diff --git a/.asf.yaml b/.asf.yaml
index 581a611dc9..bb5d874a3f 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -28,8 +28,7 @@ github:
   del_branch_on_merge: true
   #labels:
   enabled_merge_buttons:
-     # TODO: disable it after common merged
-    merge:  true
+    merge:  false
     rebase: true
     squash: true
   protected_branches:
@@ -42,7 +41,8 @@ github:
           - Analyze (java)
           - CodeQL
           - check-license
-          - build (memory, 11)
+          - build-server (memory, 11)
+          - build-commons (11)
       required_pull_request_reviews:
         dismiss_stale_reviews: true
         require_code_owner_reviews: false
diff --git a/.gitattributes b/.gitattributes
index ca5e57db70..85f64d198b 100755
--- a/.gitattributes
+++ b/.gitattributes
@@ -12,4 +12,5 @@ hugegraph-store/hg-store-dist/src/assembly/static/bin/libjemalloc_aarch64.so exp
 .github/ export-ignore
 .idea/ export-ignore
 install-dist/scripts/ export-ignore
+hugegraph-commons/hugegraph-dist/ export-ignore
 docker/ export-ignore
diff --git a/.github/workflows/check-dependencies.yml b/.github/workflows/check-dependencies.yml
index 6e3c572889..68f8c0e0c9 100644
--- a/.github/workflows/check-dependencies.yml
+++ b/.github/workflows/check-dependencies.yml
@@ -32,7 +32,7 @@ jobs:
 
       - name: mvn install
         run: |
-          mvn install -DskipTests=true -ntp
+          mvn install -Dmaven.test.skip=true -ntp
       - name: generate current dependencies
         run: |
           bash $SCRIPT_DEPENDENCY/regenerate_known_dependencies.sh current-dependencies.txt
diff --git a/.github/workflows/commons-ci.yml b/.github/workflows/commons-ci.yml
new file mode 100644
index 0000000000..7b781dd4a5
--- /dev/null
+++ b/.github/workflows/commons-ci.yml
@@ -0,0 +1,64 @@
+name: "HugeGraph-Commons CI"
+
+on:
+  workflow_dispatch:
+  push:
+    branches:
+      - master
+      - /^release-.*$/
+      - /^test-.*$/
+  pull_request:
+
+jobs:
+  build-commons:
+    runs-on: ubuntu-latest
+    env:
+      # TODO: reset use stage to false later
+      USE_STAGE: 'true' # Whether to include the stage repository.
+
+    strategy:
+      fail-fast: false
+      matrix:
+        JAVA_VERSION: ['11']
+
+    steps:
+      - name: Install JDK ${{ matrix.JAVA_VERSION }}
+        uses: actions/setup-java@v3
+        with:
+          java-version: ${{ matrix.JAVA_VERSION }}
+          distribution: 'zulu'
+
+      - name: Cache Maven packages
+        uses: actions/cache@v3
+        with:
+          path: ~/.m2
+          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+          restore-keys: ${{ runner.os }}-m2
+
+      - name: Checkout
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 2
+
+      - name: Use staged maven repo settings
+        if: ${{ env.USE_STAGE == 'true' }}
+        run: |
+          cp $HOME/.m2/settings.xml /tmp/settings.xml
+          cp -vf .github/configs/settings.xml $HOME/.m2/settings.xml && cat $HOME/.m2/settings.xml
+
+      - name: Compile
+        run: |
+          mvn compile -Dmaven.javadoc.skip=true -ntp
+
+      - name: Run common test
+        run: |
+          mvn test -pl hugegraph-commons/hugegraph-common -Dtest=UnitTestSuite -DskipCommonsTests=false
+
+      - name: Run rpc test
+        run: |
+          mvn test -pl hugegraph-commons/hugegraph-rpc -Dtest=UnitTestSuite -DskipCommonsTests=false
+
+      - name: Upload coverage to Codecov
+        uses: codecov/codecov-action@v3.0.0
+        with:
+          file: target/jacoco.xml
diff --git a/.github/workflows/pd-store-ci.yml b/.github/workflows/pd-store-ci.yml
index c0f4825251..44d4456920 100644
--- a/.github/workflows/pd-store-ci.yml
+++ b/.github/workflows/pd-store-ci.yml
@@ -1,4 +1,4 @@
-name: "Graph PD & Store & Hstore CI"
+name: "HugeGraph-PD & Store & Hstore CI"
 
 on:
   push:
@@ -14,7 +14,8 @@ jobs:
     runs-on: ubuntu-latest
     env:
       # TODO: avoid duplicated env setup in pd & store
-      USE_STAGE: 'false' # Whether to include the stage repository.
+      # TODO: reset use stage to false later
+      USE_STAGE: 'true' # Whether to include the stage repository.
       # TODO: remove outdated env
       TRAVIS_DIR: hugegraph-server/hugegraph-dist/src/assembly/travis
       REPORT_DIR: target/site/jacoco
@@ -46,11 +47,11 @@ jobs:
 
       - name: Run common test
         run: |
-          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-common-test
+          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-common-test -DskipCommonsTests=true
 
       - name: Run core test
         run: |
-          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-core-test
+          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-core-test -DskipCommonsTests=true
 
       # The above tests do not require starting a PD instance.
 
@@ -64,11 +65,11 @@ jobs:
 
       - name: Run client test
         run: |
-          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-client-test
+          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-client-test -DskipCommonsTests=true
 
       - name: Run rest test
         run: |
-          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-rest-test
+          mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-rest-test -DskipCommonsTests=true
 
       - name: Upload coverage to Codecov
         uses: codecov/codecov-action@v3.0.0
@@ -79,7 +80,7 @@ jobs:
     # TODO: avoid duplicated env setup
     runs-on: ubuntu-latest
     env:
-      USE_STAGE: 'false' # Whether to include the stage repository.
+      USE_STAGE: 'true' # Whether to include the stage repository.
       # TODO: remove outdated env
       TRAVIS_DIR: hugegraph-server/hugegraph-dist/src/assembly/travis
       REPORT_DIR: target/site/jacoco
@@ -120,27 +121,27 @@ jobs:
 
       - name: Run common test
         run: |
-          mvn test -pl hugegraph-store/hg-store-test -am -P store-common-test
+          mvn test -pl hugegraph-store/hg-store-test -am -P store-common-test -DskipCommonsTests=true
 
       - name: Run client test
         run: |
-          mvn test -pl hugegraph-store/hg-store-test -am -P store-client-test
+          mvn test -pl hugegraph-store/hg-store-test -am -P store-client-test -DskipCommonsTests=true
 
       - name: Run core test
         run: |
-          mvn test -pl hugegraph-store/hg-store-test -am -P store-core-test
+          mvn test -pl hugegraph-store/hg-store-test -am -P store-core-test -DskipCommonsTests=true
 
       - name: Run rocksdb test
         run: |
-          mvn test -pl hugegraph-store/hg-store-test -am -P store-rocksdb-test 
+          mvn test -pl hugegraph-store/hg-store-test -am -P store-rocksdb-test -DskipCommonsTests=true
 
       - name: Run server test
         run: |
-          mvn test -pl hugegraph-store/hg-store-test -am -P store-server-test
+          mvn test -pl hugegraph-store/hg-store-test -am -P store-server-test -DskipCommonsTests=true
 
       - name: Run raft-core test
         run: |
-          mvn test -pl hugegraph-store/hg-store-test -am -P store-raftcore-test 
+          mvn test -pl hugegraph-store/hg-store-test -am -P store-raftcore-test -DskipCommonsTests=true
 
       - name: Upload coverage to Codecov
         uses: codecov/codecov-action@v3.0.0
diff --git a/.github/workflows/server-ci.yml b/.github/workflows/server-ci.yml
index bbf8a5eab6..d640124ff1 100644
--- a/.github/workflows/server-ci.yml
+++ b/.github/workflows/server-ci.yml
@@ -1,4 +1,4 @@
-name: "Graph Server CI"
+name: "HugeGraph-Server CI"
 
 on:
   push:
@@ -9,11 +9,12 @@ on:
   pull_request:
 
 jobs:
-  build:
+  build-server:
     # TODO: we need test & replace it to ubuntu-24.04 or ubuntu-latest
     runs-on: ubuntu-20.04
     env:
-      USE_STAGE: 'false' # Whether to include the stage repository.
+      # TODO: reset use stage to false later
+      USE_STAGE: 'true' # Whether to include the stage repository.
       TRAVIS_DIR: hugegraph-server/hugegraph-dist/src/assembly/travis
       REPORT_DIR: target/site/jacoco
       BACKEND: ${{ matrix.BACKEND }}
diff --git a/BUILDING.md b/BUILDING.md
index b7342e68d6..d4c807c748 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -6,7 +6,7 @@ Required:
 * Java 11
 * Maven 3.5+
 
-To build without executing tests: `mvn clean package -DskipTests`
+To build without executing tests: `mvn clean package -Dmaven.test.skip=true`
 
 ## Building in IDEA
 
diff --git a/hugegraph-commons/README.md b/hugegraph-commons/README.md
new file mode 100644
index 0000000000..4ec2ebb5bb
--- /dev/null
+++ b/hugegraph-commons/README.md
@@ -0,0 +1,66 @@
+# hugegraph-commons
+
+[![License](https://img.shields.io/badge/license-Apache%202-0E78BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+[![codecov](https://codecov.io/gh/hugegraph/hugegraph-common/branch/master/graph/badge.svg)](https://codecov.io/gh/hugegraph/hugegraph-common)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.hugegraph/hugegraph-common/badge.svg)](https://mvnrepository.com/artifact/org.apache.hugegraph/hugegraph-common)
+[![CodeQL](https://github.com/apache/incubator-hugegraph-commons/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/incubator-hugegraph-commons/actions/workflows/codeql-analysis.yml)
+[![hugegraph-commons ci](https://github.com/apache/incubator-hugegraph-commons/actions/workflows/ci.yml/badge.svg)](https://github.com/apache/incubator-hugegraph-commons/actions/workflows/ci.yml)
+
+
+hugegraph-commons is a common module for [HugeGraph](https://github.com/apache/hugegraph) and its peripheral components.
+hugegraph-commons encapsulates locks, configurations, events, iterators, rest and some 
+numeric or collection util classes to simplify the development of HugeGraph and its components.
+
+## Components
+
+- Lock: atomic lock, key lock, lock group and lock manger
+- Config: register and load config option with security check
+- Event: listening and notification, do something asynchronously
+- Iterator: some iterators with extra functions, map, filter, extend, etc.
+- Rest: RESTful client implemented on OkHttp, POST, PUT, GET and DELETE
+- Util: performance analyzer, version checker, numeric and Collection utils, log and exception utils, etc.
+- Rpc: rpc component for inner module communication, currently it's based on [Sofa-RPC](https://github.com/sofastack/sofa-rpc)
+
+You could use import the dependencies in `maven` like this:
+
+```xml
+  <dependency>
+       <groupId>org.apache.hugegraph</groupId>
+       <artifactId>hugegraph-common</artifactId>
+       <version>1.2.0</version>
+  </dependency>
+```
+
+## Learn More
+
+The [doc page](https://hugegraph.apache.org/docs/) contains more information about hugegraph modules.
+
+And here are links of other repositories:
+1. [hugegraph-server](https://github.com/apache/hugegraph) (graph's core component - OLTP server)
+2. [hugegraph-toolchain](https://github.com/apache/hugegraph-toolchain) (include loader/dashboard/tool/client)
+3. [hugegraph-computer](https://github.com/apache/hugegraph-computer) (graph processing system - OLAP)
+4. [hugegraph-website/doc](https://github.com/apache/hugegraph-doc) (include doc & website code)
+
+
+
+## Contributing
+
+- Welcome to contribute to HugeGraph, please see [How to Contribute](https://hugegraph.apache.org/docs/contribution-guidelines/contribute/) for more information.  
+- Note: It's recommended to use [GitHub Desktop](https://desktop.github.com/) to greatly simplify the PR and commit process.  
+- Thank you to all the people who already contributed to HugeGraph!
+
+[![contributors graph](https://contrib.rocks/image?repo=apache/hugegraph-commons)](https://github.com/apache/incubator-hugegraph-commons/graphs/contributors)
+
+## Licence
+
+Same as HugeGraph, hugegraph-commons are also licensed under [Apache 2.0](./LICENSE) License.
+
+### Contact Us
+
+---
+
+ - [GitHub Issues](https://github.com/apache/incubator-hugegraph-commons/issues): Feedback on usage issues and functional requirements (quick response)
+ - Feedback Email: [dev@hugegraph.apache.org](mailto:dev@hugegraph.apache.org) ([subscriber](https://hugegraph.apache.org/docs/contribution-guidelines/subscribe/) only)
+ - WeChat public account: Apache HugeGraph, welcome to scan this QR code to follow us.
+
+ <img src="https://raw.githubusercontent.com/apache/incubator-hugegraph-doc/master/assets/images/wechat.png" alt="QR png" width="350"/>
diff --git a/hugegraph-commons/hugegraph-common/README.md b/hugegraph-commons/hugegraph-common/README.md
new file mode 100644
index 0000000000..8614ba126b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/README.md
@@ -0,0 +1,23 @@
+# hugegraph-common
+
+[![License](https://img.shields.io/badge/license-Apache%202-0E78BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+[![Build Status](https://travis-ci.org/hugegraph/hugegraph-common.svg?branch=master)](https://travis-ci.org/hugegraph/hugegraph-common)
+[![codecov](https://codecov.io/gh/hugegraph/hugegraph-common/branch/master/graph/badge.svg)](https://codecov.io/gh/hugegraph/hugegraph-common)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.hugegraph/hugegraph-common/badge.svg)](https://mvnrepository.com/artifact/org.apache.hugegraph/hugegraph-common)
+
+hugegraph-common is a common module for [HugeGraph](https://github.com/hugegraph/hugegraph) and its peripheral components.
+hugegraph-common encapsulates locks, configurations, events, iterators, rest and some 
+numeric or collection util classes to simplify the development of HugeGraph and 
+its components.
+
+## Components
+
+- Lock: atomic lock, key lock, lock group and lock manger
+- Config: register and load config option with security check
+- Event: listening and notification, do something asynchronously
+- Iterator: some iterators with extra functions, map, filter, extend, etc.
+- Rest: RESTful client implemented on Jersey, POST, PUT, GET and DELETE
+- Util: Performance analyzer, version checker, numeric and Collection utils, log and exception utils, etc.
+
+## Licence
+The same as HugeGraph, hugegraph-common is also licensed under Apache 2.0 License.
diff --git a/hugegraph-commons/hugegraph-common/build.sh b/hugegraph-commons/hugegraph-common/build.sh
new file mode 100644
index 0000000000..b2cb6211b9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/build.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+export MAVEN_HOME=/home/scmtools/buildkit/maven/apache-maven-3.3.9/
+export JAVA_HOME=/home/scmtools/buildkit/java/jdk1.8.0_25/
+export PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH
+
+mvn clean test -Dtest=UnitTestSuite
diff --git a/hugegraph-commons/hugegraph-common/pom.xml b/hugegraph-commons/hugegraph-common/pom.xml
new file mode 100644
index 0000000000..2010869b17
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/pom.xml
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.hugegraph</groupId>
+        <artifactId>hugegraph-commons</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>hugegraph-common</artifactId>
+    <name>${project.artifactId}</name>
+    <url>https://github.com/apache/incubator-hugegraph-commons/tree/master/hugegraph-common</url>
+    <description>
+        hugegraph-common is a common module for HugeGraph and its peripheral components.
+        hugegraph-common encapsulates locks, configurations, events, iterators, rest and some
+        numeric or collection util classes to simplify the development of HugeGraph and its
+        components.
+    </description>
+
+    <properties>
+        <!-- Use parent params -->
+        <lombok.version>1.18.8</lombok.version>
+        <okhttp.version>4.10.0</okhttp.version>
+    </properties>
+
+    <dependencies>
+        <!-- Test -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>${mockito.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Logging -->
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>${log4j2.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>${log4j2.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <version>${log4j2.version}</version>
+        </dependency>
+
+        <!-- Utility -->
+        <dependency>
+            <groupId>org.glassfish</groupId>
+            <artifactId>javax.json</artifactId>
+            <version>${javax.json.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+            <version>${commons.configuration.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-configuration2</artifactId>
+            <version>${commons.configuration2.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-logging</artifactId>
+                    <groupId>commons-logging</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>commons-lang3</artifactId>
+                    <groupId>org.apache.commons</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons.lang3.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>${commons.beanutils.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-logging</artifactId>
+                    <groupId>commons-logging</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons.io.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>${commons.collections.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>${commons.codec.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>${guava.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jsr305</artifactId>
+                    <groupId>com.google.code.findbugs</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>${jsr305.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+            <version>2.10.8</version>
+        </dependency>
+
+        <!-- javassist -->
+        <dependency>
+            <groupId>org.javassist</groupId>
+            <artifactId>javassist</artifactId>
+            <version>${javassist.version}</version>
+        </dependency>
+
+        <!-- jackson -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-jaxb-annotations</artifactId>
+            <version>${jackson.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                    <groupId>jakarta.xml.bind</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-base</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-impl</artifactId>
+            <version>${sun.xml.version}</version>
+            <scope>runtime</scope>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                    <groupId>jakarta.xml.bind</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>logging-interceptor</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.squareup.okhttp3</groupId>
+                <artifactId>okhttp-bom</artifactId>
+                <version>${okhttp.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>0.8.2</version>
+                <executions>
+                    <execution>
+                        <id>pre-unit-test</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>post-unit-test</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.parent.build.directory}</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>apache-release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-source-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/AtomicLock.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/AtomicLock.java
new file mode 100644
index 0000000000..6f7a669d7d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/AtomicLock.java
@@ -0,0 +1,82 @@
+/*
+ * 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.hugegraph.concurrent;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+public class AtomicLock {
+
+    private static final Logger LOG = Log.logger(LockManager.class);
+
+    private String name;
+    private AtomicReference<Thread> sign;
+
+    public AtomicLock(String name) {
+        this.name = name;
+        this.sign = new AtomicReference<>();
+    }
+
+    public boolean tryLock() {
+        Thread current = Thread.currentThread();
+        return this.sign.compareAndSet(null, current);
+    }
+
+    public void unlock() {
+        if (this.sign.get() == null) {
+            return;
+        }
+        Thread current = Thread.currentThread();
+        if (!this.sign.compareAndSet(current, null)) {
+            throw new RuntimeException(String.format(
+                      "Thread '%s' trying to unlock '%s' " +
+                      "which is held by other threads now.",
+                      current.getName(), this.name));
+        }
+    }
+
+    public boolean lock(int retries) {
+        // The interval between retries is exponential growth, most wait
+        // interval is 2^(retries-1)s. If retries=0, don't retry.
+        if (retries < 0 || retries > 10) {
+            throw new IllegalArgumentException(String.format(
+                      "Locking retry times should be in [0, 10], but got %d",
+                      retries));
+        }
+
+        boolean isLocked = false;
+        try {
+            for (int i = 0; !(isLocked = this.tryLock()) && i < retries; i++) {
+                Thread.sleep(1000 * (1L << i));
+            }
+        } catch (InterruptedException ignored) {
+            LOG.info("Thread sleep is interrupted.");
+        }
+        return isLocked;
+    }
+
+    public String name() {
+        return this.name;
+    }
+
+    public void name(String name) {
+        this.name = name;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/BarrierEvent.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/BarrierEvent.java
new file mode 100644
index 0000000000..3c8734d16d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/BarrierEvent.java
@@ -0,0 +1,104 @@
+/*
+ * 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.hugegraph.concurrent;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.hugegraph.util.E;
+
+public class BarrierEvent {
+
+    private final Lock lock = new ReentrantLock();
+    private final Condition cond = lock.newCondition();
+    private volatile boolean signaled = false;
+
+    /**
+     * Wait forever until the signal is received.
+     * @throws InterruptedException if interrupted.
+     */
+    public void await() throws InterruptedException {
+        this.lock.lock();
+        try {
+            while (!this.signaled) {
+                this.cond.await();
+            }
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    /**
+     * Wait specified time in milliseconds.
+     * @param timeout: the time in millisecond to wait.
+     * @return true if signal is received, false if time out.
+     * @throws InterruptedException if interrupted.
+     */
+    public boolean await(long timeout) throws InterruptedException {
+        E.checkArgument(timeout >= 0L,
+                        "The time must be >= 0, but got '%d'.",
+                        timeout);
+        long deadline = System.currentTimeMillis() + timeout;
+        this.lock.lock();
+        try {
+            while (!this.signaled) {
+                timeout = deadline - System.currentTimeMillis();
+                if (timeout > 0) {
+                    this.cond.await(timeout, TimeUnit.MILLISECONDS);
+                }
+                if (System.currentTimeMillis() >= deadline) {
+                    return this.signaled;
+                }
+            }
+        } finally {
+            this.lock.unlock();
+        }
+        return true;
+    }
+
+    public void reset() {
+        this.lock.lock();
+        try {
+            this.signaled = false;
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public void signal() {
+        this.lock.lock();
+        try {
+            this.signaled = true;
+            this.cond.signal();
+        } finally {
+            this.lock.unlock();
+        }
+    }
+
+    public void signalAll() {
+        this.lock.lock();
+        try {
+            this.signaled = true;
+            this.cond.signalAll();
+        } finally {
+            this.lock.unlock();
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/KeyLock.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/KeyLock.java
new file mode 100644
index 0000000000..44ca8803ca
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/KeyLock.java
@@ -0,0 +1,144 @@
+/*
+ * 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.hugegraph.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.locks.Lock;
+
+import org.apache.hugegraph.util.E;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Striped;
+
+/**
+ * KeyLock provide an interface of segment lock
+ */
+public class KeyLock {
+
+    private Striped<Lock> locks;
+
+    public KeyLock() {
+        // The default size is availableProcessors() * 4
+        this(Runtime.getRuntime().availableProcessors() << 2);
+    }
+
+    public KeyLock(int size) {
+        this.locks = Striped.lock(size);
+    }
+
+    private int indexOf(Lock lock) {
+        for (int i = 0; i < this.locks.size(); i++) {
+            if (this.locks.getAt(i) == lock) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Lock an object
+     * @param key The object to lock
+     * @return The lock(locked) of passed key
+     */
+    public final Lock lock(Object key) {
+        E.checkArgument(key != null, "Lock key can't be null");
+        Lock lock = this.locks.get(key);
+        lock.lock();
+        return lock;
+    }
+
+    /**
+     * Unlock an object
+     * @param key The object to unlock
+     */
+    public final void unlock(Object key) {
+        E.checkArgument(key != null, "Unlock key can't be null");
+        this.locks.get(key).unlock();
+    }
+
+    /**
+     * Lock a list of object with sorted order
+     * @param keys The objects to lock
+     * @return The locks(locked) of keys
+     */
+    public final List<Lock> lockAll(Object... keys) {
+        E.checkArgument(keys != null && keys.length > 0,
+                        "Lock keys can't be null or empty");
+        List<Lock> locks = new ArrayList<>(keys.length);
+        for (Object key : keys) {
+            E.checkArgument(key != null, "Lock key can't be null");
+            Lock lock = this.locks.get(key);
+            locks.add(lock);
+        }
+        locks.sort((a, b) -> {
+            int diff = a.hashCode() - b.hashCode();
+            if (diff == 0 && a != b) {
+                diff = this.indexOf(a) - this.indexOf(b);
+                assert diff != 0;
+            }
+            return diff;
+        });
+        for (Lock lock : locks) {
+            lock.lock();
+        }
+        return Collections.unmodifiableList(locks);
+    }
+
+    /**
+     * Lock two objects with sorted order
+     * NOTE: This is to optimize the performance of lockAll(keys)
+     * @param key1  The first object
+     * @param key2  The second object
+     * @return      locks for the two objects
+     */
+    public List<Lock> lockAll(Object key1, Object key2) {
+        E.checkArgument(key1 != null, "Lock key can't be null");
+        E.checkArgument(key2 != null, "Lock key can't be null");
+        Lock lock1 = this.locks.get(key1);
+        Lock lock2 = this.locks.get(key2);
+
+        int diff = lock1.hashCode() - lock2.hashCode();
+        if (diff == 0 && lock1 != lock2) {
+            diff = this.indexOf(lock1) - this.indexOf(lock2);
+            assert diff != 0;
+        }
+
+        List<Lock> locks = diff > 0 ?
+                           ImmutableList.of(lock2, lock1) :
+                           ImmutableList.of(lock1, lock2);
+
+        for (Lock lock : locks) {
+            lock.lock();
+        }
+
+        return locks;
+    }
+
+    /**
+     * Unlock a list of object
+     * @param locks The locks to unlock
+     */
+    public final void unlockAll(List<Lock> locks) {
+        E.checkArgument(locks != null, "Unlock locks can't be null");
+        for (int i = locks.size(); i > 0; i--) {
+            assert this.indexOf(locks.get(i - 1)) != -1;
+            locks.get(i - 1).unlock();
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/LockGroup.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/LockGroup.java
new file mode 100644
index 0000000000..aa864ecaf8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/LockGroup.java
@@ -0,0 +1,85 @@
+/*
+ * 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.hugegraph.concurrent;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class LockGroup {
+
+    private final String name;
+    private final Map<String, Object> locksMap;
+
+    public LockGroup(String lockGroup) {
+        this.name = lockGroup;
+        this.locksMap = new ConcurrentHashMap<>();
+    }
+
+    public Lock lock(String lockName) {
+        if (!this.locksMap.containsKey(lockName)) {
+            this.locksMap.putIfAbsent(lockName, new ReentrantLock());
+        }
+        return (Lock) this.locksMap.get(lockName);
+    }
+
+    public AtomicLock atomicLock(String lockName) {
+        if (!this.locksMap.containsKey(lockName)) {
+            this.locksMap.putIfAbsent(lockName, new AtomicLock(lockName));
+        }
+        return (AtomicLock) this.locksMap.get(lockName);
+    }
+
+    public ReadWriteLock readWriteLock(String lockName) {
+        if (!this.locksMap.containsKey(lockName)) {
+            this.locksMap.putIfAbsent(lockName, new ReentrantReadWriteLock());
+        }
+        return (ReadWriteLock) this.locksMap.get(lockName);
+    }
+
+    public KeyLock keyLock(String lockName) {
+        if (!this.locksMap.containsKey(lockName)) {
+            this.locksMap.putIfAbsent(lockName, new KeyLock());
+        }
+        return (KeyLock) this.locksMap.get(lockName);
+    }
+
+    public KeyLock keyLock(String lockName, int size) {
+        if (!this.locksMap.containsKey(lockName)) {
+            this.locksMap.putIfAbsent(lockName, new KeyLock(size));
+        }
+        return (KeyLock) this.locksMap.get(lockName);
+    }
+
+    public <K extends Comparable<K>> RowLock<K> rowLock(String lockName) {
+        if (!this.locksMap.containsKey(lockName)) {
+            this.locksMap.putIfAbsent(lockName, new RowLock<>());
+        }
+        Object value = this.locksMap.get(lockName);
+        @SuppressWarnings("unchecked")
+        RowLock<K> lock = (RowLock<K>) value;
+        return lock;
+    }
+
+    public String name() {
+        return this.name;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/LockManager.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/LockManager.java
new file mode 100644
index 0000000000..e686c67895
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/LockManager.java
@@ -0,0 +1,71 @@
+/*
+ * 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.hugegraph.concurrent;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class LockManager {
+
+    private static final LockManager INSTANCE = new LockManager();
+
+    public static LockManager instance() {
+        return INSTANCE;
+    }
+
+    private Map<String, LockGroup> lockGroupMap;
+
+    private LockManager() {
+        this.lockGroupMap = new ConcurrentHashMap<>();
+    }
+
+    public boolean exists(String group) {
+        return this.lockGroupMap.containsKey(group);
+    }
+
+    public LockGroup create(String group) {
+        if (exists(group)) {
+            throw new RuntimeException(String.format(
+                      "LockGroup '%s' already exists", group));
+        }
+        LockGroup lockGroup = new LockGroup(group);
+        LockGroup previous = this.lockGroupMap.putIfAbsent(group, lockGroup);
+        if (previous != null) {
+            return previous;
+        }
+        return lockGroup;
+    }
+
+    public LockGroup get(String group) {
+        LockGroup lockGroup = this.lockGroupMap.get(group);
+        if (lockGroup == null) {
+            throw new RuntimeException(String.format(
+                      "LockGroup '%s' does not exists", group));
+        }
+        return lockGroup;
+    }
+
+    public void destroy(String group) {
+        if (this.exists(group)) {
+            this.lockGroupMap.remove(group);
+        } else {
+            throw new RuntimeException(String.format(
+                      "LockGroup '%s' does not exists", group));
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/PausableScheduledThreadPool.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/PausableScheduledThreadPool.java
new file mode 100644
index 0000000000..a820aeb638
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/PausableScheduledThreadPool.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hugegraph.concurrent;
+
+import java.util.List;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+public class PausableScheduledThreadPool extends ScheduledThreadPoolExecutor {
+
+    private static final Logger LOG = Log.logger(PausableScheduledThreadPool.class);
+
+    private volatile boolean paused = false;
+
+    public PausableScheduledThreadPool(int corePoolSize,
+                                       ThreadFactory factory) {
+        super(corePoolSize, factory);
+    }
+
+    public synchronized void pauseSchedule() {
+        this.paused = true;
+        LOG.info("PausableScheduledThreadPool was paused");
+    }
+
+    public synchronized void resumeSchedule() {
+        this.paused = false;
+        this.notifyAll();
+        LOG.info("PausableScheduledThreadPool was resumed");
+    }
+
+    @Override
+    protected void beforeExecute(Thread t, Runnable r) {
+        synchronized (this) {
+            while (this.paused) {
+                try {
+                    this.wait();
+                } catch (InterruptedException e) {
+                    LOG.warn("PausableScheduledThreadPool was interrupted");
+                }
+            }
+        }
+        super.beforeExecute(t, r);
+    }
+
+    @Override
+    public void shutdown() {
+        if (this.paused) {
+            this.resumeSchedule();
+        }
+        super.shutdown();
+    }
+
+    @Override
+    public List<Runnable> shutdownNow() {
+        if (this.paused) {
+            this.resumeSchedule();
+        }
+        return super.shutdownNow();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/RowLock.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/RowLock.java
new file mode 100644
index 0000000000..3908803771
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/concurrent/RowLock.java
@@ -0,0 +1,98 @@
+/*
+ * 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.hugegraph.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.hugegraph.util.E;
+
+public class RowLock<K extends Comparable<K>> {
+
+    private final Map<K, Lock> locks = new ConcurrentHashMap<>();
+    private final ThreadLocal<Map<K, LocalLock>> localLocks =
+                  ThreadLocal.withInitial(HashMap::new);
+
+    public void lock(K key) {
+        E.checkArgument(key != null, "Lock key can't be null");
+        LocalLock localLock = this.localLocks.get().get(key);
+        if (localLock != null) {
+            localLock.lockCount++;
+        } else {
+            Lock current = new ReentrantLock();
+            Lock previous = this.locks.putIfAbsent(key, current);
+            if (previous != null) {
+                current = previous;
+            }
+            current.lock();
+            this.localLocks.get().put(key, new LocalLock(current));
+        }
+    }
+
+    public void unlock(K key) {
+        E.checkArgument(key != null, "Unlock key can't be null");
+        LocalLock localLock = this.localLocks.get().get(key);
+        if (localLock == null) {
+            return;
+        }
+        if (--localLock.lockCount == 0) {
+            this.locks.remove(key, localLock.current);
+            this.localLocks.get().remove(key);
+            localLock.current.unlock();
+        }
+        E.checkState(localLock.lockCount >= 0,
+                     "The lock count must be >= 0, but got %s",
+                     localLock.lockCount);
+    }
+
+    public void lockAll(Set<K> keys) {
+        E.checkArgument(keys != null && keys.size() > 0,
+                        "Lock keys can't be null or empty");
+        List<K> list = new ArrayList<>(keys);
+        Collections.sort(list);
+        for (K key : list) {
+            this.lock(key);
+        }
+    }
+
+    public void unlockAll(Set<K> keys) {
+        E.checkArgument(keys != null && keys.size() > 0,
+                        "Unlock keys can't be null or empty");
+        for (K key : keys) {
+            this.unlock(key);
+        }
+    }
+
+    private static class LocalLock {
+
+        private final Lock current;
+        private int lockCount;
+
+        private LocalLock(Lock current) {
+            this.current = current;
+            this.lockCount = 1;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigConvOption.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigConvOption.java
new file mode 100644
index 0000000000..bb794ec48b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigConvOption.java
@@ -0,0 +1,47 @@
+/*
+ * 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.hugegraph.config;
+
+import java.util.function.Function;
+
+import org.apache.hugegraph.util.E;
+import com.google.common.base.Predicate;
+
+public class ConfigConvOption<T, R> extends TypedOption<T, R> {
+
+    private final Function<T, R> converter;
+
+    public ConfigConvOption(String name, String desc, Predicate<T> pred,
+                            Function<T, R> convert, T value) {
+        this(name, false, desc, pred, convert, value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public ConfigConvOption(String name, boolean required, String desc,
+                            Predicate<T> pred, Function<T, R> convert,
+                            T value) {
+        super(name, required, desc, pred, (Class<T>) value.getClass(), value);
+        E.checkNotNull(convert, "convert");
+        this.converter = convert;
+    }
+
+    @Override
+    public R convert(T value) {
+        return this.converter.apply(value);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigException.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigException.java
new file mode 100644
index 0000000000..51ba0c2f55
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hugegraph.config;
+
+public class ConfigException extends RuntimeException {
+
+    private static final long serialVersionUID = -8711375282196157058L;
+
+    public ConfigException(String message) {
+        super(message);
+    }
+
+    public ConfigException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ConfigException(String message, Object... args) {
+        super(String.format(message, args));
+    }
+
+    public ConfigException(String message, Throwable cause, Object... args) {
+        super(String.format(message, args), cause);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigListConvOption.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigListConvOption.java
new file mode 100644
index 0000000000..79996c3680
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigListConvOption.java
@@ -0,0 +1,75 @@
+/*
+ * 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.hugegraph.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+
+import org.apache.hugegraph.util.E;
+import com.google.common.base.Predicate;
+
+public class ConfigListConvOption<T, R> extends TypedOption<List<T>, List<R>> {
+
+    private final Class<T> elemClass;
+    private final Function<T, R> converter;
+
+    @SuppressWarnings("unchecked")
+    public ConfigListConvOption(String name, String desc,
+                                Predicate<List<T>> pred, Function<T, R> convert,
+                                T... values) {
+        this(name, false, desc, pred, convert, null, Arrays.asList(values));
+    }
+
+    @SuppressWarnings("unchecked")
+    public ConfigListConvOption(String name, boolean required, String desc,
+                                Predicate<List<T>> pred, Function<T, R> convert,
+                                Class<T> clazz, List<T> values) {
+        super(name, required, desc, pred,
+              (Class<List<T>>) values.getClass(), values);
+        E.checkNotNull(convert, "convert");
+        if (clazz == null && values.size() > 0) {
+            clazz = (Class<T>) values.get(0).getClass();
+        }
+        E.checkArgumentNotNull(clazz, "Element class can't be null");
+        this.elemClass = clazz;
+        this.converter = convert;
+    }
+
+    @Override
+    protected boolean forList() {
+        return true;
+    }
+
+    @Override
+    protected List<T> parse(String value) {
+        return ConfigListOption.convert(value, part -> {
+            return this.parse(part, this.elemClass);
+        });
+    }
+
+    @Override
+    public List<R> convert(List<T> values) {
+        List<R> results = new ArrayList<>(values.size());
+        for (T value : values) {
+            results.add(this.converter.apply(value));
+        }
+        return results;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigListOption.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigListOption.java
new file mode 100644
index 0000000000..0a41e3b7e4
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigListOption.java
@@ -0,0 +1,79 @@
+/*
+ * 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.hugegraph.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+
+import org.apache.hugegraph.util.E;
+import com.google.common.base.Predicate;
+
+public class ConfigListOption<T> extends ConfigOption<List<T>> {
+
+    private final Class<T> elemClass;
+
+    @SuppressWarnings("unchecked")
+    public ConfigListOption(String name, String desc,
+                            Predicate<List<T>> pred, T... values) {
+        this(name, false, desc, pred, null, Arrays.asList(values));
+    }
+
+    @SuppressWarnings("unchecked")
+    public ConfigListOption(String name, boolean required, String desc,
+                            Predicate<List<T>> pred, Class<T> clazz,
+                            List<T> values) {
+        super(name, required, desc, pred,
+              (Class<List<T>>) values.getClass(), values);
+        if (clazz == null && values.size() > 0) {
+            clazz = (Class<T>) values.get(0).getClass();
+        }
+        E.checkArgumentNotNull(clazz, "Element class can't be null");
+        this.elemClass = clazz;
+    }
+
+    @Override
+    protected boolean forList() {
+        return true;
+    }
+
+    @Override
+    protected List<T> parse(String value) {
+        return convert(value, part -> this.parse(part, this.elemClass));
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> List<T> convert(Object value, Function<String, ?> conv) {
+        if (value instanceof List) {
+            return (List<T>) value;
+        }
+        // If target data type is List, parse it as a list
+        String str = (String) value;
+        if (str.startsWith("[") && str.endsWith("]")) {
+            str = str.substring(1, str.length() - 1);
+        }
+
+        String[] parts = str.split(",");
+        List<T> results = new ArrayList<>(parts.length);
+        for (String part : parts) {
+            results.add((T) conv.apply(part.trim()));
+        }
+        return results;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigOption.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigOption.java
new file mode 100644
index 0000000000..159f13901f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/ConfigOption.java
@@ -0,0 +1,37 @@
+/*
+ * 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.hugegraph.config;
+
+import com.google.common.base.Predicate;
+
+public class ConfigOption<T> extends TypedOption<T, T> {
+
+    public ConfigOption(String name, String desc, T value) {
+        this(name, desc, null, value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public ConfigOption(String name, String desc, Predicate<T> pred, T value) {
+        this(name, false, desc, pred, (Class<T>) value.getClass(), value);
+    }
+
+    public ConfigOption(String name, boolean required, String desc,
+                        Predicate<T> pred, Class<T> type, T value) {
+        super(name, required, desc, pred, type, value);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/HugeConfig.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/HugeConfig.java
new file mode 100644
index 0000000000..4837154563
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/HugeConfig.java
@@ -0,0 +1,216 @@
+/*
+ * 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.hugegraph.config;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.FileBasedConfiguration;
+import org.apache.commons.configuration2.PropertiesConfiguration;
+import org.apache.commons.configuration2.YAMLConfiguration;
+import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
+import org.apache.commons.configuration2.builder.fluent.Configurations;
+import org.apache.commons.configuration2.builder.fluent.Parameters;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.commons.configuration2.io.FileHandler;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+public class HugeConfig extends PropertiesConfiguration {
+
+    private static final Logger LOG = Log.logger(HugeConfig.class);
+
+    private String configPath;
+
+    public HugeConfig(Configuration config) {
+        loadConfig(config);
+        this.configPath = null;
+    }
+
+    public HugeConfig(String configFile) {
+        loadConfig(loadConfigFile(configFile));
+        this.configPath = configFile;
+    }
+
+    public HugeConfig(Map<String, Object> propertyMap) {
+        if (propertyMap == null) {
+            throw new ConfigException("The property map is null");
+        }
+
+        for (Map.Entry<String, Object> kv : propertyMap.entrySet()) {
+            this.addProperty(kv.getKey(), kv.getValue());
+        }
+        this.checkRequiredOptions();
+    }
+
+    private void loadConfig(Configuration config) {
+        if (config == null) {
+            throw new ConfigException("The config object is null");
+        }
+        this.setLayoutIfNeeded(config);
+
+        this.append(config);
+        this.checkRequiredOptions();
+    }
+
+    private void setLayoutIfNeeded(Configuration conf) {
+        if (!(conf instanceof PropertiesConfiguration)) {
+            return;
+        }
+        PropertiesConfiguration propConf = (PropertiesConfiguration) conf;
+        this.setLayout(propConf.getLayout());
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T, R> R get(TypedOption<T, R> option) {
+        Object value = this.getProperty(option.name());
+        if (value == null) {
+            return option.defaultValue();
+        }
+        return (R) value;
+    }
+
+    public Map<String, String> getMap(ConfigListOption<String> option) {
+        List<String> values = this.get(option);
+        Map<String, String> result = new HashMap<>();
+        for (String value : values) {
+            String[] pair = value.split(":", 2);
+            E.checkState(pair.length == 2,
+                         "Invalid option format for '%s': %s(expect KEY:VALUE)",
+                         option.name(), value);
+            result.put(pair[0].trim(), pair[1].trim());
+        }
+        return result;
+    }
+
+    @Override
+    public void addPropertyDirect(String key, Object value) {
+        TypedOption<?, ?> option = OptionSpace.get(key);
+        if (option == null) {
+            LOG.warn("The config option '{}' is redundant, " +
+                     "please ensure it has been registered", key);
+        } else {
+            // The input value is String(parsed by PropertiesConfiguration)
+            value = this.validateOption(key, value);
+        }
+        if (this.containsKey(key) && value instanceof List) {
+            for (Object item : (List<?>) value) {
+                super.addPropertyDirect(key, item);
+            }
+        } else {
+            super.addPropertyDirect(key, value);
+        }
+    }
+
+    @Override
+    protected void addPropertyInternal(String key, Object value) {
+        this.addPropertyDirect(key, value);
+    }
+
+    private Object validateOption(String key, Object value) {
+        TypedOption<?, ?> option = OptionSpace.get(key);
+
+        if (value instanceof String) {
+            return option.parseConvert((String) value);
+        }
+
+        Class<?> dataType = option.dataType();
+        if (dataType.isInstance(value)) {
+            return value;
+        }
+
+        throw new IllegalArgumentException(
+              String.format("Invalid value for key '%s': '%s'", key, value));
+    }
+
+    private void checkRequiredOptions() {
+        // TODO: Check required options must be contained in this map
+    }
+
+    public void save(File copiedFile) throws ConfigurationException {
+        FileHandler fileHandler = new FileHandler(this);
+        fileHandler.save(copiedFile);
+    }
+
+    @Nullable
+    public File file() {
+        if (StringUtils.isEmpty(this.configPath)) {
+            return null;
+        }
+
+        return new File(this.configPath);
+    }
+
+    public void file(String path) {
+        this.configPath = path;
+    }
+
+    private static Configuration loadConfigFile(String path) {
+        E.checkNotNull(path, "config path");
+        E.checkArgument(!path.isEmpty(),
+                        "The config path can't be empty");
+
+        File file = new File(path);
+        return loadConfigFile(file);
+    }
+
+    private static Configuration loadConfigFile(File configFile) {
+        E.checkArgument(configFile.exists() &&
+                        configFile.isFile() &&
+                        configFile.canRead(),
+                        "Please specify a proper config file rather than: '%s'",
+                        configFile.toString());
+
+        try {
+            String fileName = configFile.getName();
+            String fileExtension = FilenameUtils.getExtension(fileName);
+
+            Configuration config;
+            Configurations configs = new Configurations();
+
+            switch (fileExtension) {
+                case "yml":
+                case "yaml":
+                    Parameters params = new Parameters();
+                    FileBasedConfigurationBuilder<FileBasedConfiguration> builder =
+                            new FileBasedConfigurationBuilder(YAMLConfiguration.class)
+                                    .configure(params.fileBased().setFile(configFile));
+                    config = builder.getConfiguration();
+                    break;
+                case "xml":
+                    config = configs.xml(configFile);
+                    break;
+                default:
+                    config = configs.properties(configFile);
+                    break;
+            }
+            return config;
+        } catch (ConfigurationException e) {
+            throw new ConfigException("Unable to load config: '%s'",
+                                      e, configFile);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionChecker.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionChecker.java
new file mode 100644
index 0000000000..77364e1789
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionChecker.java
@@ -0,0 +1,83 @@
+/*
+ * 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.hugegraph.config;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.common.base.Predicate;
+
+public final class OptionChecker {
+
+    public static <O> Predicate<O> disallowEmpty() {
+        return o -> {
+            if (o == null) {
+                return false;
+            }
+            if (o instanceof String) {
+                return StringUtils.isNotBlank((String) o);
+            }
+            if (o.getClass().isArray() && (Array.getLength(o) == 0)) {
+                return false;
+            }
+            return !(o instanceof Iterable) || ((Iterable<?>) o).iterator().hasNext();
+        };
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <O> Predicate<O> allowValues(O... values) {
+        return o -> o != null && Arrays.asList(values).contains(o);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <O> Predicate<List<O>> inValues(O... values) {
+        return o -> o != null && new HashSet<>(Arrays.asList(values)).containsAll(o);
+    }
+
+    public static <N extends Number> Predicate<N> positiveInt() {
+        return number -> number != null && number.longValue() > 0;
+    }
+
+    public static <N extends Number> Predicate<N> nonNegativeInt() {
+        return number -> number != null && number.longValue() >= 0;
+    }
+
+    public static <N extends Number> Predicate<N> rangeInt(N min, N max) {
+        return number -> {
+            if (number == null) {
+                return false;
+            }
+            long value = number.longValue();
+            return value >= min.longValue() && value <= max.longValue();
+        };
+    }
+
+    public static <N extends Number> Predicate<N> rangeDouble(N min, N max) {
+        return number -> {
+            if (number == null) {
+                return false;
+            }
+            double value = number.doubleValue();
+            return value >= min.doubleValue() && value <= max.doubleValue();
+        };
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionHolder.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionHolder.java
new file mode 100644
index 0000000000..8f4ddca764
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionHolder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.hugegraph.config;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+public class OptionHolder {
+
+    private static final Logger LOG = Log.logger(HugeConfig.class);
+
+    protected Map<String, TypedOption<?, ?>> options;
+
+    public OptionHolder() {
+        this.options = new HashMap<>();
+    }
+
+    protected void registerOptions() {
+        for (Field field : this.getClass().getFields()) {
+            if (!TypedOption.class.isAssignableFrom(field.getType())) {
+                // Skip if not option
+                continue;
+            }
+            try {
+                TypedOption<?, ?> option = (TypedOption<?, ?>) field.get(this);
+                // Fields of subclass first, don't overwrite by superclass
+                this.options.putIfAbsent(option.name(), option);
+            } catch (Exception e) {
+                LOG.error("Failed to register option: {}", field, e);
+                throw new ConfigException(
+                          "Failed to register option: %s", field);
+            }
+        }
+    }
+
+    public Map<String, TypedOption<?, ?>> options() {
+        return Collections.unmodifiableMap(this.options);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionSpace.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionSpace.java
new file mode 100644
index 0000000000..7193d23deb
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/OptionSpace.java
@@ -0,0 +1,120 @@
+/*
+ * 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.hugegraph.config;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+public final class OptionSpace {
+
+    private static final Logger LOG = Log.logger(OptionSpace.class);
+
+    private static final Map<String, Class<? extends OptionHolder>> HOLDERS;
+    private static final Map<String, TypedOption<?, ?>> OPTIONS;
+    private static final String INSTANCE_METHOD = "instance";
+
+    static {
+        HOLDERS = new ConcurrentHashMap<>();
+        OPTIONS = new ConcurrentHashMap<>();
+    }
+
+    public static void register(String module, String holder) {
+        ClassLoader classLoader = OptionSpace.class.getClassLoader();
+        Class<?> clazz;
+        try {
+            clazz = classLoader.loadClass(holder);
+        } catch (ClassNotFoundException e) {
+            throw new ConfigException(
+                      "Failed to load class of option holder '%s'", e, holder);
+        }
+
+        // Check subclass
+        if (!OptionHolder.class.isAssignableFrom(clazz)) {
+            throw new ConfigException(
+                      "Class '%s' is not a subclass of OptionHolder", holder);
+        }
+
+        OptionHolder instance = null;
+        Exception exception = null;
+        try {
+            Method method = clazz.getMethod(INSTANCE_METHOD);
+            if (!Modifier.isStatic(method.getModifiers())) {
+                throw new NoSuchMethodException(INSTANCE_METHOD);
+            }
+            instance = (OptionHolder) method.invoke(null);
+            if (instance == null) {
+                exception = new ConfigException(
+                                "Returned null from %s() method",
+                                INSTANCE_METHOD);
+            }
+        } catch (NoSuchMethodException e) {
+            LOG.warn("Class {} does not has static method {}.",
+                     holder, INSTANCE_METHOD);
+            exception = e;
+        } catch (InvocationTargetException e) {
+            LOG.warn("Can't call static method {} from class {}.",
+                     INSTANCE_METHOD, holder);
+            exception = e;
+        } catch (IllegalAccessException e) {
+            LOG.warn("Illegal access while calling method {} from class {}.",
+                     INSTANCE_METHOD, holder);
+            exception = e;
+        }
+
+        if (exception != null) {
+            throw new ConfigException("Failed to instantiate option holder: %s",
+                                      exception, holder);
+        }
+
+        register(module, instance);
+    }
+
+    public static void register(String module, OptionHolder holder) {
+        // Check exists
+        if (HOLDERS.containsKey(module)) {
+            LOG.warn("Already registered option holder: {} ({})",
+                     module, HOLDERS.get(module));
+        }
+        E.checkArgumentNotNull(holder, "OptionHolder can't be null");
+        HOLDERS.put(module, holder.getClass());
+        OPTIONS.putAll(holder.options());
+        LOG.debug("Registered options for OptionHolder: {}",
+                  holder.getClass().getSimpleName());
+    }
+
+    public static Set<String> keys() {
+        return Collections.unmodifiableSet(OPTIONS.keySet());
+    }
+
+    public static boolean containKey(String key) {
+        return OPTIONS.containsKey(key);
+    }
+
+    public static TypedOption<?, ?> get(String key) {
+        return OPTIONS.get(key);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/TypedOption.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/TypedOption.java
new file mode 100644
index 0000000000..fc2c7de2ff
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/config/TypedOption.java
@@ -0,0 +1,194 @@
+/*
+ * 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.hugegraph.config;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.Log;
+import org.apache.commons.configuration.PropertyConverter;
+import org.slf4j.Logger;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+
+public class TypedOption<T, R> {
+
+    private static final Logger LOG = Log.logger(TypedOption.class);
+
+    private static final Set<Class<?>> ACCEPTED_DATA_TYPES;
+    private static final String ACCEPTED_DATA_TYPES_STRING;
+
+    static {
+        ACCEPTED_DATA_TYPES = ImmutableSet.of(
+                Boolean.class,
+                Short.class,
+                Integer.class,
+                Byte.class,
+                Long.class,
+                Float.class,
+                Double.class,
+                String.class,
+                String[].class,
+                Class.class,
+                List.class
+        );
+
+        ACCEPTED_DATA_TYPES_STRING = Joiner.on(", ").join(ACCEPTED_DATA_TYPES);
+    }
+
+    private final String name;
+    private final String desc;
+    private final boolean required;
+    private final Class<T> dataType;
+    private final T defaultValue;
+    private final Predicate<T> checkFunc;
+
+    @SuppressWarnings("unchecked")
+    public TypedOption(String name, boolean required, String desc,
+                       Predicate<T> pred, Class<T> type, T value) {
+        E.checkNotNull(name, "name");
+        E.checkNotNull(type, "dataType");
+
+        this.name = name;
+        this.dataType = (Class<T>) this.checkAndAssignDataType(type);
+        this.defaultValue = value;
+        this.required = required;
+        this.desc = desc;
+        this.checkFunc = pred;
+
+        this.check(this.defaultValue);
+    }
+
+    private Class<?> checkAndAssignDataType(Class<T> dataType) {
+        for (Class<?> clazz : ACCEPTED_DATA_TYPES) {
+            if (clazz.isAssignableFrom(dataType)) {
+                return clazz;
+            }
+        }
+
+        String msg = String.format("Input data type '%s' doesn't belong " +
+                                   "to acceptable type set: [%s]",
+                                   dataType, ACCEPTED_DATA_TYPES_STRING);
+        throw new IllegalArgumentException(msg);
+    }
+
+    public String name() {
+        return this.name;
+    }
+
+    public Class<T> dataType() {
+        return this.dataType;
+    }
+
+    public String desc() {
+        return this.desc;
+    }
+
+    public boolean required() {
+        return this.required;
+    }
+
+    public R defaultValue() {
+        return this.convert(this.defaultValue);
+    }
+
+    public R parseConvert(String value) {
+        T parsed = this.parse(value);
+        this.check(parsed);
+        return this.convert(parsed);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected T parse(String value) {
+        return (T) this.parse(value, this.dataType);
+    }
+
+    protected Object parse(String value, Class<?> dataType) {
+        if (dataType.equals(String.class)) {
+            return value;
+        } else if (dataType.equals(Class.class)) {
+            try {
+                if (value.startsWith("class")) {
+                    value = value.substring("class".length()).trim();
+                }
+                return Class.forName(value);
+            } catch (ClassNotFoundException e) {
+                throw new ConfigException(
+                          "Failed to parse Class from String '%s'", e, value);
+            }
+        } else if (List.class.isAssignableFrom(dataType)) {
+            E.checkState(this.forList(),
+                         "List option can't be registered with class %s",
+                         this.getClass().getSimpleName());
+        }
+
+        // Use PropertyConverter method `toXXX` convert value
+        String methodTo = "to" + dataType.getSimpleName();
+        try {
+            Method method = PropertyConverter.class.getMethod(
+                            methodTo, Object.class);
+            return method.invoke(null, value);
+        } catch (ReflectiveOperationException e) {
+            LOG.error("Invalid type of value '{}' for option '{}'",
+                      value, this.name, e);
+            throw new ConfigException(
+                      "Invalid type of value '%s' for option '%s', " +
+                      "expect '%s' type",
+                      value, this.name, dataType.getSimpleName());
+        }
+    }
+
+    protected void check(Object value) {
+        E.checkNotNull(value, "value", this.name);
+        if (!this.dataType.isInstance(value)) {
+            throw new ConfigException(
+                      "Invalid type of value '%s' for option '%s', " +
+                      "expect type %s but got %s", value, this.name,
+                      this.dataType.getSimpleName(),
+                      value.getClass().getSimpleName());
+        }
+
+        if (this.checkFunc != null) {
+            @SuppressWarnings("unchecked")
+            T result = (T) value;
+            if (!this.checkFunc.apply(result)) {
+                throw new ConfigException("Invalid option value for '%s': %s",
+                                          this.name, value);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected R convert(T value) {
+        return (R) value;
+    }
+
+    protected boolean forList() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("[%s]%s=%s", this.dataType.getSimpleName(),
+                             this.name, this.defaultValue);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/date/SafeDateFormat.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/date/SafeDateFormat.java
new file mode 100644
index 0000000000..716880568a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/date/SafeDateFormat.java
@@ -0,0 +1,64 @@
+/*
+ * 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.hugegraph.date;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.joda.time.DateTimeZone;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+/**
+ * The SafeDateFormat actually is a proxy for joda DateTimeFormatter
+ */
+public class SafeDateFormat {
+
+    private static final int ONE_HOUR_MS = 3600 * 1000;
+
+    private final String pattern;
+    private DateTimeFormatter formatter;
+
+    public SafeDateFormat(String pattern) {
+        this.pattern = pattern;
+        this.formatter = DateTimeFormat.forPattern(pattern);
+    }
+
+    public synchronized void setTimeZone(String zoneId) {
+        int hoursOffset = TimeZone.getTimeZone(zoneId).getRawOffset() /
+                          ONE_HOUR_MS;
+        DateTimeZone zone = DateTimeZone.forOffsetHours(hoursOffset);
+        this.formatter = this.formatter.withZone(zone);
+    }
+
+    public TimeZone getTimeZone() {
+        return this.formatter.getZone().toTimeZone();
+    }
+
+    public Date parse(String source) {
+        return this.formatter.parseDateTime(source).toDate();
+    }
+
+    public String format(Date date) {
+        return this.formatter.print(date.getTime());
+    }
+
+    public Object toPattern() {
+        return this.pattern;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/Event.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/Event.java
new file mode 100644
index 0000000000..b9cf87fa76
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/Event.java
@@ -0,0 +1,71 @@
+/*
+ * 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.hugegraph.event;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.hugegraph.util.E;
+
+public class Event extends java.util.EventObject {
+
+    private static final long serialVersionUID = 1625973849208342813L;
+
+    private String name;
+    private Object[] args;
+
+    public Event(Object source, String event) {
+        this(source, event, Collections.emptyList().toArray());
+    }
+
+    public Event(Object source, String event, Object... args) {
+        super(source);
+        this.name = event;
+        this.args = args;
+    }
+
+    public String name() {
+        return this.name;
+    }
+
+    public Object[] args() {
+        return this.args;
+    }
+
+    public void checkArgs(Class<?>... classes) throws IllegalArgumentException {
+        E.checkArgument(this.args.length == classes.length,
+                        "The args count of event '%s' should be %s(actual %s)",
+                        this.name, classes.length, this.args.length);
+        int i = 0;
+        for (Class<?> c : classes) {
+            Object arg = this.args[i++];
+            if (arg == null) {
+                continue;
+            }
+            E.checkArgument(c.isAssignableFrom(arg.getClass()),
+                            "The arg '%s'(%s) can't match %s",
+                            arg, arg.getClass(), c);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Event{name='%s', args=%s}",
+                             this.name, Arrays.asList(this.args));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/EventHub.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/EventHub.java
new file mode 100644
index 0000000000..b37c67133b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/EventHub.java
@@ -0,0 +1,197 @@
+/*
+ * 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.hugegraph.event;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nullable;
+
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.ExecutorUtil;
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+import org.apache.hugegraph.iterator.ExtendableIterator;
+import com.google.common.collect.ImmutableList;
+
+public class EventHub {
+
+    private static final Logger LOG = Log.logger(EventHub.class);
+
+    public static final String EVENT_WORKER = "event-worker-%d";
+    public static final String ANY_EVENT = "*";
+
+    private static final List<EventListener> EMPTY = ImmutableList.of();
+
+    // Event executor
+    private static ExecutorService executor = null;
+
+    private String name;
+    private Map<String, List<EventListener>> listeners;
+
+    public EventHub() {
+        this("hub");
+    }
+
+    public EventHub(String name) {
+        this(name, 1, Runtime.getRuntime().availableProcessors() << 2);
+    }
+
+    public EventHub(String name, int threadSize) {
+        LOG.debug("Create new EventHub {},threadSize {}", name, threadSize);
+        this.name = name;
+        this.listeners = new ConcurrentHashMap<>();
+        EventHub.init(threadSize);
+    }
+
+    public EventHub(String name, int corePoolSize, int maximumPoolSize) {
+        LOG.debug("Create new EventHub {},corePoolSize {}, maximumPoolSize {}", name, corePoolSize, maximumPoolSize);
+        this.name = name;
+        this.listeners = new ConcurrentHashMap<>();
+        EventHub.init(corePoolSize, maximumPoolSize);
+    }
+
+    public static synchronized void init(int poolSize) {
+        if (executor != null) {
+            return;
+        }
+        LOG.debug("Init pool(size {}) for EventHub", poolSize);
+        executor = ExecutorUtil.newFixedThreadPool(poolSize, EVENT_WORKER);
+    }
+
+    public static synchronized void init(int corePoolSize, int maximumPoolSize) {
+        LOG.debug("Init corePoolSize {}, maximumPoolSize {} for EventHub", corePoolSize, maximumPoolSize);
+        if (executor != null) {
+            LOG.debug("EventHub executor already initialized");
+            return;
+        }
+        executor = ExecutorUtil.newDynamicThreadExecutor(EVENT_WORKER, corePoolSize, maximumPoolSize);
+    }
+
+    public static synchronized boolean destroy(long timeout)
+                                               throws InterruptedException {
+        E.checkState(executor != null, "EventHub has not been initialized");
+        LOG.debug("Destroy pool for EventHub");
+        executor.shutdown();
+        return executor.awaitTermination(timeout, TimeUnit.SECONDS);
+    }
+
+    private static ExecutorService executor() {
+        ExecutorService e = executor;
+        E.checkState(e != null, "The event executor has been destroyed");
+        return e;
+    }
+
+    public String name() {
+        return this.name;
+    }
+
+    public boolean containsListener(String event) {
+        List<EventListener> ls = this.listeners.get(event);
+        return ls != null && ls.size() > 0;
+    }
+
+    public List<EventListener> listeners(String event) {
+        List<EventListener> ls = this.listeners.get(event);
+        return ls == null ? EMPTY : Collections.unmodifiableList(ls);
+    }
+
+    public void listen(String event, EventListener listener) {
+        E.checkNotNull(event, "event");
+        E.checkNotNull(listener, "event listener");
+
+        if (!this.listeners.containsKey(event)) {
+            this.listeners.putIfAbsent(event, new CopyOnWriteArrayList<>());
+        }
+        List<EventListener> ls = this.listeners.get(event);
+        assert ls != null : this.listeners;
+        ls.add(listener);
+    }
+
+    public List<EventListener> unlisten(String event) {
+        List<EventListener> ls = this.listeners.remove(event);
+        return ls == null ? EMPTY : Collections.unmodifiableList(ls);
+    }
+
+    public int unlisten(String event, EventListener listener) {
+        List<EventListener> ls = this.listeners.get(event);
+        if (ls == null) {
+            return 0;
+        }
+
+        int count = 0;
+        while (ls.remove(listener)) {
+            count++;
+        }
+        return count;
+    }
+
+    public Future<Integer> notify(String event, @Nullable Object... args) {
+        @SuppressWarnings("resource")
+        ExtendableIterator<EventListener> all = new ExtendableIterator<>();
+
+        List<EventListener> ls = this.listeners.get(event);
+        if (ls != null && !ls.isEmpty()) {
+            all.extend(ls.iterator());
+        }
+        List<EventListener> lsAny = this.listeners.get(ANY_EVENT);
+        if (lsAny != null && !lsAny.isEmpty()) {
+            all.extend(lsAny.iterator());
+        }
+
+        if (!all.hasNext()) {
+            return CompletableFuture.completedFuture(0);
+        }
+
+        Event ev = new Event(this, event, args);
+
+        // The submit will catch params: `all`(Listeners) and `ev`(Event)
+        return executor().submit(() -> {
+            int count = 0;
+            // Notify all listeners, and ignore the results
+            while (all.hasNext()) {
+                try {
+                    all.next().event(ev);
+                    count++;
+                } catch (Throwable e) {
+                    LOG.warn("Failed to handle event: {}", ev, e);
+                }
+            }
+            return count;
+        });
+    }
+
+    public Object call(String event, @Nullable Object... args) {
+        List<EventListener> ls = this.listeners.get(event);
+        if (ls == null) {
+            throw new RuntimeException("Not found listener for: " + event);
+        } else if (ls.size() != 1) {
+            throw new RuntimeException("Too many listeners for: " + event);
+        }
+        EventListener listener = ls.get(0);
+        return listener.event(new Event(this, event, args));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/EventListener.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/EventListener.java
new file mode 100644
index 0000000000..24fc594a5b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/event/EventListener.java
@@ -0,0 +1,27 @@
+/*
+ * 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.hugegraph.event;
+
+public interface EventListener extends java.util.EventListener {
+    /**
+     * The event callback
+     * @param event object
+     * @return event result
+     */
+    Object event(Event event);
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/func/TriFunction.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/func/TriFunction.java
new file mode 100644
index 0000000000..4b086440bc
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/func/TriFunction.java
@@ -0,0 +1,23 @@
+/*
+ * 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.hugegraph.func;
+
+public interface TriFunction<T1, T2, T3, R> {
+
+    R apply(T1 v1, T2 v2, T3 v3);
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/BatchMapperIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/BatchMapperIterator.java
new file mode 100644
index 0000000000..795ba61f93
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/BatchMapperIterator.java
@@ -0,0 +1,104 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Function;
+
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.InsertionOrderUtil;
+
+import com.google.common.collect.ImmutableList;
+
+public class BatchMapperIterator<T, R> extends WrappedIterator<R> {
+
+    private final int batch;
+    private final Iterator<T> originIterator;
+    private final Function<List<T>, Iterator<R>> mapperCallback;
+
+    private Iterator<R> batchIterator;
+
+    public BatchMapperIterator(int batch, Iterator<T> origin,
+                               Function<List<T>, Iterator<R>> mapper) {
+        E.checkArgument(batch > 0, "Expect batch > 0, but got %s", batch);
+        this.batch = batch;
+        this.originIterator = origin;
+        this.mapperCallback = mapper;
+        this.batchIterator = null;
+    }
+
+    @Override
+    protected Iterator<T> originIterator() {
+        return this.originIterator;
+    }
+
+    @Override
+    protected final boolean fetch() {
+        if (this.batchIterator != null && this.fetchFromBatch()) {
+            return true;
+        }
+
+        List<T> batch = this.nextBatch();
+        assert this.batchIterator == null;
+        while (!batch.isEmpty()) {
+            // Do fetch
+            this.batchIterator = this.mapperCallback.apply(batch);
+            if (this.batchIterator != null && this.fetchFromBatch()) {
+                return true;
+            }
+            // Try next batch
+            batch = this.nextBatch();
+        }
+        return false;
+    }
+
+    protected final List<T> nextBatch() {
+        if (!this.originIterator.hasNext()) {
+            return ImmutableList.of();
+        }
+        List<T> list = InsertionOrderUtil.newList();
+        for (int i = 0; i < this.batch && this.originIterator.hasNext(); i++) {
+            T next = this.originIterator.next();
+            list.add(next);
+        }
+        return list;
+    }
+
+    protected final boolean fetchFromBatch() {
+        E.checkNotNull(this.batchIterator, "mapper results");
+        while (this.batchIterator.hasNext()) {
+            R result = this.batchIterator.next();
+            if (result != null) {
+                assert this.current == none();
+                this.current = result;
+                return true;
+            }
+        }
+        this.resetBatchIterator();
+        return false;
+    }
+
+    protected final void resetBatchIterator() {
+        if (this.batchIterator == null) {
+            return;
+        }
+        close(this.batchIterator);
+        this.batchIterator = null;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/CIter.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/CIter.java
new file mode 100644
index 0000000000..249d8dc8e4
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/CIter.java
@@ -0,0 +1,23 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+
+public interface CIter<R> extends Iterator<R>, AutoCloseable, Metadatable {
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/ExtendableIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/ExtendableIterator.java
new file mode 100644
index 0000000000..94c734b988
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/ExtendableIterator.java
@@ -0,0 +1,98 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentLinkedDeque;
+
+import org.apache.hugegraph.util.E;
+
+public class ExtendableIterator<T> extends WrappedIterator<T> {
+
+    private final Deque<Iterator<T>> itors;
+
+    private Iterator<T> currentIterator;
+
+    public ExtendableIterator() {
+        this.itors = new ConcurrentLinkedDeque<>();
+        this.currentIterator = null;
+    }
+
+    public ExtendableIterator(Iterator<T> iter) {
+        this();
+        this.extend(iter);
+    }
+
+    public ExtendableIterator(Iterator<T> itor1, Iterator<T> itor2) {
+        this();
+        this.extend(itor1);
+        this.extend(itor2);
+    }
+
+    public ExtendableIterator<T> extend(Iterator<T> iter) {
+        E.checkState(this.currentIterator == null,
+                     "Can't extend iterator after iterating");
+        if (iter != null) {
+            this.itors.addLast(iter);
+        }
+        return this;
+    }
+
+    @Override
+    public void close() throws Exception {
+        for (Iterator<T> iter : this.itors) {
+            if (iter instanceof AutoCloseable) {
+                ((AutoCloseable) iter).close();
+            }
+        }
+    }
+
+    @Override
+    protected Iterator<T> originIterator() {
+        return this.currentIterator;
+    }
+
+    @Override
+    protected boolean fetch() {
+        assert this.current == none();
+        if (this.itors.isEmpty()) {
+            return false;
+        }
+
+        if (this.currentIterator != null && this.currentIterator.hasNext()) {
+            this.current = this.currentIterator.next();
+            return true;
+        }
+
+        Iterator<T> first;
+        while ((first = this.itors.peekFirst()) != null && !first.hasNext()) {
+            if (first == this.itors.peekLast() && this.itors.size() == 1) {
+                this.currentIterator = first;
+                // The last one
+                return false;
+            }
+            close(this.itors.removeFirst());
+        }
+
+        assert first != null && first.hasNext();
+        this.currentIterator = first;
+        this.current = this.currentIterator.next();
+        return true;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FilterIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FilterIterator.java
new file mode 100644
index 0000000000..d467f5151a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FilterIterator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+import java.util.function.Function;
+
+public class FilterIterator<T> extends WrappedIterator<T> {
+
+    private final Iterator<T> originIterator;
+    private final Function<T, Boolean> filterCallback;
+
+    public FilterIterator(Iterator<T> origin, Function<T, Boolean> filter) {
+        this.originIterator = origin;
+        this.filterCallback = filter;
+    }
+
+    @Override
+    protected Iterator<T> originIterator() {
+        return this.originIterator;
+    }
+
+    @Override
+    protected final boolean fetch() {
+        while (this.originIterator.hasNext()) {
+            T next = this.originIterator.next();
+            // Do filter
+            if (next != null && this.filterCallback.apply(next)) {
+                assert this.current == none();
+                this.current = next;
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FlatMapperFilterIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FlatMapperFilterIterator.java
new file mode 100644
index 0000000000..e202a1dffe
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FlatMapperFilterIterator.java
@@ -0,0 +1,50 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+import java.util.function.Function;
+
+import org.apache.hugegraph.util.E;
+
+public class FlatMapperFilterIterator<T, R> extends FlatMapperIterator<T, R> {
+
+    private final Function<R, Boolean> filterCallback;
+
+    public FlatMapperFilterIterator(Iterator<T> origin,
+                                    Function<T, Iterator<R>> mapper,
+                                    Function<R, Boolean> filter) {
+        super(origin, mapper);
+        this.filterCallback = filter;
+    }
+
+    @Override
+    protected final boolean fetchFromBatch() {
+        E.checkNotNull(this.batchIterator, "mapper results");
+        while (this.batchIterator.hasNext()) {
+            R result = this.batchIterator.next();
+            if (result != null && this.filterCallback.apply(result)) {
+                assert this.current == none();
+                this.current = result;
+                return true;
+            }
+        }
+        this.resetBatchIterator();
+        return false;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FlatMapperIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FlatMapperIterator.java
new file mode 100644
index 0000000000..3273ab8ec8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/FlatMapperIterator.java
@@ -0,0 +1,89 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+import java.util.function.Function;
+
+import org.apache.hugegraph.util.E;
+
+public class FlatMapperIterator<T, R> extends WrappedIterator<R> {
+
+    private final Iterator<T> originIterator;
+    private final Function<T, Iterator<R>> mapperCallback;
+
+    protected Iterator<R> batchIterator;
+
+    public FlatMapperIterator(Iterator<T> origin,
+                              Function<T, Iterator<R>> mapper) {
+        this.originIterator = origin;
+        this.mapperCallback = mapper;
+        this.batchIterator = null;
+    }
+
+    @Override
+    public void close() throws Exception {
+        this.resetBatchIterator();
+        super.close();
+    }
+
+    @Override
+    protected Iterator<T> originIterator() {
+        return this.originIterator;
+    }
+
+    @Override
+    protected final boolean fetch() {
+        if (this.batchIterator != null && this.fetchFromBatch()) {
+            return true;
+        }
+
+        while (this.originIterator.hasNext()) {
+            T next = this.originIterator.next();
+            assert this.batchIterator == null;
+            // Do fetch
+            this.batchIterator = this.mapperCallback.apply(next);
+            if (this.batchIterator != null && this.fetchFromBatch()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected boolean fetchFromBatch() {
+        E.checkNotNull(this.batchIterator, "mapper results");
+        while (this.batchIterator.hasNext()) {
+            R result = this.batchIterator.next();
+            if (result != null) {
+                assert this.current == none();
+                this.current = result;
+                return true;
+            }
+        }
+        this.resetBatchIterator();
+        return false;
+    }
+
+    protected final void resetBatchIterator() {
+        if (this.batchIterator == null) {
+            return;
+        }
+        close(this.batchIterator);
+        this.batchIterator = null;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/LimitIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/LimitIterator.java
new file mode 100644
index 0000000000..9df6299a6b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/LimitIterator.java
@@ -0,0 +1,64 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+import java.util.function.Function;
+
+public class LimitIterator<T> extends WrappedIterator<T> {
+
+    private final Iterator<T> originIterator;
+    private final Function<T, Boolean> filterCallback;
+
+    public LimitIterator(Iterator<T> origin, Function<T, Boolean> filter) {
+        this.originIterator = origin;
+        this.filterCallback = filter;
+    }
+
+    @Override
+    protected Iterator<T> originIterator() {
+        return this.originIterator;
+    }
+
+    @Override
+    protected final boolean fetch() {
+        while (this.originIterator.hasNext()) {
+            T next = this.originIterator.next();
+            if (next == null) {
+                continue;
+            }
+            // Do filter
+            boolean reachLimit = this.filterCallback.apply(next);
+            if (reachLimit) {
+                this.closeOriginIterator();
+                return false;
+            }
+            assert this.current == none();
+            this.current = next;
+            return true;
+        }
+        return false;
+    }
+
+    protected final void closeOriginIterator() {
+        if (this.originIterator == null) {
+            return;
+        }
+        close(this.originIterator);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/ListIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/ListIterator.java
new file mode 100644
index 0000000000..77d54765fd
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/ListIterator.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hugegraph.util.InsertionOrderUtil;
+
+public class ListIterator<T> extends WrappedIterator<T> {
+
+    private final Iterator<T> originIterator;
+    private final Iterator<T> resultsIterator;
+    private final Collection<T> results;
+
+    public ListIterator(long capacity, Iterator<T> origin) {
+        List<T> results = InsertionOrderUtil.newList();
+        while (origin.hasNext()) {
+            if (capacity >= 0L && results.size() >= capacity) {
+                throw new IllegalArgumentException(
+                          "The iterator exceeded capacity " + capacity);
+            }
+            results.add(origin.next());
+        }
+        this.originIterator = origin;
+        this.results = Collections.unmodifiableList(results);
+        this.resultsIterator = this.results.iterator();
+    }
+
+    public ListIterator(Collection<T> origin) {
+        this.originIterator = origin.iterator();
+        this.results = origin instanceof List ?
+                       Collections.unmodifiableList((List<T>) origin) :
+                       Collections.unmodifiableCollection(origin);
+        this.resultsIterator = this.results.iterator();
+    }
+
+    @Override
+    public void remove() {
+        this.resultsIterator.remove();
+    }
+
+    public Collection<T> list() {
+        return this.results;
+    }
+
+    @Override
+    protected boolean fetch() {
+        assert this.current == none();
+        if (!this.resultsIterator.hasNext()) {
+            return false;
+        }
+        this.current = this.resultsIterator.next();
+        return true;
+    }
+
+    @Override
+    protected Iterator<T> originIterator() {
+        return this.originIterator;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/MapperIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/MapperIterator.java
new file mode 100644
index 0000000000..f93d4ab5d3
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/MapperIterator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+import java.util.function.Function;
+
+public class MapperIterator<T, R> extends WrappedIterator<R> {
+
+    private final Iterator<T> originIterator;
+    private final Function<T, R> mapperCallback;
+
+    public MapperIterator(Iterator<T> origin, Function<T, R> mapper) {
+        this.originIterator = origin;
+        this.mapperCallback = mapper;
+    }
+
+    @Override
+    protected Iterator<T> originIterator() {
+        return this.originIterator;
+    }
+
+    @Override
+    protected final boolean fetch() {
+        while (this.originIterator.hasNext()) {
+            T next = this.originIterator.next();
+            R result = this.mapperCallback.apply(next);
+            if (result != null) {
+                assert this.current == none();
+                this.current = result;
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/Metadatable.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/Metadatable.java
new file mode 100644
index 0000000000..992138ab53
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/Metadatable.java
@@ -0,0 +1,23 @@
+/*
+ * 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.hugegraph.iterator;
+
+public interface Metadatable {
+
+    Object metadata(String meta, Object... args);
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/WrappedIterator.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/WrappedIterator.java
new file mode 100644
index 0000000000..9836d997c7
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/iterator/WrappedIterator.java
@@ -0,0 +1,99 @@
+/*
+ * 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.hugegraph.iterator;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public abstract class WrappedIterator<R> implements CIter<R> {
+
+    private static final Object NONE = new Object();
+
+    protected R current;
+
+    public WrappedIterator() {
+        this.current = none();
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (this.current != none()) {
+            return true;
+        }
+        return this.fetch();
+    }
+
+    @Override
+    public R next() {
+        if (this.current == none()) {
+            this.fetch();
+            if (this.current == none()) {
+                throw new NoSuchElementException();
+            }
+        }
+        R current = this.current;
+        this.current = none();
+        return current;
+    }
+
+    @Override
+    public void remove() {
+        Iterator<?> iterator = this.originIterator();
+        if (iterator == null) {
+            throw new NoSuchElementException(
+                      "The origin iterator can't be null for removing");
+        }
+        iterator.remove();
+    }
+
+    @Override
+    public void close() throws Exception {
+        Iterator<?> iterator = this.originIterator();
+        if (iterator instanceof AutoCloseable) {
+            ((AutoCloseable) iterator).close();
+        }
+    }
+
+    @Override
+    public Object metadata(String meta, Object... args) {
+        Iterator<?> iterator = this.originIterator();
+        if (iterator instanceof Metadatable) {
+            return ((Metadatable) iterator).metadata(meta, args);
+        }
+        throw new IllegalStateException("Original iterator is not Metadatable");
+    }
+
+    @SuppressWarnings("unchecked")
+    protected static final <R> R none() {
+        return (R) NONE;
+    }
+
+    public static void close(Iterator<?> iterator) {
+        if (iterator instanceof AutoCloseable) {
+            try {
+                ((AutoCloseable) iterator).close();
+            } catch (Exception e) {
+                throw new IllegalStateException("Failed to close iterator");
+            }
+        }
+    }
+
+    protected abstract Iterator<?> originIterator();
+
+    protected abstract boolean fetch();
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseCommonParam.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseCommonParam.java
new file mode 100644
index 0000000000..dac13e8d1a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseCommonParam.java
@@ -0,0 +1,106 @@
+/*
+ * 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.hugegraph.license;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.time.DateUtils;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class LicenseCommonParam {
+
+    @JsonProperty("subject")
+    private String subject;
+
+    @JsonProperty("issued_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date issuedTime = new Date();
+
+    @JsonProperty("not_before")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date notBefore = this.issuedTime;
+
+    @JsonProperty("not_after")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date notAfter = DateUtils.addDays(this.notBefore, 30);
+
+    @JsonProperty("consumer_type")
+    private String consumerType = "user";
+
+    @JsonProperty("consumer_amount")
+    private Integer consumerAmount = 1;
+
+    @JsonProperty("description")
+    private String description = "";
+
+    @JsonProperty("extra_params")
+    private List<LicenseExtraParam> extraParams;
+
+    public LicenseCommonParam() {
+        // pass
+    }
+
+    public LicenseCommonParam(String subject, String description,
+                              Date issued, Date notBefore, Date notAfter,
+                              String consumerType, int consumerAmount,
+                              List<LicenseExtraParam> extraParams) {
+        this.subject = subject;
+        this.description = description;
+        this.issuedTime = issued;
+        this.notBefore = notBefore;
+        this.notAfter = notAfter;
+        this.consumerType = consumerType;
+        this.consumerAmount = consumerAmount;
+        this.extraParams = extraParams;
+    }
+
+    public String subject() {
+        return this.subject;
+    }
+
+    public Date issuedTime() {
+        return this.issuedTime;
+    }
+
+    public Date notBefore() {
+        return this.notBefore;
+    }
+
+    public Date notAfter() {
+        return this.notAfter;
+    }
+
+    public String consumerType() {
+        return this.consumerType;
+    }
+
+    public Integer consumerAmount() {
+        return this.consumerAmount;
+    }
+
+    public String description() {
+        return this.description;
+    }
+
+    public List<LicenseExtraParam> extraParams() {
+        return this.extraParams;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseCreateParam.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseCreateParam.java
new file mode 100644
index 0000000000..d67f8a2a3d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseCreateParam.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hugegraph.license;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class LicenseCreateParam extends LicenseCommonParam {
+
+    @JsonProperty("private_alias")
+    private String privateAlias;
+
+    @JsonAlias("key_ticket")
+    @JsonProperty("key_password")
+    private String keyPassword;
+
+    @JsonAlias("store_ticket")
+    @JsonProperty("store_password")
+    private String storePassword;
+
+    @JsonProperty("privatekey_path")
+    private String privateKeyPath;
+
+    @JsonProperty("license_path")
+    private String licensePath;
+
+    public String privateAlias() {
+        return this.privateAlias;
+    }
+
+    public String keyPassword() {
+        return this.keyPassword;
+    }
+
+    public String storePassword() {
+        return this.storePassword;
+    }
+
+    public String privateKeyPath() {
+        return this.privateKeyPath;
+    }
+
+    public String licensePath() {
+        return this.licensePath;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseExtraParam.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseExtraParam.java
new file mode 100644
index 0000000000..4f563ebce2
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseExtraParam.java
@@ -0,0 +1,119 @@
+/*
+ * 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.hugegraph.license;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class LicenseExtraParam {
+
+    public static final int NO_LIMIT = -1;
+
+    @JsonProperty("id")
+    private String id;
+
+    @JsonProperty("version")
+    private String version;
+
+    @JsonProperty("graphs")
+    private int graphs;
+
+    @JsonProperty("ip")
+    private String ip;
+
+    @JsonProperty("mac")
+    private String mac;
+
+    @JsonProperty("cpus")
+    private int cpus;
+
+    // The unit is MB
+    @JsonProperty("ram")
+    private int ram;
+
+    @JsonProperty("threads")
+    private int threads;
+
+    // The unit is MB
+    @JsonProperty("memory")
+    private int memory;
+
+    @JsonProperty("nodes")
+    private int nodes;
+
+    // The unit is MB
+    @JsonProperty("data_size")
+    private long dataSize;
+
+    @JsonProperty("vertices")
+    private long vertices;
+
+    @JsonProperty("edges")
+    private long edges;
+
+    public String id() {
+        return this.id;
+    }
+
+    public String version() {
+        return this.version;
+    }
+
+    public int graphs() {
+        return this.graphs;
+    }
+
+    public String ip() {
+        return this.ip;
+    }
+
+    public String mac() {
+        return this.mac;
+    }
+
+    public int cpus() {
+        return this.cpus;
+    }
+
+    public int ram() {
+        return this.ram;
+    }
+
+    public int threads() {
+        return this.threads;
+    }
+
+    public int memory() {
+        return this.memory;
+    }
+
+    public int nodes() {
+        return this.nodes;
+    }
+
+    public long dataSize() {
+        return this.dataSize;
+    }
+
+    public long vertices() {
+        return this.vertices;
+    }
+
+    public long edges() {
+        return this.edges;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseInstallParam.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseInstallParam.java
new file mode 100644
index 0000000000..3717e5d518
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseInstallParam.java
@@ -0,0 +1,60 @@
+/*
+ * 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.hugegraph.license;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class LicenseInstallParam {
+
+    @JsonProperty("subject")
+    private String subject;
+
+    @JsonProperty("public_alias")
+    private String publicAlias;
+
+    @JsonAlias("store_ticket")
+    @JsonProperty("store_password")
+    private String storePassword;
+
+    @JsonProperty("publickey_path")
+    private String publicKeyPath;
+
+    @JsonProperty("license_path")
+    private String licensePath;
+
+    public String subject() {
+        return this.subject;
+    }
+
+    public String publicAlias() {
+        return this.publicAlias;
+    }
+
+    public String storePassword() {
+        return this.storePassword;
+    }
+
+    public String licensePath() {
+        return this.licensePath;
+    }
+
+    public String publicKeyPath() {
+        return this.publicKeyPath;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseManager.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseManager.java
new file mode 100644
index 0000000000..47bb886b07
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseManager.java
@@ -0,0 +1,32 @@
+/*
+ * 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.hugegraph.license;
+
+public interface LicenseManager {
+
+    LicenseParams installLicense() throws Exception;
+
+    void uninstallLicense() throws Exception;
+
+    LicenseParams verifyLicense() throws Exception;
+
+    interface VerifyCallback {
+
+        void onVerifyLicense(LicenseParams params) throws Exception;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseManagerFactory.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseManagerFactory.java
new file mode 100644
index 0000000000..5794663175
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseManagerFactory.java
@@ -0,0 +1,30 @@
+/*
+ * 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.hugegraph.license;
+
+import org.apache.commons.lang.NotImplementedException;
+
+import org.apache.hugegraph.license.LicenseManager.VerifyCallback;
+
+public class LicenseManagerFactory {
+
+    public static LicenseManager create(LicenseInstallParam param,
+                                        VerifyCallback veryfyCallback) {
+        throw new NotImplementedException("No LicenseManager available");
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseParams.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseParams.java
new file mode 100644
index 0000000000..94b9dd15c0
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/LicenseParams.java
@@ -0,0 +1,45 @@
+/*
+ * 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.hugegraph.license;
+
+import java.util.Date;
+import java.util.List;
+
+public class LicenseParams extends LicenseCommonParam {
+
+    public LicenseParams() {
+        super();
+    }
+
+    public LicenseParams(String subject, String description,
+                         Date issued, Date notBefore, Date notAfter,
+                         String consumerType, int consumerAmount,
+                         List<LicenseExtraParam> extraParams) {
+        super(subject, description, issued, notBefore, notAfter,
+              consumerType, consumerAmount, extraParams);
+    }
+
+    public LicenseExtraParam matchParam(String id) {
+        for (LicenseExtraParam param : this.extraParams()) {
+            if (param.id().equals(id)) {
+                return param;
+            }
+        }
+        return null;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/MachineInfo.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/MachineInfo.java
new file mode 100755
index 0000000000..cd106921ea
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/license/MachineInfo.java
@@ -0,0 +1,126 @@
+/*
+ * 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.hugegraph.license;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class MachineInfo {
+
+    private List<String> ipAddressList;
+    private List<String> macAddressList;
+
+    public MachineInfo() {
+        this.ipAddressList = null;
+        this.macAddressList = null;
+    }
+
+    public List<String> getIpAddress() {
+        if (this.ipAddressList != null) {
+            return this.ipAddressList;
+        }
+        this.ipAddressList = new ArrayList<>();
+        List<InetAddress> inetAddresses = this.getLocalAllInetAddress();
+        if (inetAddresses != null && !inetAddresses.isEmpty()) {
+            this.ipAddressList = inetAddresses.stream()
+                                              .map(InetAddress::getHostAddress)
+                                              .distinct()
+                                              .map(String::toLowerCase)
+                                              .collect(Collectors.toList());
+        }
+        return this.ipAddressList;
+    }
+
+    public List<String> getMacAddress() {
+        if (this.macAddressList != null) {
+            return this.macAddressList;
+        }
+        this.macAddressList = new ArrayList<>();
+        List<InetAddress> inetAddresses = this.getLocalAllInetAddress();
+        if (inetAddresses != null && !inetAddresses.isEmpty()) {
+            // Get the Mac address of all network interfaces
+            List<String> list = new ArrayList<>();
+            Set<String> uniqueValues = new HashSet<>();
+            for (InetAddress inetAddress : inetAddresses) {
+                String macByInetAddress = this.getMacByInetAddress(inetAddress);
+                if (uniqueValues.add(macByInetAddress)) {
+                    list.add(macByInetAddress);
+                }
+            }
+            this.macAddressList = list;
+        }
+        return this.macAddressList;
+    }
+
+    public List<InetAddress> getLocalAllInetAddress() {
+        Enumeration<NetworkInterface> interfaces;
+        try {
+            interfaces = NetworkInterface.getNetworkInterfaces();
+        } catch (SocketException e) {
+            throw new RuntimeException("Failed to get network interfaces");
+        }
+
+        List<InetAddress> result = new ArrayList<>();
+        while (interfaces.hasMoreElements()) {
+            NetworkInterface nw = interfaces.nextElement();
+            for (Enumeration<InetAddress> inetAddresses = nw.getInetAddresses();
+                 inetAddresses.hasMoreElements(); ) {
+                InetAddress inetAddr = inetAddresses.nextElement();
+                if (!inetAddr.isLoopbackAddress() &&
+                    !inetAddr.isLinkLocalAddress() &&
+                    !inetAddr.isMulticastAddress()) {
+                    result.add(inetAddr);
+                }
+            }
+        }
+        return result;
+    }
+
+    public String getMacByInetAddress(InetAddress inetAddr) {
+        byte[] mac;
+        try {
+            mac = NetworkInterface.getByInetAddress(inetAddr)
+                                  .getHardwareAddress();
+        } catch (Exception e) {
+            throw new RuntimeException(String.format(
+                      "Failed to get mac address for inet address '%s'",
+                      inetAddr));
+        }
+
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < mac.length; i++) {
+            if (i != 0) {
+                sb.append("-");
+            }
+            String temp = Integer.toHexString(mac[i] & 0xff);
+            if (temp.length() == 1) {
+                sb.append("0").append(temp);
+            } else {
+                sb.append(temp);
+            }
+        }
+        return sb.toString().toUpperCase();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/LightStopwatch.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/LightStopwatch.java
new file mode 100644
index 0000000000..6bdbcaad37
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/LightStopwatch.java
@@ -0,0 +1,185 @@
+/*
+ * 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.hugegraph.perf;
+
+import java.util.List;
+
+import org.apache.hugegraph.perf.PerfUtil.FastMap;
+
+public final class LightStopwatch implements Stopwatch {
+
+    private long lastStartTime = -1L;
+
+    private long times = 0L;
+    private long totalCost = 0L;
+    private long totalChildrenTimes = -1L;
+
+    private final String name;
+    private final Path parent;
+    private final Path id;
+    private final FastMap<String, Stopwatch> children;
+
+    public LightStopwatch(String name, Stopwatch parent) {
+        this(name, parent.id());
+        parent.child(name, this);
+    }
+
+    public LightStopwatch(String name, Path parent) {
+        this.name = name;
+        this.parent = parent;
+        this.id = Stopwatch.id(parent, name);
+        this.children = new FastMap<>();
+    }
+
+    @Override
+    public Path id() {
+        return this.id;
+    }
+
+    @Override
+    public String name() {
+        return this.name;
+    }
+
+    @Override
+    public Path parent() {
+        return this.parent;
+    }
+
+    @Override
+    public void lastStartTime(long startTime) {
+        this.lastStartTime = startTime;
+    }
+
+    @Override
+    public void startTime(long startTime) {
+        this.times++;
+        this.lastStartTime = startTime;
+    }
+
+    @Override
+    public void endTime(long startTime) {
+        this.totalCost += PerfUtil.now() - this.lastStartTime;
+    }
+
+    @Override
+    public long times() {
+        return this.times;
+    }
+
+    @Override
+    public long totalTimes() {
+        if (this.totalChildrenTimes > 0L) {
+            return this.times + this.totalChildrenTimes;
+        }
+        return this.times;
+    }
+
+    @Override
+    public long totalChildrenTimes() {
+        return this.totalChildrenTimes;
+    }
+
+    @Override
+    public long totalCost() {
+        return this.totalCost;
+    }
+
+    @Override
+    public void totalCost(long totalCost) {
+        this.totalCost = totalCost;
+    }
+
+    @Override
+    public long minCost() {
+        return -1L;
+    }
+
+    @Override
+    public long maxCost() {
+        return -1L;
+    }
+
+    @Override
+    public long totalWasted() {
+        return 0L;
+    }
+
+    @Override
+    public long totalSelfWasted() {
+        return 0L;
+    }
+
+    @Override
+    public long totalChildrenWasted() {
+        return -1L;
+    }
+
+    @Override
+    public void fillChildrenTotal(List<Stopwatch> children) {
+        // Fill total times of children
+        this.totalChildrenTimes = children.stream().mapToLong(Stopwatch::totalTimes).sum();
+    }
+
+    @Override
+    public LightStopwatch copy() {
+        try {
+            return (LightStopwatch) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public Stopwatch child(String name) {
+        return this.children.get(name);
+    }
+
+    @Override
+    public Stopwatch child(String name, Stopwatch watch) {
+        if (watch == null) {
+            return this.children.remove(name);
+        }
+        return this.children.put(name, watch);
+    }
+
+    @Override
+    public boolean empty() {
+        return this.children.size() == 0;
+    }
+
+    @Override
+    public void clear() {
+        this.lastStartTime = -1L;
+
+        this.times = 0L;
+        this.totalCost = 0L;
+        this.totalChildrenTimes = -1L;
+
+        this.children.clear();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("{parent:%s,name:%s," +
+                             "times:%s,totalChildrenTimes:%s,totalCost:%s}",
+                             this.parent, this.name,
+                             this.times, this.totalChildrenTimes,
+                             this.totalCost);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/NormalStopwatch.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/NormalStopwatch.java
new file mode 100644
index 0000000000..40901434e8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/NormalStopwatch.java
@@ -0,0 +1,302 @@
+/*
+ * 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.hugegraph.perf;
+
+import java.util.List;
+import java.util.function.BiFunction;
+
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+import org.apache.hugegraph.testutil.Whitebox;
+
+public final class NormalStopwatch implements Stopwatch {
+
+    private static final Logger LOG = Log.logger(Stopwatch.class);
+
+    private static final String MULTI_THREAD_ACCESS_ERROR =
+                         "There may be multi-threaded access, ensure " +
+                         "not call PerfUtil.profileSingleThread(true) when " +
+                         "multithreading.";
+
+    private long lastStartTime = -1L;
+
+    private long times = 0L;
+    private long totalCost = 0L;
+    private long minCost = Long.MAX_VALUE;
+    private long maxCost = 0L;
+    private long totalSelfWasted = 0L;
+    private long totalChildrenWasted = -1L;
+    private long totalChildrenTimes = -1L;
+
+    private final String name;
+    private final Path parent;
+    private final Path id;
+    private final PerfUtil.FastMap<String, Stopwatch> children;
+
+    public NormalStopwatch(String name, Stopwatch parent) {
+        this(name, parent.id());
+        parent.child(name, this);
+    }
+
+    public NormalStopwatch(String name, Path parent) {
+        this.name = name;
+        this.parent = parent;
+        this.id = Stopwatch.id(parent, name);
+        this.children = new PerfUtil.FastMap<>();
+    }
+
+    @Override
+    public Path id() {
+        return this.id;
+    }
+
+    @Override
+    public String name() {
+        return this.name;
+    }
+
+    @Override
+    public Path parent() {
+        return this.parent;
+    }
+
+    @Override
+    public void lastStartTime(long startTime) {
+        this.lastStartTime = startTime;
+    }
+
+    @Override
+    public void startTime(long startTime) {
+        assert this.lastStartTime == -1L : MULTI_THREAD_ACCESS_ERROR;
+
+        this.times++;
+        this.lastStartTime = startTime;
+
+        long endTime = PerfUtil.now();
+        long wastedTime = endTime - startTime;
+        if (wastedTime <= 0L) {
+            wastedTime += eachStartWastedLost;
+        }
+
+        this.totalSelfWasted += wastedTime;
+    }
+
+    @Override
+    public void endTime(long startTime) {
+        assert startTime >= this.lastStartTime && this.lastStartTime != -1L :
+               MULTI_THREAD_ACCESS_ERROR;
+
+        long endTime = PerfUtil.now();
+        // The following code cost about 3ns~4ns
+        long wastedTime = endTime - startTime;
+        if (wastedTime <= 0L) {
+            wastedTime += eachEndWastedLost;
+        }
+
+        long cost = endTime - this.lastStartTime;
+
+        if (this.minCost > cost) {
+            this.minCost = cost;
+        }
+        if (this.maxCost < cost) {
+            this.maxCost = cost;
+        }
+
+        this.totalCost += cost;
+        this.totalSelfWasted += wastedTime;
+        this.lastStartTime = -1L;
+    }
+
+    @Override
+    public long times() {
+        return this.times;
+    }
+
+    @Override
+    public long totalCost() {
+        return this.totalCost;
+    }
+
+    @Override
+    public void totalCost(long totalCost) {
+        this.totalCost = totalCost;
+    }
+
+    @Override
+    public long minCost() {
+        return this.minCost;
+    }
+
+    @Override
+    public long maxCost() {
+        return this.maxCost;
+    }
+
+    @Override
+    public long totalTimes() {
+        if (this.totalChildrenTimes > 0L) {
+            return this.times + this.totalChildrenTimes;
+        }
+        return this.times;
+    }
+
+    @Override
+    public long totalChildrenTimes() {
+        return this.totalChildrenTimes;
+    }
+
+    @Override
+    public long totalWasted() {
+        if (this.totalChildrenWasted > 0L) {
+            return this.totalSelfWasted + this.totalChildrenWasted;
+        }
+        return this.totalSelfWasted;
+    }
+
+    @Override
+    public long totalSelfWasted() {
+        return this.totalSelfWasted;
+    }
+
+    @Override
+    public long totalChildrenWasted() {
+        return this.totalChildrenWasted;
+    }
+
+    @Override
+    public void fillChildrenTotal(List<Stopwatch> children) {
+        // Fill total wasted cost of children
+        this.totalChildrenWasted = children.stream().mapToLong(Stopwatch::totalWasted).sum();
+        // Fill total times of children
+        this.totalChildrenTimes = children.stream().mapToLong(Stopwatch::totalTimes).sum();
+    }
+
+    @Override
+    public Stopwatch copy() {
+        try {
+            return (Stopwatch) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public Stopwatch child(String name) {
+        return this.children.get(name);
+    }
+
+    @Override
+    public Stopwatch child(String name, Stopwatch watch) {
+        if (watch == null) {
+            return this.children.remove(name);
+        }
+        return this.children.put(name, watch);
+    }
+
+    @Override
+    public boolean empty() {
+        return this.children.size() == 0;
+    }
+
+    @Override
+    public void clear() {
+        this.lastStartTime = -1L;
+
+        this.times = 0L;
+        this.totalCost = 0L;
+
+        this.minCost = Long.MAX_VALUE;
+        this.maxCost = 0L;
+        this.totalSelfWasted = 0L;
+        this.totalChildrenWasted = -1L;
+        this.totalChildrenTimes = -1L;
+
+        this.children.clear();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("{parent:%s,name:%s," +
+                             "times:%s,totalChildrenTimes:%s," +
+                             "totalCost:%s,minCost:%s,maxCost:%s," +
+                             "totalSelfWasted:%s,totalChildrenWasted:%s}",
+                             this.parent, this.name,
+                             this.times, this.totalChildrenTimes,
+                             this.totalCost, this.minCost, this.maxCost,
+                             this.totalSelfWasted, this.totalChildrenWasted);
+    }
+
+    private static long eachStartWastedLost = 0L;
+    private static long eachEndWastedLost = 0L;
+
+    protected static void initEachWastedLost() {
+        int times = 100000000;
+
+        PerfUtil.LocalStack<Stopwatch> callStack = Whitebox.getInternalState(
+                                          PerfUtil.instance(), "callStack");
+
+        long baseStart = PerfUtil.now();
+        for (int i = 0; i < times; i++) {
+            PerfUtil.instance();
+        }
+        long baseCost = PerfUtil.now() - baseStart;
+
+        BiFunction<String, Runnable, Long> testEachCost = (name, test) -> {
+            long start = PerfUtil.now();
+            test.run();
+            long end = PerfUtil.now();
+            long cost = end - start - baseCost;
+            if (cost < 0L) {
+                cost = 0L;
+            }
+            long eachCost = cost / times;
+
+            LOG.info("Wasted time test: cost={}ms, base_cost={}ms, {}={}ns",
+                     cost / 1000000.0, baseCost / 1000000.0, name, eachCost);
+            return eachCost;
+        };
+
+        String startName = "each_start_cost";
+        eachStartWastedLost = testEachCost.apply(startName, () -> {
+            Stopwatch watch = PerfUtil.instance().start(startName);
+            PerfUtil.instance().end(startName);
+            for (int i = 0; i < times; i++) {
+                // Test call start()
+                PerfUtil.instance().start(startName);
+                // Mock end()
+                watch.lastStartTime(-1L);
+                callStack.pop();
+            }
+        });
+
+        String endName = "each_end_cost";
+        eachEndWastedLost = testEachCost.apply(endName, () -> {
+            Stopwatch watch = PerfUtil.instance().start(endName);
+            PerfUtil.instance().end(endName);
+            for (int i = 0; i < times; i++) {
+                // Mock start()
+                callStack.push(watch);
+                watch.lastStartTime(0L);
+                // Test call start()
+                PerfUtil.instance().end(endName);
+                watch.totalCost(0L);
+            }
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/PerfUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/PerfUtil.java
new file mode 100644
index 0000000000..77b68d6be7
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/PerfUtil.java
@@ -0,0 +1,687 @@
+/*
+ * 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.hugegraph.perf;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.EmptyStackException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.slf4j.Logger;
+
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.Log;
+import org.apache.hugegraph.util.ReflectionUtil;
+import org.apache.hugegraph.func.TriFunction;
+import org.apache.hugegraph.testutil.Assert.ThrowableConsumer;
+import org.apache.hugegraph.perf.Stopwatch.Path;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+
+public final class PerfUtil {
+
+    private static final Logger LOG = Log.logger(PerfUtil.class);
+    private static final int DEFAULT_CAPACITY = 1024;
+
+    private static final ThreadLocal<PerfUtil> INSTANCE = new ThreadLocal<>();
+
+    private static PerfUtil SINGLE_INSTANCE = null;
+    private static Thread SINGLE_THREAD = null;
+    private static LocalTimer LOCAL_TIMER = null;
+    private static boolean LIGHT_WATCH = false;
+
+    private final Map<Path, Stopwatch> stopwatches;
+    private final LocalStack<Stopwatch> callStack;
+    private final Stopwatch root;
+
+    private PerfUtil() {
+        this.stopwatches = new HashMap<>(DEFAULT_CAPACITY);
+        this.callStack = new LocalStack<>(DEFAULT_CAPACITY);
+        this.root = newStopwatch(Path.ROOT_NAME, Path.EMPTY);
+    }
+
+    public static PerfUtil instance() {
+        if (SINGLE_INSTANCE != null &&
+            SINGLE_THREAD == Thread.currentThread()) {
+            // Return the only one instance for single thread, for performance
+            return SINGLE_INSTANCE;
+        }
+
+        PerfUtil p = INSTANCE.get();
+        if (p == null) {
+            p = new PerfUtil();
+            INSTANCE.set(p);
+        }
+        return p;
+    }
+
+    public static void profileSingleThread(boolean yes) {
+        SINGLE_INSTANCE = yes ? PerfUtil.instance() : null;
+        SINGLE_THREAD = yes ? Thread.currentThread() : null;
+    }
+
+    public static void useLocalTimer(boolean yes) {
+        if (yes) {
+            if (LOCAL_TIMER != null) {
+                return;
+            }
+            LOCAL_TIMER = new LocalTimer();
+            try {
+                LOCAL_TIMER.startTimeUpdateLoop();
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+
+            if (!LIGHT_WATCH) {
+                NormalStopwatch.initEachWastedLost();
+            }
+        } else {
+            if (LOCAL_TIMER == null) {
+                return;
+            }
+            try {
+                LOCAL_TIMER.stop();
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            } finally {
+                LOCAL_TIMER = null;
+            }
+        }
+    }
+
+    public static void useLightStopwatch(boolean yes) {
+        if (yes != LIGHT_WATCH) {
+            PerfUtil instance = INSTANCE.get();
+            boolean empty = instance == null || instance.empty();
+            String message = "Please call clear() before switching " +
+                             "light-stopwatch due to there is dirty watch";
+            E.checkArgument(empty, message);
+        }
+        LIGHT_WATCH = yes;
+    }
+
+    protected static long now() {
+        if (LOCAL_TIMER != null) {
+            return LOCAL_TIMER.now();
+        }
+        // System.nanoTime() cost about 40 ns each call
+        return System.nanoTime();
+    }
+
+    protected static Stopwatch newStopwatch(String name, Path parent) {
+        return LIGHT_WATCH ? new LightStopwatch(name, parent) :
+                             new NormalStopwatch(name, parent);
+    }
+
+    protected static Stopwatch newStopwatch(String name, Stopwatch parent) {
+        return LIGHT_WATCH ? new LightStopwatch(name, parent) :
+                             new NormalStopwatch(name, parent);
+    }
+
+    public Stopwatch start(String name) {
+        long start = now();
+
+        Stopwatch parent = this.callStack.empty() ?
+                           this.root : this.callStack.peek();
+
+        // Get watch by name from local tree
+        Stopwatch watch = parent.child(name);
+        if (watch == null) {
+            watch = newStopwatch(name, parent);
+            assert !this.stopwatches.containsKey(watch.id()) : watch;
+            this.stopwatches.put(watch.id(), watch);
+        }
+        this.callStack.push(watch);
+
+        watch.startTime(start);
+
+        return watch;
+    }
+
+    public Stopwatch start2(String name) {
+        long start = now(); // cost 70 ns with System.nanoTime()
+
+        Path parent = this.callStack.empty() ?
+                      Path.EMPTY : this.callStack.peek().id();
+        Path id = Stopwatch.id(parent, name); // cost 130
+        // Get watch by id from global map
+        Stopwatch watch = this.stopwatches.get(id); // cost 170
+        if (watch == null) {
+            watch = newStopwatch(name, parent);
+            this.stopwatches.put(watch.id(), watch); // cost 180
+        }
+        this.callStack.push(watch); // cost 190
+
+        watch.startTime(start);
+
+        return watch;
+    }
+
+    public void end(String name) {
+        long start = LIGHT_WATCH ? 0L : now();
+
+        Stopwatch watch = this.callStack.pop();
+        if (watch == null || watch.name() != name) {
+            throw new IllegalArgumentException("Invalid watch name: " + name);
+        }
+
+        watch.endTime(start);
+    }
+
+    public boolean empty() {
+        return this.stopwatches.isEmpty() && this.root.empty();
+    }
+
+    public void clear() {
+        String error = "Can't be cleared when the call has not ended yet";
+        E.checkState(this.callStack.empty(), error);
+
+        this.stopwatches.clear();
+        this.root.clear();
+    }
+
+    public void profilePackage(String... packages) throws Throwable {
+        Set<String> loadedClasses = new HashSet<>();
+
+        Function<String, Boolean> inPackage = (cls) -> {
+            for (String pkg : packages) {
+                if (cls.startsWith(pkg)) {
+                    return true;
+                }
+            }
+            return false;
+        };
+
+        ThrowableConsumer<String> profileClassIfPresent = (cls) -> {
+            if (!loadedClasses.contains(cls)) {
+                // Profile super class
+                for (String s : ReflectionUtil.superClasses(cls)) {
+                    if (!loadedClasses.contains(s) && inPackage.apply(s)) {
+                        profileClass(s);
+                        loadedClasses.add(s);
+                    }
+                }
+                // Profile self class
+                profileClass(cls);
+                loadedClasses.add(cls);
+            }
+        };
+
+        Iterator<ClassInfo> classes = ReflectionUtil.classes(packages);
+        while (classes.hasNext()) {
+            String cls = classes.next().getName();
+            // Profile self class
+            profileClassIfPresent.accept(cls);
+            // Profile nested class
+            for (String s : ReflectionUtil.nestedClasses(cls)) {
+                profileClassIfPresent.accept(s);
+            }
+        }
+    }
+
+    public void profileClass(String... classes) throws Throwable {
+        ClassPool classPool = ClassPool.getDefault();
+
+        for (String cls : classes) {
+            CtClass ctClass = classPool.get(cls);
+            List<CtMethod> methods = ReflectionUtil.getMethodsAnnotatedWith(
+                                     ctClass, Watched.class, false);
+            for (CtMethod method : methods) {
+                profile(method);
+            }
+
+            // Load class and make it effective
+            if (!methods.isEmpty()) {
+                ctClass.toClass();
+            }
+        }
+    }
+
+    private void profile(CtMethod ctMethod)
+                         throws CannotCompileException, ClassNotFoundException {
+        final String START =
+                "org.apache.hugegraph.perf.PerfUtil.instance().start(\"%s\");";
+        final String END =
+                "org.apache.hugegraph.perf.PerfUtil.instance().end(\"%s\");";
+
+        Watched annotation = (Watched) ctMethod.getAnnotation(Watched.class);
+
+        String name = annotation.value();
+        if (name.isEmpty()) {
+            name = ctMethod.getName();
+        }
+        if (!annotation.prefix().isEmpty()) {
+            name = annotation.prefix() + "." + name;
+        }
+
+        ctMethod.insertBefore(String.format(START, name));
+        // Insert as a finally-statement
+        ctMethod.insertAfter(String.format(END, name), true);
+
+        LOG.debug("Profiled for: '{}' [{}]", name, ctMethod.getLongName());
+    }
+
+    @Override
+    public String toString() {
+        return this.stopwatches.toString();
+    }
+
+    public String toJson() {
+        StringBuilder sb = new StringBuilder(8 + this.stopwatches.size() * 96);
+        sb.append('{');
+        for (Map.Entry<Path, Stopwatch> w : this.stopwatches.entrySet()) {
+            sb.append('"');
+            sb.append(w.getKey());
+            sb.append('"');
+
+            sb.append(':');
+
+            sb.append(w.getValue().toJson());
+
+            sb.append(',');
+        }
+        if (!this.stopwatches.isEmpty()) {
+            sb.deleteCharAt(sb.length() - 1);
+        }
+        sb.append('}');
+        return sb.toString();
+    }
+
+    // TODO: move toECharts() method out of this class
+    public String toECharts() {
+        TriFunction<Integer, Integer, List<Stopwatch>, String> formatLevel = (
+                    totalDepth, depth, items) -> {
+            float factor = 100.0f / (totalDepth + 1);
+            float showFactor = 1 + (totalDepth - depth) / (float) depth;
+
+            float radiusFrom = depth * factor;
+            float radiusTo = depth * factor + factor;
+            if (depth == 1) {
+                radiusFrom = 0;
+            }
+
+            StringBuilder sb = new StringBuilder(8 + items.size() * 128);
+            sb.append('{');
+            sb.append("name: 'Total Cost',");
+            sb.append("type: 'pie',");
+            sb.append(String.format("radius: ['%s%%', '%s%%'],",
+                                    radiusFrom, radiusTo));
+            sb.append(String.format(
+                      "label: {normal: {position: 'inner', formatter:" +
+                      "function(params) {" +
+                      "  if (params.percent > %s) return params.data.name;" +
+                      "  else return '';" +
+                      "}}},", showFactor));
+            sb.append("data: [");
+
+            items.sort((i, j) -> i.id().compareTo(j.id()));
+            for (Stopwatch w : items) {
+                sb.append('{');
+
+                sb.append("id:'");
+                sb.append(w.id());
+                sb.append("',");
+
+                sb.append("name:'");
+                sb.append(w.name());
+                sb.append("',");
+
+                sb.append("value:");
+                // w.totalCost() - w.totalWasted() ?
+                sb.append(w.totalCost());
+                sb.append(',');
+
+                sb.append("cost:");
+                sb.append(w.totalCost() / 1000000.0);
+                sb.append(',');
+
+                sb.append("minCost:");
+                sb.append(w.minCost());
+                sb.append(',');
+
+                sb.append("maxCost:");
+                sb.append(w.maxCost());
+                sb.append(',');
+
+                sb.append("wasted:");
+                sb.append(w.totalWasted() / 1000000.0);
+                sb.append(',');
+
+                sb.append("selfWasted:");
+                sb.append(w.totalSelfWasted() / 1000000.0);
+                sb.append(',');
+
+                sb.append("times:");
+                sb.append(w.times());
+                sb.append(',');
+
+                sb.append("totalTimes:");
+                sb.append(w.totalTimes());
+
+                sb.append('}');
+                sb.append(',');
+            }
+            if (!items.isEmpty()) {
+                sb.deleteCharAt(sb.length() - 1);
+            }
+            sb.append("]}");
+            return sb.toString();
+        };
+
+        BiConsumer<List<Stopwatch>, List<Stopwatch>> fillChildrenTotal =
+                (itemsOfLn, itemsOfLnParent) -> {
+                    for (Stopwatch parent : itemsOfLnParent) {
+                        List<Stopwatch> children = itemsOfLn.stream().filter(c -> {
+                            return c.parent().equals(parent.id());
+                        }).collect(Collectors.toList());
+
+                        parent.fillChildrenTotal(children);
+                    }
+                };
+
+        BiConsumer<List<Stopwatch>, List<Stopwatch>> fillOther =
+                (itemsOfLn, itemsOfLnParent) -> {
+                    for (Stopwatch parent : itemsOfLnParent) {
+                        Stream<Stopwatch> children = itemsOfLn.stream().filter(c -> {
+                            return c.parent().equals(parent.id());
+                        });
+                        // Fill other cost
+                        long sumCost = children.mapToLong(Stopwatch::totalCost).sum();
+                        long otherCost = parent.totalCost() - sumCost;
+                        if (otherCost > 0L) {
+                            Stopwatch other = newStopwatch("~", parent.id());
+                            other.totalCost(otherCost);
+                            itemsOfLn.add(other);
+                        }
+                    }
+                };
+
+        Map<Path, Stopwatch> items = this.stopwatches;
+        Map<Integer, List<Stopwatch>> levelItems = new HashMap<>();
+        int maxDepth = 0;
+        for (Map.Entry<Path, Stopwatch> e : items.entrySet()) {
+            int depth = e.getKey().toString().split("/").length;
+            List<Stopwatch> levelItem = levelItems.get(depth);
+            if (levelItem == null) {
+                levelItem = new LinkedList<>();
+                levelItems.putIfAbsent(depth, levelItem);
+            }
+            levelItem.add(e.getValue().copy());
+            if (depth > maxDepth) {
+                maxDepth = depth;
+            }
+        }
+
+        // Fill wasted cost from the outermost to innermost
+        for (int i = maxDepth; i > 0; i--) {
+            assert levelItems.containsKey(i) : i;
+            List<Stopwatch> itemsOfI = levelItems.get(i);
+            List<Stopwatch> itemsOfParent = levelItems.get(i - 1);
+            if (itemsOfParent != null) {
+                // Fill total value of children
+                fillChildrenTotal.accept(itemsOfI, itemsOfParent);
+            }
+        }
+
+        StringBuilder sb = new StringBuilder(8 + items.size() * 128);
+        // Output results header
+        sb.append("{");
+        sb.append("tooltip: {trigger: 'item', " +
+            "formatter: function(params) {" +
+            "  return params.data.name + ' ' + params.percent + '% <br/>'" +
+            "    + 'cost: ' + params.data.cost + ' (ms) <br/>'" +
+            "    + 'min cost: ' + params.data.minCost + ' (ns) <br/>'" +
+            "    + 'max cost: ' + params.data.maxCost + ' (ns) <br/>'" +
+            "    + 'wasted: ' + params.data.wasted + ' (ms) <br/>'" +
+            "    + 'self wasted: ' + params.data.selfWasted + ' (ms) <br/>'" +
+            "    + 'times: ' + params.data.times + '<br/>'" +
+            "    + 'total times: ' + params.data.totalTimes + '<br/>'" +
+            "    + 'path: ' + params.data.id + '<br/>';" +
+            "}");
+        sb.append("},");
+        sb.append("series: [");
+        // Output results data
+        for (int i = 1; i <= maxDepth; i++) {
+            assert levelItems.containsKey(i) : i;
+            List<Stopwatch> itemsOfI = levelItems.get(i);
+            List<Stopwatch> itemsOfParent = levelItems.get(i - 1);
+            if (itemsOfParent != null) {
+                // Fill other cost for non-root level, ignore root level (i=1)
+                fillOther.accept(itemsOfI, itemsOfParent);
+            }
+            // Output items of level I
+            sb.append(formatLevel.apply(maxDepth, i, itemsOfI));
+            sb.append(',');
+        }
+        if (!items.isEmpty()) {
+            sb.deleteCharAt(sb.length() - 1);
+        }
+        sb.append("]}");
+
+        return sb.toString();
+    }
+
+    public static final class LocalTimer {
+
+        // Header: 4 bytes classptr + 8 bytes markword
+        private volatile long padding11 = 0L;
+        private volatile long padding12 = 0L;
+        private volatile long padding13 = 0L;
+        private volatile long padding14 = 0L;
+        private volatile long padding15 = 0L;
+        private volatile long padding16 = 0L; // the 1st 64 bytes
+
+        private volatile long time = 0L;
+
+        private volatile long padding21 = 0L;
+        private volatile long padding22 = 0L;
+        private volatile long padding23 = 0L;
+        private volatile long padding24 = 0L;
+        private volatile long padding25 = 0L;
+        private volatile long padding26 = 0L;
+        private volatile long padding27 = 0L; // the 2nd 64 bytes
+
+        private volatile boolean running = false;
+        private Thread thread = null;
+
+        public long now() {
+            // Read current ns time (be called frequently)
+            return this.time;
+        }
+
+        public void startTimeUpdateLoop() throws InterruptedException {
+            assert this.thread == null;
+            assert this.preventOptimizePadding() == 0L;
+            this.running = true;
+            CountDownLatch started = new CountDownLatch(1);
+            this.thread = new Thread(() -> {
+                started.countDown();
+                while (this.running) {
+                    this.time = System.nanoTime();
+                    // Prevent frequent updates for perf (5.2s => 3.6s for 8kw)
+                    Thread.yield();
+                }
+            }, "LocalTimer");
+            this.thread.setDaemon(true);
+            this.thread.start();
+            started.await();
+        }
+
+        public void stop() throws InterruptedException {
+            this.running = false;
+            if (this.thread != null) {
+                this.thread.join();
+            }
+        }
+
+        public long preventOptimizePadding() {
+            long p1 = this.padding11 + this.padding12 + this.padding13 +
+                      this.padding14 + this.padding15 + this.padding16;
+            long p2 = this.padding21 + this.padding22 + this.padding23 +
+                      this.padding24 + this.padding25 + this.padding26 +
+                      this.padding27;
+            return p1 + p2;
+        }
+    }
+
+    public static final class LocalStack<T> {
+
+        private final Object[] elementData;
+        private int elementCount;
+
+        public LocalStack(int capacity) {
+            this.elementData = new Object[capacity];
+            this.elementCount = 0;
+        }
+
+        int size() {
+            return this.elementCount;
+        }
+
+        boolean empty() {
+            return this.elementCount == 0;
+        }
+
+        public void push(T elem) {
+            this.elementData[this.elementCount++] = elem;
+        }
+
+        public T pop() {
+            if (this.elementCount == 0) {
+                throw new EmptyStackException();
+            }
+            this.elementCount--;
+            @SuppressWarnings("unchecked")
+            T elem = (T) this.elementData[this.elementCount];
+            this.elementData[this.elementCount] = null;
+            return elem;
+        }
+
+        public T peek() {
+            if (this.elementCount == 0) {
+                throw new EmptyStackException();
+            }
+            @SuppressWarnings("unchecked")
+            T elem = (T) this.elementData[this.elementCount - 1];
+            return elem;
+        }
+    }
+
+    public static final class FastMap<K, V> {
+
+        private final Map<K, V> hashMap;
+
+        private K key1;
+        private K key2;
+        private K key3;
+
+        private V val1;
+        private V val2;
+        private V val3;
+
+        public FastMap() {
+            this.hashMap = new HashMap<>();
+        }
+
+        public int size() {
+            return this.hashMap.size();
+        }
+
+        public boolean containsKey(Object key) {
+            return this.hashMap.containsKey(key);
+        }
+
+        public V get(Object key) {
+            if (key == this.key1) {
+                return this.val1;
+            } else if (key == this.key2) {
+                return this.val2;
+            } else if (key == this.key3) {
+                return this.val3;
+            }
+
+            return this.hashMap.get(key);
+        }
+
+        public V put(K key, V value) {
+            if (this.key1 == null) {
+                this.key1 = key;
+                this.val1 = value;
+            } else if (this.key2 == null) {
+                this.key2 = key;
+                this.val2 = value;
+            } else if (this.key3 == null) {
+                this.key3 = key;
+                this.val3 = value;
+            }
+
+            return this.hashMap.put(key, value);
+        }
+
+        public V remove(Object key) {
+            if (key == this.key1) {
+                this.key1 = null;
+                this.val1 = null;
+            } else if (key == this.key2) {
+                this.key2 = null;
+                this.val2 = null;
+            } else if (key == this.key3) {
+                this.key3 = null;
+                this.val3 = null;
+            }
+
+            return this.hashMap.remove(key);
+        }
+
+        public void clear() {
+            this.key1 = null;
+            this.key2 = null;
+            this.key3 = null;
+
+            this.val1 = null;
+            this.val2 = null;
+            this.val3 = null;
+
+            this.hashMap.clear();
+        }
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
+    public @interface Watched {
+        String value() default "";
+        String prefix() default "";
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/Stopwatch.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/Stopwatch.java
new file mode 100644
index 0000000000..487c778820
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/perf/Stopwatch.java
@@ -0,0 +1,148 @@
+/*
+ * 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.hugegraph.perf;
+
+import java.util.List;
+
+public interface Stopwatch extends Cloneable {
+
+    Path id();
+
+    String name();
+
+    Path parent();
+
+    void startTime(long startTime);
+
+    void endTime(long startTime);
+
+    void lastStartTime(long startTime);
+
+    long times();
+
+    long totalTimes();
+
+    long totalChildrenTimes();
+
+    long totalCost();
+
+    void totalCost(long otherCost);
+
+    long minCost();
+
+    long maxCost();
+
+    long totalWasted();
+
+    long totalSelfWasted();
+
+    long totalChildrenWasted();
+
+    void fillChildrenTotal(List<Stopwatch> children);
+
+    Stopwatch copy();
+
+    Stopwatch child(String name);
+
+    Stopwatch child(String name, Stopwatch watch);
+
+    boolean empty();
+
+    void clear();
+
+    default String toJson() {
+        int len = 200 + this.name().length() + this.parent().length();
+        StringBuilder sb = new StringBuilder(len);
+        sb.append("{");
+        sb.append("\"parent\":\"").append(this.parent()).append("\"");
+        sb.append(",\"name\":\"").append(this.name()).append("\"");
+        sb.append(",\"times\":").append(this.times());
+        sb.append(",\"total_cost\":").append(this.totalCost());
+        sb.append(",\"min_cost\":").append(this.minCost());
+        sb.append(",\"max_cost\":").append(this.maxCost());
+        sb.append(",\"total_self_wasted\":").append(this.totalSelfWasted());
+        sb.append(",\"total_children_wasted\":").append(
+                                                 this.totalChildrenWasted());
+        sb.append(",\"total_children_times\":").append(
+                                                 this.totalChildrenTimes());
+        sb.append("}");
+        return sb.toString();
+    }
+
+    static Path id(Path parent, String name) {
+        if (parent == Path.EMPTY && name == Path.ROOT_NAME) {
+            return Path.EMPTY;
+        }
+        return new Path(parent, name);
+    }
+
+    final class Path implements Comparable<Path> {
+
+        public static final String ROOT_NAME = "root";
+        public static final Path EMPTY = new Path("");
+
+        private final String path;
+
+        public Path(String self) {
+            this.path = self;
+        }
+
+        public Path(Path parent, String name) {
+            if (parent == EMPTY) {
+                this.path = name;
+            } else {
+                this.path = parent.path + '/' + name;
+            }
+        }
+
+        public int length() {
+            return this.path.length();
+        }
+
+        @Override
+        public int hashCode() {
+            return this.path.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this.hashCode() != obj.hashCode()) {
+                return false;
+            }
+            if (!(obj instanceof Path)) {
+                return false;
+            }
+            Path other = (Path) obj;
+            return this.path.equals(other.path);
+        }
+
+        @Override
+        public int compareTo(Path other) {
+            return this.path.compareTo(other.path);
+        }
+
+        @Override
+        public String toString() {
+            return this.path;
+        }
+
+        public boolean endsWith(String name) {
+            return this.path.endsWith(name);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
new file mode 100644
index 0000000000..c13a686b71
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
@@ -0,0 +1,490 @@
+/*
+ * 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.hugegraph.rest;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyStore;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hugegraph.util.JsonUtilCommon;
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableMap;
+
+import lombok.SneakyThrows;
+import okhttp3.ConnectionPool;
+import okhttp3.HttpUrl;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import okio.BufferedSink;
+import okio.GzipSink;
+import okio.Okio;
+
+/**
+ * This class provides an abstract implementation of the RestClient interface.
+ * It provides methods for making HTTP requests (GET, POST, PUT, DELETE) to a REST API.
+ * Note: It uses the OkHttp library to make these requests for now.
+ */
+public abstract class AbstractRestClient implements RestClient {
+
+    private final ThreadLocal<String> authContext;
+
+    private final OkHttpClient client;
+
+    private final String baseUrl;
+
+    public AbstractRestClient(String url, int timeout) {
+        this(url, RestClientConfig.builder().timeout(timeout).build());
+    }
+
+    public AbstractRestClient(String url, String user, String password, int timeout) {
+        this(url, RestClientConfig.builder()
+                                  .user(user)
+                                  .password(password)
+                                  .timeout(timeout)
+                                  .build());
+    }
+
+    public AbstractRestClient(String url, int timeout, int idleTime,
+                              int maxConns, int maxConnsPerRoute) {
+        this(url, RestClientConfig.builder()
+                                  .idleTime(idleTime)
+                                  .timeout(timeout)
+                                  .maxConns(maxConns)
+                                  .maxConnsPerRoute(maxConnsPerRoute)
+                                  .build());
+    }
+
+    public AbstractRestClient(String url, String user, String password, int timeout,
+                              int maxConns, int maxConnsPerRoute,
+                              String trustStoreFile, String trustStorePassword) {
+        this(url, RestClientConfig.builder()
+                                  .user(user).password(password)
+                                  .timeout(timeout)
+                                  .maxConns(maxConns)
+                                  .maxConnsPerRoute(maxConnsPerRoute)
+                                  .trustStoreFile(trustStoreFile)
+                                  .trustStorePassword(trustStorePassword)
+                                  .build());
+    }
+
+    public AbstractRestClient(String url, String token, int timeout,
+                              int maxConns, int maxConnsPerRoute,
+                              String trustStoreFile, String trustStorePassword) {
+        this(url, RestClientConfig.builder()
+                                  .token(token)
+                                  .timeout(timeout)
+                                  .maxConns(maxConns)
+                                  .maxConnsPerRoute(maxConnsPerRoute)
+                                  .trustStoreFile(trustStoreFile)
+                                  .trustStorePassword(trustStorePassword)
+                                  .build());
+    }
+
+    public AbstractRestClient(String url, RestClientConfig config) {
+        this.baseUrl = url;
+        this.client = buildOkHttpClient(config);
+        this.authContext = new InheritableThreadLocal<>();
+    }
+
+    private static RequestBody buildRequestBody(Object body, RestHeaders headers) {
+        String contentType = parseContentType(headers);
+        String bodyContent;
+        if (RestHeaders.APPLICATION_JSON.equals(contentType)) {
+            if (body == null) {
+                bodyContent = "{}";
+            } else if (body instanceof String) {
+                bodyContent = (String) body;
+            } else {
+                bodyContent = JsonUtilCommon.toJson(body);
+            }
+        } else {
+            bodyContent = String.valueOf(body);
+        }
+        RequestBody requestBody = RequestBody.create(bodyContent.getBytes(),
+                                                     MediaType.parse(contentType));
+
+        if (headers != null &&
+            "gzip".equals(headers.get(RestHeaders.CONTENT_ENCODING))) {
+            requestBody = gzipBody(requestBody);
+        }
+        return requestBody;
+    }
+
+    private static RequestBody gzipBody(final RequestBody body) {
+        return new RequestBody() {
+            @Override
+            public MediaType contentType() {
+                return body.contentType();
+            }
+
+            @Override
+            public long contentLength() {
+                return -1; // We don't know the compressed length in advance!
+            }
+
+            @Override
+            public void writeTo(@NotNull BufferedSink sink) throws IOException {
+                BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
+                body.writeTo(gzipSink);
+                gzipSink.close();
+            }
+        };
+    }
+
+    private static String parseContentType(RestHeaders headers) {
+        if (headers != null) {
+            String contentType = headers.get(RestHeaders.CONTENT_TYPE);
+            if (contentType != null) {
+                return contentType;
+            }
+        }
+        return RestHeaders.APPLICATION_JSON;
+    }
+
+    private OkHttpClient buildOkHttpClient(RestClientConfig config) {
+        OkHttpClient.Builder builder = new OkHttpClient.Builder();
+
+        if (config.getTimeout() != null) {
+            builder.connectTimeout(config.getTimeout(), TimeUnit.MILLISECONDS)
+                   .readTimeout(config.getTimeout(), TimeUnit.MILLISECONDS);
+        }
+        if (config.getConnectTimeout() != null) {
+            builder.connectTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS);
+        }
+        if (config.getReadTimeout() != null) {
+            builder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
+        }
+
+        if (config.getMaxIdleConns() != null || config.getIdleTime() != null) {
+            ConnectionPool connectionPool = new ConnectionPool(config.getMaxIdleConns(),
+                                                               config.getIdleTime(),
+                                                               TimeUnit.SECONDS);
+            builder.connectionPool(connectionPool);
+        }
+
+        // auth header interceptor
+        if (StringUtils.isNotBlank(config.getUser()) &&
+            StringUtils.isNotBlank(config.getPassword())) {
+            builder.addInterceptor(new OkHttpBasicAuthInterceptor(config.getUser(),
+                                                                  config.getPassword()));
+        }
+        if (StringUtils.isNotBlank(config.getToken())) {
+            builder.addInterceptor(new OkHttpTokenInterceptor(config.getToken()));
+        }
+
+        // ssl
+        configSsl(builder, this.baseUrl, config.getTrustStoreFile(),
+                  config.getTrustStorePassword());
+
+        // Execute builder callback before builder.build() for user configs
+        if (config.getBuilderCallback() != null) {
+            config.getBuilderCallback().accept(builder);
+        }
+
+        OkHttpClient okHttpClient = builder.build();
+
+        if (config.getMaxConns() != null) {
+            okHttpClient.dispatcher().setMaxRequests(config.getMaxConns());
+        }
+
+        if (config.getMaxConnsPerRoute() != null) {
+            okHttpClient.dispatcher().setMaxRequestsPerHost(config.getMaxConnsPerRoute());
+        }
+
+        return okHttpClient;
+    }
+
+    @SneakyThrows
+    private void configSsl(OkHttpClient.Builder builder, String url, String trustStoreFile,
+                           String trustStorePass) {
+        if (StringUtils.isBlank(trustStoreFile) || StringUtils.isBlank(trustStorePass)) {
+            return;
+        }
+
+        X509TrustManager trustManager = trustManagerForCertificates(trustStoreFile, trustStorePass);
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(null, new TrustManager[]{trustManager}, null);
+        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+
+        builder.sslSocketFactory(sslSocketFactory, trustManager)
+               .hostnameVerifier(new HostNameVerifier(url));
+    }
+
+    @Override
+    public RestResult post(String path, Object object) {
+        return this.post(path, object, null, null);
+    }
+
+    @Override
+    public RestResult post(String path, Object object, RestHeaders headers) {
+        return this.post(path, object, headers, null);
+    }
+
+    @Override
+    public RestResult post(String path, Object object, Map<String, Object> params) {
+        return this.post(path, object, null, params);
+    }
+
+    private Request.Builder genRequestBuilder(String path, String id, RestHeaders headers,
+                                              Map<String, Object> params) {
+        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(this.baseUrl))
+                                            .newBuilder()
+                                            .addPathSegments(path);
+        if (id != null) {
+            urlBuilder.addPathSegment(id);
+        }
+
+        if (params != null) {
+            params.forEach((name, value) -> {
+                if (value == null) {
+                    return;
+                }
+
+                if (value instanceof Collection) {
+                    for (Object i : (Collection<?>) value) {
+                        urlBuilder.addQueryParameter(name, String.valueOf(i));
+                    }
+                } else {
+                    urlBuilder.addQueryParameter(name, String.valueOf(value));
+                }
+            });
+        }
+
+        Request.Builder builder = newRequestBuilder().url(urlBuilder.build());
+
+        if (headers != null) {
+            builder.headers(headers.toOkHttpHeader());
+        }
+
+        this.attachAuthToRequest(builder);
+
+        return builder;
+    }
+
+    /**
+     * In order to provide subclasses with overloading opportunities
+     */
+    protected Request.Builder newRequestBuilder() {
+        return new Request.Builder();
+    }
+
+    @SneakyThrows
+    @Override
+    public RestResult post(String path, Object object, RestHeaders headers,
+                           Map<String, Object> params) {
+        Request.Builder requestBuilder = genRequestBuilder(path, null, headers, params);
+        requestBuilder.post(buildRequestBody(object, headers));
+
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 200, 201, 202);
+            return new RestResult(response);
+        }
+    }
+
+    @Override
+    public RestResult put(String path, String id, Object object) {
+        return this.put(path, id, object, ImmutableMap.of());
+    }
+
+    @Override
+    public RestResult put(String path, String id, Object object, RestHeaders headers) {
+        return this.put(path, id, object, headers, null);
+    }
+
+    @Override
+    public RestResult put(String path, String id, Object object, Map<String, Object> params) {
+        return this.put(path, id, object, null, params);
+    }
+
+    @SneakyThrows
+    @Override
+    public RestResult put(String path, String id, Object object,
+                          RestHeaders headers,
+                          Map<String, Object> params) {
+        Request.Builder requestBuilder = genRequestBuilder(path, id, headers, params);
+        requestBuilder.put(buildRequestBody(object, headers));
+
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 200, 202);
+            return new RestResult(response);
+        }
+    }
+
+    @Override
+    public RestResult get(String path) {
+        return this.get(path, null, ImmutableMap.of());
+    }
+
+    @Override
+    public RestResult get(String path, Map<String, Object> params) {
+        return this.get(path, null, params);
+    }
+
+    @Override
+    public RestResult get(String path, String id) {
+        return this.get(path, id, ImmutableMap.of());
+    }
+
+    @SneakyThrows
+    private RestResult get(String path, String id, Map<String, Object> params) {
+        Request.Builder requestBuilder = genRequestBuilder(path, id, null, params);
+
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 200);
+            return new RestResult(response);
+        }
+    }
+
+    @Override
+    public RestResult delete(String path, Map<String, Object> params) {
+        return this.delete(path, null, params);
+    }
+
+    @Override
+    public RestResult delete(String path, String id) {
+        return this.delete(path, id, ImmutableMap.of());
+    }
+
+    @SneakyThrows
+    private RestResult delete(String path, String id,
+                              Map<String, Object> params) {
+        Request.Builder requestBuilder = genRequestBuilder(path, id, null, params);
+        requestBuilder.delete();
+
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 204, 202);
+            return new RestResult(response);
+        }
+    }
+
+    protected abstract void checkStatus(Response response, int... statuses);
+
+    @SneakyThrows
+    protected Response request(Request.Builder requestBuilder) {
+        return this.client.newCall(requestBuilder.build()).execute();
+    }
+
+    @SneakyThrows
+    @Override
+    public void close() {
+        if (this.client != null) {
+            this.client.dispatcher().executorService().shutdown();
+            this.client.connectionPool().evictAll();
+            if (this.client.cache() != null) {
+                this.client.cache().close();
+            }
+        }
+    }
+
+    public static String encode(String raw) {
+        try {
+            return URLEncoder.encode(raw, StandardCharsets.UTF_8.toString()).replace("+", "%2B");
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException("Failed to encode string: " + raw, e);
+        }
+    }
+
+    public void resetAuthContext() {
+        this.authContext.remove();
+    }
+
+    public String getAuthContext() {
+        return this.authContext.get();
+    }
+
+    public void setAuthContext(String auth) {
+        this.authContext.set(auth);
+    }
+
+    private void attachAuthToRequest(Request.Builder builder) {
+        // Add auth header
+        String auth = this.getAuthContext();
+        if (StringUtils.isNotEmpty(auth)) {
+            builder.addHeader(RestHeaders.AUTHORIZATION, auth);
+        }
+    }
+
+    @SneakyThrows
+    private X509TrustManager trustManagerForCertificates(String trustStoreFile,
+                                                         String trustStorePass) {
+        char[] password = trustStorePass.toCharArray();
+
+        // load keyStore
+        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        try (FileInputStream in = new FileInputStream(trustStoreFile)) {
+            keyStore.load(in, password);
+        }
+
+        TrustManagerFactory trustManagerFactory =
+                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        trustManagerFactory.init(keyStore);
+
+        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
+            throw new IllegalStateException("Unexpected default trust managers:" +
+                                            Arrays.toString(trustManagers));
+        }
+        return (X509TrustManager) trustManagers[0];
+    }
+
+    public static class HostNameVerifier implements HostnameVerifier {
+
+        private final String url;
+
+        public HostNameVerifier(String url) {
+            if (!url.startsWith("http://") && !url.startsWith("https://")) {
+                url = "http://" + url;
+            }
+            url = URI.create(url).getHost();
+            this.url = url;
+        }
+
+        @Override
+        public boolean verify(String hostname, SSLSession session) {
+            if (!this.url.isEmpty() && this.url.endsWith(hostname)) {
+                return true;
+            } else {
+                HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier();
+                return verifier.verify(hostname, session);
+            }
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/ClientException.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/ClientException.java
new file mode 100644
index 0000000000..ba954a28ff
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/ClientException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.hugegraph.rest;
+
+public class ClientException extends RuntimeException {
+
+    private static final long serialVersionUID = 814572040103754705L;
+
+    public ClientException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ClientException(String message, Object... args) {
+        super(String.format(message, args));
+    }
+
+    public ClientException(String message, Throwable cause, Object... args) {
+        super(String.format(message, args), cause);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpBasicAuthInterceptor.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpBasicAuthInterceptor.java
new file mode 100644
index 0000000000..f7b1509f50
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpBasicAuthInterceptor.java
@@ -0,0 +1,47 @@
+/*
+ * 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.hugegraph.rest;
+
+import java.io.IOException;
+
+import okhttp3.Credentials;
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class OkHttpBasicAuthInterceptor implements Interceptor {
+
+    private final String credentials;
+
+    public OkHttpBasicAuthInterceptor(String user, String password) {
+        this.credentials = Credentials.basic(user, password);
+    }
+
+    @Override
+    public Response intercept(Chain chain) throws IOException {
+        Request request = chain.request();
+        if (request.header(RestHeaders.AUTHORIZATION) == null) {
+            Request authenticatedRequest = request.newBuilder()
+                                                  .header(RestHeaders.AUTHORIZATION,
+                                                          this.credentials)
+                                                  .build();
+            return chain.proceed(authenticatedRequest);
+        }
+        return chain.proceed(request);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpTokenInterceptor.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpTokenInterceptor.java
new file mode 100644
index 0000000000..f564033225
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpTokenInterceptor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.hugegraph.rest;
+
+import static org.apache.hugegraph.rest.RestHeaders.AUTHORIZATION;
+import static org.apache.hugegraph.rest.RestHeaders.BEARER_PREFIX;
+
+import java.io.IOException;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+
+public class OkHttpTokenInterceptor implements Interceptor {
+
+    private final String token;
+
+    public OkHttpTokenInterceptor(String token) {
+        this.token = token;
+    }
+
+    @Override
+    public Response intercept(Chain chain) throws IOException {
+        Request request = chain.request();
+        if (request.header(AUTHORIZATION) == null) {
+            Request authenticatedRequest = request.newBuilder()
+                                                  .header(AUTHORIZATION,
+                                                          BEARER_PREFIX + this.token)
+                                                  .build();
+            return chain.proceed(authenticatedRequest);
+        }
+        return chain.proceed(request);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClient.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClient.java
new file mode 100644
index 0000000000..d5b58d9fc6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClient.java
@@ -0,0 +1,63 @@
+/*
+ * 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.hugegraph.rest;
+
+import java.util.Map;
+
+public interface RestClient {
+    /**
+     * Post method
+     */
+    RestResult post(String path, Object object);
+
+    RestResult post(String path, Object object, RestHeaders headers);
+
+    RestResult post(String path, Object object, Map<String, Object> params);
+
+    RestResult post(String path, Object object, RestHeaders headers, Map<String, Object> params);
+
+    /**
+     * Put method
+     */
+    RestResult put(String path, String id, Object object);
+
+    RestResult put(String path, String id, Object object, RestHeaders headers);
+
+    RestResult put(String path, String id, Object object, Map<String, Object> params);
+
+    RestResult put(String path, String id, Object object, RestHeaders headers,
+                   Map<String, Object> params);
+
+    /**
+     * Get method
+     */
+    RestResult get(String path);
+
+    RestResult get(String path, Map<String, Object> params);
+
+    RestResult get(String path, String id);
+
+    /**
+     * Delete method
+     */
+    RestResult delete(String path, Map<String, Object> params);
+
+    RestResult delete(String path, String id);
+
+    void close();
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClientConfig.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClientConfig.java
new file mode 100644
index 0000000000..c8e766ba7e
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClientConfig.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.hugegraph.rest;
+
+import java.util.function.Consumer;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import okhttp3.OkHttpClient;
+
+@Builder
+@Getter
+@Setter
+@SuppressWarnings("unused")
+public class RestClientConfig {
+
+    private String user;
+    private String password;
+    private String token;
+    /**
+     * @deprecated use connectTimeout and readTimeout instead
+     */
+    @Deprecated
+    private Integer timeout;
+    /** unit in milliseconds */
+    private Integer connectTimeout;
+    /** unit in milliseconds */
+    private Integer readTimeout;
+    private Integer maxConns;
+    private Integer maxConnsPerRoute;
+    // unit in seconds
+    private Integer idleTime = 30;
+    private Integer maxIdleConns = 5;
+    private String trustStoreFile;
+    private String trustStorePassword;
+    private Consumer<OkHttpClient.Builder> builderCallback;
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestHeaders.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestHeaders.java
new file mode 100644
index 0000000000..03c082ede3
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestHeaders.java
@@ -0,0 +1,90 @@
+/*
+ * 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.hugegraph.rest;
+
+import java.util.Date;
+import java.util.Iterator;
+
+import kotlin.Pair;
+
+public class RestHeaders {
+
+    public static final String CONTENT_TYPE = "Content-Type";
+
+    public static final String CONTENT_ENCODING = "Content-Encoding";
+
+    public static final String AUTHORIZATION = "Authorization";
+
+    public static final String APPLICATION_JSON = "application/json";
+
+    public static final String BEARER_PREFIX = "Bearer ";
+
+    private final okhttp3.Headers.Builder headersBuilder;
+
+    public RestHeaders() {
+        this.headersBuilder = new okhttp3.Headers.Builder();
+    }
+
+    public static RestHeaders convertToRestHeaders(okhttp3.Headers headers) {
+        RestHeaders restHeaders = new RestHeaders();
+
+        if (headers != null) {
+            Iterator<Pair<String, String>> iter = headers.iterator();
+            while (iter.hasNext()) {
+                Pair<String, String> pair = iter.next();
+                restHeaders.add(pair.getFirst(), pair.getSecond());
+            }
+        }
+        return restHeaders;
+    }
+
+    public String get(String key) {
+        return this.headersBuilder.get(key);
+    }
+
+    public Date getDate(String key) {
+        return this.headersBuilder.build().getDate(key);
+    }
+
+    public RestHeaders add(String key, String value) {
+        this.headersBuilder.add(key, value);
+        return this;
+    }
+
+    public RestHeaders add(String key, Date value) {
+        this.headersBuilder.add(key, value);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.toOkHttpHeader().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof RestHeaders) {
+            return this.toOkHttpHeader().equals(((RestHeaders) obj).toOkHttpHeader());
+        }
+        return false;
+    }
+
+    public okhttp3.Headers toOkHttpHeader() {
+        return this.headersBuilder.build();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java
new file mode 100644
index 0000000000..0aa482b067
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java
@@ -0,0 +1,114 @@
+/*
+ * 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.hugegraph.rest;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.Module;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import lombok.SneakyThrows;
+import okhttp3.Response;
+
+public class RestResult {
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    private final int status;
+    private final RestHeaders headers;
+    private final String content;
+
+    public RestResult(Response response) {
+        this(response.code(), getResponseContent(response),
+             RestHeaders.convertToRestHeaders(response.headers()));
+    }
+
+    public RestResult(int status, String content, RestHeaders headers) {
+        this.status = status;
+        this.headers = headers;
+        this.content = content;
+    }
+
+    @SneakyThrows
+    private static String getResponseContent(Response response) {
+        return response.body().string();
+    }
+
+    public static void registerModule(Module module) {
+        MAPPER.registerModule(module);
+    }
+
+    public int status() {
+        return this.status;
+    }
+
+    public RestHeaders headers() {
+        return this.headers;
+    }
+
+    public String content() {
+        return this.content;
+    }
+
+    public <T> T readObject(Class<T> clazz) {
+        try {
+            return MAPPER.readValue(this.content, clazz);
+        } catch (Exception e) {
+            throw new SerializeException("Failed to deserialize: %s", e, this.content);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public <T> List<T> readList(String key, Class<T> clazz) {
+        try {
+            JsonNode root = MAPPER.readTree(this.content);
+            JsonNode element = root.get(key);
+            if (element == null) {
+                throw new SerializeException("Can't find value of the key: %s in json.", key);
+            }
+            JavaType type = MAPPER.getTypeFactory()
+                                  .constructParametrizedType(ArrayList.class,
+                                                             List.class, clazz);
+            return MAPPER.convertValue(element, type);
+        } catch (IOException e) {
+            throw new SerializeException("Failed to deserialize %s", e, this.content);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public <T> List<T> readList(Class<T> clazz) {
+        JavaType type = MAPPER.getTypeFactory()
+                              .constructParametrizedType(ArrayList.class,
+                                                         List.class, clazz);
+        try {
+            return MAPPER.readValue(this.content, type);
+        } catch (IOException e) {
+            throw new SerializeException("Failed to deserialize %s", e, this.content);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return String.format("{status=%s, headers=%s, content=%s}", this.status, this.headers,
+                             this.content);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/SerializeException.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/SerializeException.java
new file mode 100644
index 0000000000..857ea9427d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/SerializeException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.hugegraph.rest;
+
+public class SerializeException extends ClientException {
+
+    private static final long serialVersionUID = -4622753445618619311L;
+
+    public SerializeException(String message, Throwable e) {
+        super(message, e);
+    }
+
+    public SerializeException(String message, Object... args) {
+        super(message, args);
+    }
+
+    public SerializeException(String message, Throwable e, Object... args) {
+        super(message, e, args);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/testutil/Assert.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/testutil/Assert.java
new file mode 100644
index 0000000000..bd82eef6a9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/testutil/Assert.java
@@ -0,0 +1,164 @@
+/*
+ * 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.hugegraph.testutil;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Description;
+
+public class Assert extends org.junit.Assert {
+
+    @FunctionalInterface
+    public interface ThrowableRunnable {
+        void run() throws Throwable;
+    }
+
+    @FunctionalInterface
+    public interface ThrowableConsumer<T> {
+        void accept(T t) throws Throwable;
+    }
+
+    public static void assertThrows(Class<? extends Throwable> clazz,
+                                    ThrowableRunnable runnable,
+                                    Consumer<Throwable> exceptionConsumer) {
+        Throwable expectedException = assertThrows(clazz, runnable);
+        assert expectedException != null;
+        exceptionConsumer.accept(expectedException);
+    }
+
+    public static Throwable assertThrows(Class<? extends Throwable> clazz,
+                                         ThrowableRunnable runnable) {
+        try {
+            // expect throwing here
+            runnable.run();
+        } catch (Throwable e) {
+            if (!clazz.isInstance(e)) {
+                // exception type not matched
+                Assert.fail(String.format("Bad exception type %s(expected %s)",
+                                          e.getClass().getName(), clazz.getName()));
+            }
+
+            return e;
+        }
+
+        // no exception
+        Assert.fail(String.format("No exception was thrown(expected %s)",
+                                  clazz.getName()));
+
+        // unavailable
+        assert false;
+        return null;
+    }
+
+    public static void assertEquals(byte expected, Object actual) {
+        org.junit.Assert.assertEquals(expected, actual);
+    }
+
+    public static void assertEquals(short expected, Object actual) {
+        org.junit.Assert.assertEquals(expected, actual);
+    }
+
+    public static void assertEquals(char expected, Object actual) {
+        org.junit.Assert.assertEquals(expected, actual);
+    }
+
+    public static void assertEquals(int expected, Object actual) {
+        org.junit.Assert.assertEquals(expected, actual);
+    }
+
+    public static void assertEquals(long expected, Object actual) {
+        org.junit.Assert.assertEquals(expected, actual);
+    }
+
+    public static void assertEquals(float expected, Object actual) {
+        org.junit.Assert.assertEquals(expected, actual);
+    }
+
+    public static void assertEquals(double expected, Object actual) {
+        org.junit.Assert.assertEquals(expected, actual);
+    }
+
+    @SuppressWarnings("deprecation")
+    public static void assertGt(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp > 0;
+        }, ">"));
+    }
+
+    @SuppressWarnings("deprecation")
+    public static void assertGte(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp >= 0;
+        }, ">="));
+    }
+
+    @SuppressWarnings("deprecation")
+    public static void assertLt(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp < 0;
+        }, "<"));
+    }
+
+    @SuppressWarnings("deprecation")
+    public static void assertLte(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp <= 0;
+        }, "<="));
+    }
+
+    @SuppressWarnings("deprecation")
+    public static void assertContains(String sub, String actual) {
+        org.junit.Assert.assertThat(actual, CoreMatchers.containsString(sub));
+    }
+
+    @SuppressWarnings("deprecation")
+    public static void assertInstanceOf(Class<?> clazz, Object object) {
+        org.junit.Assert.assertThat(object, CoreMatchers.instanceOf(clazz));
+    }
+
+    private static class NumberMatcher extends BaseMatcher<Object> {
+
+        private final String symbol;
+        private final Number expected;
+        private final Function<Integer, Boolean> cmp;
+
+        NumberMatcher(Number expected, Function<Integer, Boolean> cmp, String symbol) {
+            this.expected = expected;
+            this.cmp = cmp;
+            this.symbol = symbol;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean matches(Object actual) {
+            Assert.assertInstanceOf(this.expected.getClass(), actual);
+            Assert.assertInstanceOf(Comparable.class, actual);
+            int cmp = ((Comparable<Number>) actual).compareTo(this.expected);
+            return this.cmp.apply(cmp);
+        }
+
+        @Override
+        public void describeTo(Description desc) {
+            desc.appendText("a number ").appendText(this.symbol)
+                .appendText(" ").appendText(this.expected.toString());
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/testutil/Whitebox.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/testutil/Whitebox.java
new file mode 100644
index 0000000000..73d8ee2afd
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/testutil/Whitebox.java
@@ -0,0 +1,184 @@
+/*
+ * 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.hugegraph.testutil;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Objects;
+
+import org.apache.hugegraph.util.E;
+import com.google.common.primitives.Primitives;
+
+public class Whitebox {
+
+    public static final char SEPARATOR = '.';
+
+    public static void setInternalState(Object target,
+                                        String fieldName, Object value) {
+        assert target != null;
+        assert fieldName != null;
+        int sep = fieldName.lastIndexOf(SEPARATOR);
+        if (sep > 0) {
+            String prefix = fieldName.substring(0, sep);
+            Object result = getInternalState(target, prefix);
+            E.checkArgument(result != null,
+                            "Can't set value on null field: `%s.%s`",
+                            target, prefix);
+            target = result;
+            fieldName = fieldName.substring(sep + 1);
+        }
+
+        Class<?> c = target instanceof Class<?> ?
+                     (Class<?>) target : target.getClass();
+        try {
+            Field f = getFieldFromHierarchy(c, fieldName);
+            f.setAccessible(true);
+            f.set(target, value);
+        } catch (Exception e) {
+            throw new RuntimeException(String.format(
+                      "Can't set value of '%s' against object '%s'",
+                      fieldName, target), e);
+        }
+    }
+
+    public static <T> T getInternalState(Object target, String fieldName) {
+        assert fieldName != null;
+        int sep = fieldName.indexOf(SEPARATOR);
+        if (sep > 0) {
+            String field = fieldName.substring(0, sep);
+            Object value = getInternalState(target, field);
+            field = fieldName.substring(sep + 1);
+            return getInternalState(value, field);
+        }
+
+        Class<?> c = target instanceof Class<?> ?
+                     (Class<?>) target : target.getClass();
+        try {
+            Field f = getFieldFromHierarchy(c, fieldName);
+            f.setAccessible(true);
+            @SuppressWarnings("unchecked")
+            T result = (T) f.get(target);
+            return result;
+        } catch (Exception e) {
+            throw new RuntimeException(String.format(
+                      "Unable to get internal state on field '%s' of %s",
+                      fieldName, target), e);
+        }
+    }
+
+    private static Field getFieldFromHierarchy(Class<?> clazz, String field) {
+        Field f = getField(clazz, field);
+        while (f == null && clazz != Object.class) {
+            clazz = clazz.getSuperclass();
+            f = getField(clazz, field);
+        }
+        if (f == null) {
+            throw new RuntimeException(String.format(
+                      "Not declared field '%s' in class '%s'",
+                      field, clazz.getSimpleName()));
+        }
+        return f;
+    }
+
+    private static Field getField(Class<?> clazz, String field) {
+        try {
+            return clazz.getDeclaredField(field);
+        } catch (NoSuchFieldException e) {
+            return null;
+        }
+    }
+
+    public static <T> T invokeStatic(Class<?> clazz, String methodName,
+                                     Object... args) {
+        return invoke(clazz, methodName, (Object) null, args);
+    }
+
+    public static <T> T invokeStatic(Class<?> clazz,  Class<?>[] classes,
+                                     String methodName, Object... args) {
+        return invoke(clazz, classes, methodName, (Object) null, args);
+    }
+
+    public static <T> T invoke(Object owner, String field,
+                               String methodName, Object... args) {
+        Object self = getInternalState(owner, field);
+        Objects.requireNonNull(self);
+        return invoke(self.getClass(), methodName, self, args);
+    }
+
+    public static <T> T invoke(Object owner, String field, Class<?>[] classes,
+                               String methodName, Object... args) {
+        Object self = getInternalState(owner, field);
+        Objects.requireNonNull(self);
+        return invoke(self.getClass(), classes, methodName, self, args);
+    }
+
+    public static <T> T invoke(Class<?> clazz, String methodName,
+                               Object self, Object... args) {
+        Class<?>[] classes = new Class<?>[args.length];
+        int i = 0;
+        for (Object arg : args) {
+            E.checkArgument(arg != null, "The argument can't be null");
+            classes[i++] = Primitives.unwrap(arg.getClass());
+        }
+        return invoke(clazz, classes, methodName, self, args);
+    }
+
+    public static <T> T invoke(Class<?> clazz, Class<?>[] classes,
+                               String methodName, Object self, Object... args) {
+        Method method = method(clazz, methodName, classes);
+        try {
+            method.setAccessible(true);
+            @SuppressWarnings("unchecked")
+            T result = (T) method.invoke(self, args);
+            return result;
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(String.format(
+                      "Can't invoke method '%s' of class '%s': %s",
+                      methodName, clazz, e.getMessage()), e);
+        } catch (InvocationTargetException e) {
+            Throwable target = e.getTargetException();
+            if (target instanceof RuntimeException) {
+                throw (RuntimeException) target;
+            }
+            throw new RuntimeException(String.format(
+                      "Can't invoke method '%s' of class '%s': %s",
+                      methodName, clazz, target.getMessage()), target);
+        }
+    }
+
+    public static Method method(Class<?> clazz, String methodName,
+                                Class<?>[] argsClasses) {
+        try {
+            return clazz.getDeclaredMethod(methodName, argsClasses);
+        } catch (NoSuchMethodException e) {
+            Class<?> superclass = clazz.getSuperclass();
+            if (superclass != null) {
+                try {
+                    return method(superclass, methodName, argsClasses);
+                } catch (Exception ignored) {
+                    // pass
+                }
+            }
+            throw new RuntimeException(String.format(
+                      "Can't find method '%s' with args %s of class '%s'",
+                      methodName, Arrays.asList(argsClasses), clazz), e);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/Bytes.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/Bytes.java
new file mode 100644
index 0000000000..4abd57df44
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/Bytes.java
@@ -0,0 +1,103 @@
+/*
+ * 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.hugegraph.util;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * TODO: extends com.google.common.primitives.Bytes
+ */
+public final class Bytes {
+
+    public static final long BASE = 1024L;
+    public static final long KB = BASE;
+    public static final long MB = KB * BASE;
+    public static final long GB = MB * BASE;
+    public static final long TB = GB * KB;
+    public static final long PB = GB * MB;
+    public static final long EB = GB * GB;
+
+    private static final Comparator<byte[]> CMP = UnsignedBytes.lexicographicalComparator();
+
+    public static int compare(byte[] bytes1, byte[] bytes2) {
+        return CMP.compare(bytes1, bytes2);
+    }
+
+    public static byte[] concat(byte[] bytes1, byte[] bytes2) {
+        byte[] result = new byte[bytes1.length + bytes2.length];
+        System.arraycopy(bytes1, 0, result, 0, bytes1.length);
+        System.arraycopy(bytes2, 0, result, bytes1.length, bytes2.length);
+        return result;
+    }
+
+    public static boolean prefixWith(byte[] bytes, byte[] prefix) {
+        if (bytes.length < prefix.length) {
+            return false;
+        }
+        for (int i = 0; i < prefix.length; i++) {
+            if (bytes[i] != prefix[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static boolean contains(byte[] bytes, byte value) {
+        for (byte b : bytes) {
+            if (b == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static int indexOf(byte[] bytes, byte value) {
+        for (int i = 0; i < bytes.length; i++) {
+            if (bytes[i] == value) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public static boolean equals(byte[] bytes1, byte[] bytes2) {
+        return Arrays.equals(bytes1, bytes2);
+    }
+
+    public static String toHex(byte b) {
+        return toHex(new byte[]{b});
+    }
+
+    public static String toHex(byte[] bytes) {
+        return new String(Hex.encodeHex(bytes));
+    }
+
+    public static byte[] fromHex(String hex) {
+        try {
+            return Hex.decodeHex(hex.toCharArray());
+        } catch (DecoderException e) {
+            throw new RuntimeException("Failed to decode hex: " + hex, e);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/CheckSocket.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/CheckSocket.java
new file mode 100644
index 0000000000..09a36b9a36
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/CheckSocket.java
@@ -0,0 +1,37 @@
+/*
+ * 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.hugegraph.util;
+
+import static java.lang.System.exit;
+
+import java.net.InetAddress;
+import java.net.Socket;
+
+public final class CheckSocket {
+
+    public static void main(String[] args) {
+        try {
+            // Check if the socket connection can be closed normally
+            new Socket(InetAddress.getByName(args[0]), Integer.parseInt(args[1])).close();
+            exit(0);
+        } catch (Exception e) {
+            e.printStackTrace();
+            exit(-1);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/CollectionUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/CollectionUtil.java
new file mode 100644
index 0000000000..f719b8a552
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/CollectionUtil.java
@@ -0,0 +1,448 @@
+/*
+ * 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.hugegraph.util;
+
+import java.lang.reflect.Array;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.Function;
+
+public final class CollectionUtil {
+
+    public static <T> Set<T> toSet(Object object) {
+        E.checkNotNull(object, "object");
+        Set<T> set = InsertionOrderUtil.newSet();
+        fillCollection(set, object);
+        return set;
+    }
+
+    public static <T> List<T> toList(Object object) {
+        E.checkNotNull(object, "object");
+        List<T> list = new ArrayList<>();
+        fillCollection(list, object);
+        return list;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> void fillCollection(Collection<T> collection,
+                                           Object object) {
+        if (object.getClass().isArray()) {
+            int length = Array.getLength(object);
+            for (int i = 0; i < length; i++) {
+                collection.add((T) Array.get(object, i));
+            }
+        } else if (object instanceof Collection) {
+            collection.addAll((Collection<T>) object);
+        } else {
+            collection.add((T) object);
+        }
+    }
+
+    public static <T> boolean prefixOf(List<T> prefix, List<T> all) {
+        E.checkNotNull(prefix, "prefix");
+        E.checkNotNull(all, "all");
+
+        if (prefix.size() > all.size()) {
+            return false;
+        }
+
+        for (int i = 0; i < prefix.size(); i++) {
+            T first = prefix.get(i);
+            T second = all.get(i);
+            if (first == second) {
+                continue;
+            }
+            if (first == null || !first.equals(second)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static Set<Integer> randomSet(int min, int max, int count) {
+        E.checkArgument(max > min, "Invalid min/max: %s/%s", min, max);
+        E.checkArgument(0 < count && count <= max - min,
+                        "Invalid count %s", count);
+
+        Set<Integer> randoms = new HashSet<>();
+        while (randoms.size() < count) {
+            randoms.add(ThreadLocalRandom.current().nextInt(min, max));
+        }
+        return randoms;
+    }
+
+    public static boolean allUnique(Collection<?> collection) {
+        HashSet<Object> set = new HashSet<>(collection.size());
+        for (Object elem : collection) {
+            if (!set.add(elem)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Get sub-set of a set.
+     * @param original original set
+     * @param from index of start position
+     * @param to index of end position(exclude), but -1 means the last element
+     * @param <T> element type of set
+     * @return sub-set of original set [from, to)
+     */
+    public static <T> Set<T> subSet(Set<T> original, int from, int to) {
+        E.checkArgument(from >= 0,
+                        "Invalid from parameter of subSet(): %s", from);
+        if (to < 0) {
+            to = original.size();
+        } else {
+            E.checkArgument(to >= from,
+                            "Invalid to parameter of subSet(): %s", to);
+        }
+        List<T> list = new ArrayList<>(original);
+        return new LinkedHashSet<>(list.subList(from, to));
+    }
+
+    public static <T> Set<T> union(Collection<T> first, Collection<T> second) {
+        E.checkNotNull(first, "first");
+        E.checkNotNull(second, "second");
+        HashSet<T> results = new HashSet<>(first);
+        results.addAll(second);
+        return results;
+    }
+
+    /**
+     * Find the intersection of two collections, the original collections
+     * will not be modified
+     * @param first the first collection
+     * @param second the second collection
+     * @param <T> element type of collection
+     * @return intersection of the two collections
+     */
+    public static <T> Collection<T> intersect(Collection<T> first,
+                                              Collection<T> second) {
+        E.checkNotNull(first, "first");
+        E.checkNotNull(second, "second");
+
+        HashSet<T> results;
+        if (first instanceof HashSet) {
+            @SuppressWarnings("unchecked")
+            HashSet<T> clone = (HashSet<T>) ((HashSet<T>) first).clone();
+            results = clone;
+        } else {
+            results = new HashSet<>(first);
+        }
+        results.retainAll(second);
+        return results;
+    }
+
+    /**
+     * Find the intersection of two collections, note that the first collection
+     * will be modified and store the results
+     * @param first the first collection, it will be modified
+     * @param second the second collection
+     * @param <T> element type of collection
+     * @return intersection of the two collections
+     */
+    public static <T> Collection<T> intersectWithModify(Collection<T> first,
+                                                        Collection<T> second) {
+        E.checkNotNull(first, "first");
+        E.checkNotNull(second, "second");
+        first.retainAll(second);
+        return first;
+    }
+
+    public static <T> boolean hasIntersection(List<T> first, Set<T> second) {
+        E.checkNotNull(first, "first");
+        E.checkNotNull(second, "second");
+        for (T firstElem : first) {
+            if (second.contains(firstElem)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static <T> boolean hasIntersection(Set<T> first, Set<T> second) {
+        E.checkNotNull(first, "first");
+        E.checkNotNull(second, "second");
+        if (first.size() <= second.size()) {
+            for (T firstElem : first) {
+                if (second.contains(firstElem)) {
+                    return true;
+                }
+            }
+        } else {
+            for (T secondElem : second) {
+                if (first.contains(secondElem)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(
+                  Map<K, V> map, boolean incr) {
+        List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());
+        if (incr) {
+            list.sort(Map.Entry.comparingByKey());
+        } else {
+            list.sort(Collections.reverseOrder(Map.Entry.comparingByKey()));
+        }
+
+        Map<K, V> result = new LinkedHashMap<>();
+        for (Map.Entry<K, V> entry : list) {
+            result.put(entry.getKey(), entry.getValue());
+        }
+        return result;
+    }
+
+    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(
+                  Map<K, V> map, boolean incr) {
+        List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());
+        if (incr) {
+            list.sort(Map.Entry.comparingByValue());
+        } else {
+            list.sort(Collections.reverseOrder(Map.Entry.comparingByValue()));
+        }
+
+        Map<K, V> result = new LinkedHashMap<>();
+        for (Map.Entry<K, V> entry : list) {
+            result.put(entry.getKey(), entry.getValue());
+        }
+        return result;
+    }
+
+    /**
+     * Cross combine the A(n, n) combinations of each part in parts
+     * @param parts a list of part, like [{a,b}, {1,2}, {x,y}]
+     * @return List<List<Integer>> all combinations like
+     * [{a,b,1,2,x,y}, {a,b,1,2,y,x}, {a,b,2,1,x,y}, {a,b,2,1,y,x}...]
+     */
+    public static <T> List<List<T>> crossCombineParts(List<List<T>> parts) {
+        List<List<T>> results = new ArrayList<>();
+        Deque<List<T>> selected = new ArrayDeque<>();
+        crossCombineParts(parts, 0, selected, results);
+        return results;
+    }
+
+    private static <T> void crossCombineParts(List<List<T>> parts,
+                                              int level,
+                                              Deque<List<T>> selected,
+                                              List<List<T>> results) {
+        assert level < parts.size();
+        List<T> part = parts.get(level);
+        for (List<T> combination : anm(part)) {
+            selected.addLast(combination);
+
+            if (level < parts.size() - 1) {
+                crossCombineParts(parts, level + 1, selected, results);
+            } else if (level == parts.size() - 1) {
+                results.add(flatToList(selected));
+            }
+
+            selected.removeLast();
+        }
+    }
+
+    private static <T> List<T> flatToList(Deque<List<T>> parts) {
+        List<T> list = new ArrayList<>();
+        for (List<T> part : parts) {
+            list.addAll(part);
+        }
+        return list;
+    }
+
+    /**
+     * Traverse C(n, m) combinations of a list
+     * @param all list to contain all items for combination
+     * @param n m of C(n, m)
+     * @param m n of C(n, m)
+     * @return List<List<T>> all combinations
+     */
+    public static <T> List<List<T>> cnm(List<T> all, int n, int m) {
+        List<List<T>> combs = new ArrayList<>();
+        cnm(all, n, m, comb -> {
+            combs.add(comb);
+            return false;
+        });
+        return combs;
+    }
+
+    /**
+     * Traverse C(n, m) combinations of a list to find first matched
+     * result combination and call back with the result.
+     * @param all list to contain all items for combination
+     * @param n m of C(n, m)
+     * @param m n of C(n, m)
+     * @return true if matched any kind of items combination else false, the
+     * callback can always return false if you want to traverse all combinations
+     */
+    public static <T> boolean cnm(List<T> all, int n, int m,
+                                  Function<List<T>, Boolean> callback) {
+        return cnm(all, n, m, 0, null, callback);
+    }
+
+    /**
+     * Traverse C(n, m) combinations of a list to find first matched
+     * result combination and call back with the result.
+     * @param all list to contain all items for combination
+     * @param n n of C(n, m)
+     * @param m m of C(n, m)
+     * @param current current position in list
+     * @param selected list to contain selected items
+     * @return true if matched any kind of items combination else false, the
+     * callback can always return false if you want to traverse all combinations
+     */
+    private static <T> boolean cnm(List<T> all, int n, int m,
+                                   int current, List<T> selected,
+                                   Function<List<T>, Boolean> callback) {
+        assert n <= all.size();
+        assert m <= n;
+        assert current <= all.size();
+        if (selected == null) {
+            selected = new ArrayList<>(m);
+        }
+
+        if (m == 0) {
+            assert selected.size() > 0 : selected;
+            // All n items are selected
+            List<T> tmpResult = Collections.unmodifiableList(selected);
+            return callback.apply(tmpResult);
+        }
+        if (n == m) {
+            // No choice, select all n items, we don't update the `result` here
+            List<T> tmpResult = new ArrayList<>(selected);
+            tmpResult.addAll(all.subList(current, all.size()));
+            return callback.apply(tmpResult);
+        }
+
+        if (current >= all.size()) {
+            // Reach the end of items
+            return false;
+        }
+
+        // Select current item, continue to select C(m-1, n-1)
+        int index = selected.size();
+        selected.add(all.get(current));
+        ++current;
+        if (cnm(all, n - 1, m - 1, current, selected, callback)) {
+            // NOTE: we can pop the tailing items if want to keep result clear
+            return true;
+        }
+        // Not select current item, pop it and continue to select C(m-1, n)
+        selected.remove(index);
+        assert selected.size() == index : selected;
+        return cnm(all, n - 1, m, current, selected, callback);
+    }
+
+    /**
+     * Traverse A(n, m) combinations of a list with n = m = all.size()
+     * @param all list to contain all items for combination
+     * @return List<List<T>> all combinations
+     */
+    public static <T> List<List<T>> anm(List<T> all) {
+        return anm(all, all.size(), all.size());
+    }
+
+    /**
+     * Traverse A(n, m) combinations of a list
+     * @param all list to contain all items for combination
+     * @param n m of A(n, m)
+     * @param m n of A(n, m)
+     * @return List<List<T>> all combinations
+     */
+    public static <T> List<List<T>> anm(List<T> all, int n, int m) {
+        List<List<T>> combs = new ArrayList<>();
+        anm(all, n, m, comb -> {
+            combs.add(comb);
+            return false;
+        });
+        return combs;
+    }
+
+    /**
+     * Traverse A(n, m) combinations of a list to find first matched
+     * result combination and call back with the result.
+     * @param all list to contain all items for combination
+     * @param n m of A(n, m)
+     * @param m n of A(n, m)
+     * @return true if matched any kind of items combination else false, the
+     * callback can always return false if you want to traverse all combinations
+     */
+    public static <T> boolean anm(List<T> all, int n, int m,
+                                  Function<List<T>, Boolean> callback) {
+        return anm(all, n, m, null, callback);
+    }
+
+    /**
+     * Traverse A(n, m) combinations of a list to find first matched
+     * result combination and call back with the result.
+     * @param all list to contain all items for combination
+     * @param n m of A(n, m)
+     * @param m n of A(n, m)
+     * @param selected list to contain selected items
+     * @return true if matched any kind of items combination else false, the
+     * callback can always return false if you want to traverse all combinations
+     */
+    private static <T> boolean anm(List<T> all, int n, int m,
+                                   List<Integer> selected,
+                                   Function<List<T>, Boolean> callback) {
+        assert n <= all.size();
+        assert m <= n;
+        if (selected == null) {
+            selected = new ArrayList<>(m);
+        }
+
+        if (m == 0) {
+            // All n items are selected
+            List<T> tmpResult = new ArrayList<>();
+            for (int i : selected) {
+                tmpResult.add(all.get(i));
+            }
+            return callback.apply(tmpResult);
+        }
+
+        for (int i = 0; i < all.size(); i++) {
+            if (selected.contains(i)) {
+                continue;
+            }
+            int index = selected.size();
+            selected.add(i);
+
+            // Select current item, continue to select A(m-1, n-1)
+            if (anm(all, n - 1, m - 1, selected, callback)) {
+                return true;
+            }
+
+            selected.remove(index);
+            assert selected.size() == index : selected;
+        }
+        return false;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/DateUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/DateUtil.java
new file mode 100644
index 0000000000..4e7ce13de0
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/DateUtil.java
@@ -0,0 +1,77 @@
+/*
+ * 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.hugegraph.util;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.hugegraph.date.SafeDateFormat;
+import com.google.common.collect.ImmutableMap;
+
+public final class DateUtil {
+
+    public static final Date DATE_ZERO = new Date(0L);
+
+    private static final Map<String, String> VALID_DFS = ImmutableMap.of(
+            "^\\d{4}-\\d{1,2}-\\d{1,2}",
+            "yyyy-MM-dd",
+            "^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}",
+            "yyyy-MM-dd HH:mm:ss",
+            "^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}\\.\\d{1,3}",
+            "yyyy-MM-dd HH:mm:ss.SSS"
+    );
+
+    private static final Map<String, SafeDateFormat> DATE_FORMATS = new ConcurrentHashMap<>();
+
+    public static Date parse(String value) {
+        for (Map.Entry<String, String> entry : VALID_DFS.entrySet()) {
+            if (value.matches(entry.getKey())) {
+                return parse(value, entry.getValue());
+            }
+        }
+        throw new IllegalArgumentException(String.format(
+                  "Expected date format is: %s, but got '%s'", VALID_DFS.values(), value));
+    }
+
+    public static Date parse(String value, String df) {
+        SafeDateFormat dateFormat = getDateFormat(df);
+        return dateFormat.parse(value);
+    }
+
+    public static Date now() {
+        return new Date();
+    }
+
+    private static SafeDateFormat getDateFormat(String df) {
+        SafeDateFormat dateFormat = DATE_FORMATS.get(df);
+        if (dateFormat == null) {
+            dateFormat = new SafeDateFormat(df);
+            SafeDateFormat previous = DATE_FORMATS.putIfAbsent(df, dateFormat);
+            if (previous != null) {
+                dateFormat = previous;
+            }
+        }
+        return dateFormat;
+    }
+
+    public static Object toPattern(String df) {
+        SafeDateFormat dateFormat = getDateFormat(df);
+        return dateFormat.toPattern();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/E.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/E.java
new file mode 100644
index 0000000000..214add304b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/E.java
@@ -0,0 +1,66 @@
+/*
+ * 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.hugegraph.util;
+
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
+import com.google.common.base.Preconditions;
+
+public final class E {
+
+    public static void checkNotNull(Object object, String elem) {
+        Preconditions.checkNotNull(object, "The '%s' can't be null", elem);
+    }
+
+    public static void checkNotNull(Object object, String elem, String owner) {
+        Preconditions.checkNotNull(object,
+                                   "The '%s' of '%s' can't be null",
+                                   elem, owner);
+    }
+
+    public static void checkNotEmpty(Collection<?> collection, String elem) {
+        Preconditions.checkArgument(!collection.isEmpty(),
+                                    "The '%s' can't be empty", elem);
+    }
+
+    public static void checkNotEmpty(Collection<?> collection, String elem, String owner) {
+        Preconditions.checkArgument(!collection.isEmpty(),
+                                    "The '%s' of '%s' can't be empty",
+                                    elem, owner);
+    }
+
+    public static void checkArgument(boolean expression,
+                                     @Nullable String message,
+                                     @Nullable Object... args) {
+        Preconditions.checkArgument(expression, message, args);
+    }
+
+    public static void checkArgumentNotNull(Object object,
+                                            @Nullable String message,
+                                            @Nullable Object... args) {
+        Preconditions.checkArgument(object != null, message, args);
+    }
+
+    public static void checkState(boolean expression,
+                                  @Nullable String message,
+                                  @Nullable Object... args) {
+        Preconditions.checkState(expression, message, args);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ExceptionUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ExceptionUtil.java
new file mode 100644
index 0000000000..7142aea76a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ExceptionUtil.java
@@ -0,0 +1,49 @@
+/*
+ * 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.hugegraph.util;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public final class ExceptionUtil {
+
+    public static Throwable rootCause(Throwable e) {
+        Throwable cause = e;
+        while (cause.getCause() != null) {
+            cause = cause.getCause();
+        }
+        return cause;
+    }
+
+    public static RuntimeException transToRuntimeException(Throwable e) {
+        if (e instanceof RuntimeException) {
+            return (RuntimeException) e;
+        }
+        return new RuntimeException(rootCause(e).getMessage(), e);
+    }
+
+    public static <T> T futureGet(Future<T> future) {
+        try {
+            return future.get();
+        } catch (InterruptedException e) {
+            throw ExceptionUtil.transToRuntimeException(e);
+        } catch (ExecutionException e) {
+            throw ExceptionUtil.transToRuntimeException(e.getCause());
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ExecutorUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ExecutorUtil.java
new file mode 100644
index 0000000000..f0ff7f1172
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ExecutorUtil.java
@@ -0,0 +1,111 @@
+/*
+ * 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.hugegraph.util;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.apache.hugegraph.concurrent.PausableScheduledThreadPool;
+
+
+
+public final class ExecutorUtil {
+
+    public static ThreadPoolExecutor newDynamicThreadExecutor(String name,
+                                                              int corePoolSize,
+                                                              int maximumPoolSize) {
+
+        long keepAliveTime = 60L;
+        TimeUnit unit = TimeUnit.SECONDS;
+        ThreadFactory factory = new BasicThreadFactory.Builder()
+                .namingPattern(name)
+                .build();
+        CustomBlockingQueue<Runnable> workQueue = new CustomBlockingQueue<>();
+        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
+                corePoolSize,
+                maximumPoolSize,
+                keepAliveTime,
+                unit,
+                workQueue,
+                factory,
+                new ThreadPoolExecutor.CallerRunsPolicy()
+        );
+
+        workQueue.setThreadPoolExecutor(threadPoolExecutor);
+
+        return threadPoolExecutor;
+    }
+
+    static class CustomBlockingQueue<E> extends LinkedBlockingQueue<E> {
+        private ThreadPoolExecutor threadPoolExecutor;
+
+        public void setThreadPoolExecutor(ThreadPoolExecutor threadPoolExecutor) {
+            this.threadPoolExecutor = threadPoolExecutor;
+        }
+
+        @Override
+        public boolean offer(E e) {
+            if (threadPoolExecutor.getPoolSize() < threadPoolExecutor.getMaximumPoolSize()) {
+                return false;
+            }
+            return super.offer(e);
+        }
+    }
+
+    public static ExecutorService newFixedThreadPool(String name) {
+        return newFixedThreadPool(1, name);
+    }
+
+    public static ExecutorService newFixedThreadPool(int size, String name) {
+        ThreadFactory factory = new BasicThreadFactory.Builder()
+                                                      .namingPattern(name)
+                                                      .build();
+        return Executors.newFixedThreadPool(size, factory);
+    }
+
+    public static ScheduledExecutorService newScheduledThreadPool(String name) {
+        return newScheduledThreadPool(1, name);
+    }
+
+    public static ScheduledExecutorService newScheduledThreadPool(int size,
+                                                                  String name) {
+        ThreadFactory factory = new BasicThreadFactory.Builder()
+                                                      .namingPattern(name)
+                                                      .build();
+        return Executors.newScheduledThreadPool(size, factory);
+    }
+
+    public static PausableScheduledThreadPool newPausableScheduledThreadPool(
+                                              String name) {
+        return newPausableScheduledThreadPool(1, name);
+    }
+
+    public static PausableScheduledThreadPool newPausableScheduledThreadPool(
+                                              int size, String name) {
+        ThreadFactory factory = new BasicThreadFactory.Builder()
+                                                      .namingPattern(name)
+                                                      .build();
+        return new PausableScheduledThreadPool(size, factory);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/HashUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/HashUtil.java
new file mode 100644
index 0000000000..fa382f7d10
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/HashUtil.java
@@ -0,0 +1,44 @@
+/*
+ * 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.hugegraph.util;
+
+import java.nio.charset.Charset;
+
+import com.google.common.base.Charsets;
+import com.google.common.hash.Hashing;
+
+public final class HashUtil {
+
+    private static final Charset CHARSET = Charsets.UTF_8;
+
+    public static byte[] hash(byte[] bytes) {
+        return Hashing.murmur3_32().hashBytes(bytes).asBytes();
+    }
+
+    public static String hash(String value) {
+        return Hashing.murmur3_32().hashString(value, CHARSET).toString();
+    }
+
+    public static byte[] hash128(byte[] bytes) {
+        return Hashing.murmur3_128().hashBytes(bytes).asBytes();
+    }
+
+    public static String hash128(String value) {
+        return Hashing.murmur3_128().hashString(value, CHARSET).toString();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/InsertionOrderUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/InsertionOrderUtil.java
new file mode 100644
index 0000000000..bb80ff602d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/InsertionOrderUtil.java
@@ -0,0 +1,64 @@
+/*
+ * 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.hugegraph.util;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public final class InsertionOrderUtil {
+
+    public static <K, V> Map<K, V> newMap() {
+        return new LinkedHashMap<>();
+    }
+
+    public static <K, V> Map<K, V> newMap(int initialCapacity) {
+        return new LinkedHashMap<>(initialCapacity);
+    }
+
+    public static <K, V> Map<K, V> newMap(Map<K, V> origin) {
+        return new LinkedHashMap<>(origin);
+    }
+
+    public static <V> Set<V> newSet() {
+        return new LinkedHashSet<>();
+    }
+
+    public static <V> Set<V> newSet(int initialCapacity) {
+        return new LinkedHashSet<>(initialCapacity);
+    }
+
+    public static <V> Set<V> newSet(Set<V> origin) {
+        return new LinkedHashSet<>(origin);
+    }
+
+    public static <V> List<V> newList() {
+        return new ArrayList<>();
+    }
+
+    public static <V> List<V> newList(int initialCapacity) {
+        return new ArrayList<>(initialCapacity);
+    }
+
+    public static <V> List<V> newList(List<V> origin) {
+        return new ArrayList<>(origin);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/JsonUtilCommon.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/JsonUtilCommon.java
new file mode 100644
index 0000000000..ad0acebeec
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/JsonUtilCommon.java
@@ -0,0 +1,94 @@
+/*
+ * 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.hugegraph.util;
+
+import java.io.IOException;
+
+import org.apache.hugegraph.rest.SerializeException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.Module;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Utility class for JSON operations.
+ */
+public final class JsonUtilCommon {
+
+    /**
+     * ObjectMapper instance used for JSON operations.
+     */
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    /**
+     * Registers a module with the ObjectMapper.
+     *
+     * @param module the module to register
+     */
+    public static void registerModule(Module module) {
+        MAPPER.registerModule(module);
+    }
+
+    /**
+     * Converts an object to a JSON string.
+     *
+     * @param object the object to convert
+     * @return the JSON string representation of the object
+     * @throws SerializeException if the object cannot be serialized
+     */
+    public static String toJson(Object object) {
+        try {
+            return MAPPER.writeValueAsString(object);
+        } catch (JsonProcessingException e) {
+            throw new SerializeException("Failed to serialize object '%s'", e, object);
+        }
+    }
+
+    /**
+     * Converts a JSON string to an object of the specified class.
+     *
+     * @param json  the JSON string
+     * @param clazz the class of the object
+     * @return the object represented by the JSON string
+     * @throws SerializeException if the JSON string cannot be deserialized
+     */
+    public static <T> T fromJson(String json, Class<T> clazz) {
+        try {
+            return MAPPER.readValue(json, clazz);
+        } catch (IOException e) {
+            throw new SerializeException("Failed to deserialize json '%s'", e, json);
+        }
+    }
+
+    /**
+     * Converts a JsonNode to an object of the specified class.
+     *
+     * @param node  the JsonNode
+     * @param clazz the class of the object
+     * @return the object represented by the JsonNode
+     * @throws SerializeException if the JsonNode cannot be deserialized
+     */
+    public static <T> T convertValue(JsonNode node, Class<T> clazz) {
+        try {
+            return MAPPER.convertValue(node, clazz);
+        } catch (IllegalArgumentException e) {
+            throw new SerializeException("Failed to deserialize json node '%s'", e, node);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/Log.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/Log.java
new file mode 100644
index 0000000000..0338272d83
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/Log.java
@@ -0,0 +1,32 @@
+/*
+ * 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.hugegraph.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class Log {
+
+    public static Logger logger(String name) {
+        return LoggerFactory.getLogger(name);
+    }
+
+    public static Logger logger(Class<?> clazz) {
+        return LoggerFactory.getLogger(clazz);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/LongEncoding.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/LongEncoding.java
new file mode 100644
index 0000000000..761d72b907
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/LongEncoding.java
@@ -0,0 +1,151 @@
+/*
+ * 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.hugegraph.util;
+
+public final class LongEncoding {
+
+    private static final String B64_SYMBOLS =
+            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~";
+
+    private static final String LENGTH_SYMBOLS = "0123456789ABCDEF";
+    private static final char SORTABLE_NEG = LENGTH_SYMBOLS.charAt(0);
+    private static final char SIGNED_NEG = '-';
+
+    private static final long FULL_LONG = Long.MIN_VALUE;
+
+    public static String encodeNumber(Object number) {
+        Number num = NumericUtil.convertToNumber(number);
+        long value = NumericUtil.numberToSortableLong(num);
+        return encodeSortable(value);
+    }
+
+    public static Number decodeNumber(String str, Class<?> clazz) {
+        long value = decodeSortable(str);
+        return NumericUtil.sortableLongToNumber(value, clazz);
+    }
+
+    public static String encodeSortable(long num) {
+        boolean negative = false;
+        if (num < 0L) {
+            negative = true;
+            num += FULL_LONG;
+        }
+
+        String encoded = encode(num, B64_SYMBOLS);
+        int length = encoded.length();
+        E.checkArgument(length <= LENGTH_SYMBOLS.length(),
+                        "Length symbols can't represent encoded number '%s'",
+                        encoded);
+        StringBuilder sb = new StringBuilder(length + 2);
+        if (negative) {
+            sb.append(SORTABLE_NEG);
+        }
+        char len = LENGTH_SYMBOLS.charAt(length);
+        sb.append(len);
+        sb.append(encoded);
+
+        return sb.toString();
+    }
+
+    public static long decodeSortable(String str) {
+        E.checkArgument(str.length() >= 2,
+                        "Length of sortable encoded string must be >=2");
+        boolean negative = str.charAt(0) == SORTABLE_NEG;
+        int lengthPos = 0;
+        if (negative) {
+            lengthPos = 1;
+        }
+        int length = B64_SYMBOLS.indexOf(str.charAt(lengthPos));
+        E.checkArgument(length == str.length() - lengthPos - 1,
+                        "Can't decode illegal string '%s' with wrong length",
+                        str);
+        String encoded = str.substring(lengthPos + 1);
+        long value = decode(encoded, B64_SYMBOLS);
+        if (negative) {
+            value -= FULL_LONG;
+        }
+        return value;
+    }
+
+    public static String encodeSignedB64(long value) {
+        boolean negative = false;
+        if (value < 0L) {
+            negative = true;
+            if (value == FULL_LONG) {
+                return "-80000000000";
+            }
+            value = -value;
+        }
+        assert value >= 0L : value;
+        String encoded = encodeB64(value);
+        return negative ? SIGNED_NEG + encoded : encoded;
+    }
+
+    public static long decodeSignedB64(String value) {
+        boolean negative = false;
+        if (!value.isEmpty() && value.charAt(0) == SIGNED_NEG) {
+            negative = true;
+            value = value.substring(1);
+        }
+        long decoded = decodeB64(value);
+        return negative ? -decoded : decoded;
+    }
+
+    public static boolean validB64Char(char c) {
+        return B64_SYMBOLS.indexOf(c) != -1;
+    }
+
+    public static String encodeB64(long num) {
+        return encode(num, B64_SYMBOLS);
+    }
+
+    public static long decodeB64(String str) {
+        return decode(str, B64_SYMBOLS);
+    }
+
+    public static long decode(String encoded, String symbols) {
+        final int B = symbols.length();
+        E.checkArgument(B > 0, "The symbols parameter can't be empty");
+        long num = 0L;
+        for (char ch : encoded.toCharArray()) {
+            num *= B;
+            int pos = symbols.indexOf(ch);
+            if (pos < 0) {
+                throw new NumberFormatException(String.format(
+                          "Can't decode symbol '%s' in string '%s'",
+                          ch, encoded));
+            }
+            num += pos;
+        }
+        return num;
+    }
+
+    public static String encode(long num, String symbols) {
+        final int B = symbols.length();
+        E.checkArgument(num >= 0L, "Expected non-negative number: %s", num);
+        E.checkArgument(B > 0, "The symbols parameter can't be empty");
+
+        StringBuilder sb = new StringBuilder();
+        do {
+            sb.append(symbols.charAt((int) (num % B)));
+            num /= B;
+        } while (num != 0L);
+
+        return sb.reverse().toString();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/NumericUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/NumericUtil.java
new file mode 100644
index 0000000000..516170811a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/NumericUtil.java
@@ -0,0 +1,372 @@
+/*
+ * 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.hugegraph.util;
+
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+import java.util.Date;
+import java.util.function.Function;
+
+/**
+ * This file is copied verbatim from Apache Lucene NumericUtils.java
+ * Only the double/float to sortable long/int conversions are retained.
+ */
+public final class NumericUtil {
+
+    private static final long FULL_LONG = Long.MIN_VALUE;
+    private static final int FULL_INT = Integer.MIN_VALUE;
+    private static final byte FULL_BYTE = Byte.MIN_VALUE;
+
+    private NumericUtil() {
+    }
+
+    /**
+     * Converts a <code>double</code> value to a sortable signed
+     * <code>long</code>. The value is converted by getting their IEEE 754
+     * floating-point &quot;double format&quot; bit layout and then some bits
+     * are swapped, to be able to compare the result as long. By this the
+     * precision is not reduced, but the value can be easily used as a long. The
+     * sort order (including {@link Double#NaN}) is defined by
+     * {@link Double#compareTo}; {@code NaN} is greater than positive infinity.
+     * @param value input double value
+     * @return output sortable long value
+     * @see #sortableLongToDouble
+     */
+    public static long doubleToSortableLong(double value) {
+        return sortableDoubleBits(Double.doubleToLongBits(value));
+    }
+
+    /**
+     * Converts a sortable <code>long</code> back to a <code>double</code>.
+     * @param value input double value
+     * @return output sortable long value
+     * @see #doubleToSortableLong
+     */
+    public static double sortableLongToDouble(long value) {
+        return Double.longBitsToDouble(sortableDoubleBits(value));
+    }
+
+    /**
+     * Converts a <code>float</code> value to a sortable signed
+     * <code>int</code>. The value is converted by getting their IEEE 754
+     * floating-point &quot;float format&quot; bit layout and then some bits are
+     * swapped, to be able to compare the result as int. By this the precision
+     * is not reduced, but the value can be easily used as an int. The sort order
+     * (including {@link Float#NaN}) is defined by {@link Float#compareTo};
+     * {@code NaN} is greater than positive infinity.
+     * @param value input float value
+     * @return output sortable int value
+     * @see #sortableIntToFloat
+     */
+    public static int floatToSortableInt(float value) {
+        return sortableFloatBits(Float.floatToIntBits(value));
+    }
+
+    /**
+     * Converts a sortable <code>int</code> back to a <code>float</code>.
+     * @param value input int value
+     * @return output sortable float value
+     * @see #floatToSortableInt
+     */
+    public static float sortableIntToFloat(int value) {
+        return Float.intBitsToFloat(sortableFloatBits(value));
+    }
+
+    /**
+     * Converts IEEE 754 representation of a double to sortable order (or back
+     * to the original)
+     * @param bits The long format of a double value
+     * @return The sortable long value
+     */
+    public static long sortableDoubleBits(long bits) {
+        return bits ^ ((bits >> 63) & 0x7fffffffffffffffL);
+    }
+
+    /**
+     * Converts IEEE 754 representation of a float to sortable order (or back to
+     * the original)
+     * @param bits The int format of a float value
+     * @return The sortable int value
+     */
+    public static int sortableFloatBits(int bits) {
+        /*
+         * Convert to its inverse digits if negative else keep the origin
+         * NOTE: (bits >> 31) is 0x00000000 if bits >= 0
+         *       (bits >> 31) is 0xFFFFFFFF if bits < 0
+         */
+        return bits ^ ((bits >> 31) & 0x7fffffff);
+    }
+
+    public static long numberToSortableLong(Number number) {
+        if (number instanceof Double) {
+            return doubleToSortableLong(number.doubleValue());
+        } else if (number instanceof Float) {
+            return floatToSortableInt(number.floatValue());
+        } else if (number instanceof Long || number instanceof Integer ||
+                   number instanceof Short || number instanceof Byte) {
+            return number.longValue();
+        } else if (number instanceof BigDecimal) {
+            BigDecimal bd = (BigDecimal) number;
+            boolean intNumber = bd.stripTrailingZeros().scale() <= 0;
+            return intNumber ? bd.longValueExact() :
+                   doubleToSortableLong(bd.doubleValue());
+        }
+
+        // TODO: support other number types
+        throw unsupportedNumberType(number);
+    }
+
+    public static Number sortableLongToNumber(long value, Class<?> clazz) {
+        assert NumericUtil.isNumber(clazz);
+
+        if (clazz == Double.class) {
+            return sortableLongToDouble(value);
+        } else if (clazz == Float.class) {
+            return sortableIntToFloat((int) value);
+        } else if (clazz == Long.class) {
+            return value;
+        } else if (clazz == Integer.class) {
+            return (int) value;
+        } else if (clazz == Short.class) {
+            return (short) value;
+        } else if (clazz == Byte.class) {
+            return (byte) value;
+        }
+
+        // TODO: support other number types
+        throw unsupportedNumberType(clazz);
+    }
+
+    public static byte[] numberToSortableBytes(Number number) {
+        if (number instanceof Long) {
+            return longToSortableBytes(number.longValue());
+        } else if (number instanceof Double) {
+            long value = doubleToSortableLong(number.doubleValue());
+            return longToSortableBytes(value);
+        } else if (number instanceof Float) {
+            int value = floatToSortableInt(number.floatValue());
+            return intToSortableBytes(value);
+        } else if (number instanceof Integer || number instanceof Short) {
+            return intToSortableBytes(number.intValue());
+        } else if (number instanceof Byte) {
+            return byteToSortableBytes(number.byteValue());
+        }
+
+        // TODO: support other number types
+        throw unsupportedNumberType(number);
+    }
+
+    public static Number sortableBytesToNumber(byte[] bytes, Class<?> clazz) {
+        assert NumericUtil.isNumber(clazz);
+
+        if (clazz == Long.class) {
+            return sortableBytesToLong(bytes);
+        } else if (clazz == Double.class) {
+            return sortableLongToDouble(sortableBytesToLong(bytes));
+        } else if (clazz == Float.class) {
+            return sortableIntToFloat(sortableBytesToInt(bytes));
+        } else if (clazz == Integer.class) {
+            return sortableBytesToInt(bytes);
+        } else if (clazz == Short.class) {
+            return (short) sortableBytesToInt(bytes);
+        } else if (clazz == Byte.class) {
+            return sortableBytesToByte(bytes);
+        }
+
+        // TODO: support other number types
+        throw unsupportedNumberType(clazz);
+    }
+
+    public static Number minValueOf(Class<?> clazz) {
+        E.checkArgumentNotNull(clazz, "The clazz can't be null");
+
+        if (Long.class.isAssignableFrom(clazz) ||
+            Double.class.isAssignableFrom(clazz)) {
+            return Long.MIN_VALUE;
+        }
+        if (Integer.class.isAssignableFrom(clazz) ||
+            Short.class.isAssignableFrom(clazz) ||
+            Float.class.isAssignableFrom(clazz)) {
+            return Integer.MIN_VALUE;
+        }
+        if (Byte.class.isAssignableFrom(clazz)) {
+            return Byte.MIN_VALUE;
+        }
+
+        // TODO: support other number types
+        throw unsupportedNumberType(clazz);
+    }
+
+    public static Number maxValueOf(Class<?> clazz) {
+        E.checkArgumentNotNull(clazz, "The clazz can't be null");
+
+        if (Long.class.isAssignableFrom(clazz) ||
+            Double.class.isAssignableFrom(clazz)) {
+            return Long.MAX_VALUE;
+        }
+        if (Integer.class.isAssignableFrom(clazz) ||
+            Float.class.isAssignableFrom(clazz) ||
+            Short.class.isAssignableFrom(clazz)) {
+            return Integer.MAX_VALUE;
+        }
+        if (Byte.class.isAssignableFrom(clazz)) {
+            return Byte.MAX_VALUE;
+        }
+
+        // TODO: support other number types
+        throw unsupportedNumberType(clazz);
+    }
+
+    public static byte[] longToSortableBytes(long value) {
+        return longToBytes(value + FULL_LONG);
+    }
+
+    public static long sortableBytesToLong(byte[] bytes) {
+        return bytesToLong(bytes) - FULL_LONG;
+    }
+
+    public static byte[] intToSortableBytes(int value) {
+        return intToBytes(value + FULL_INT);
+    }
+
+    public static int sortableBytesToInt(byte[] bytes) {
+        return bytesToInt(bytes) - FULL_INT;
+    }
+
+    public static byte[] byteToSortableBytes(byte value) {
+        value += FULL_BYTE;
+        return new byte[]{value};
+    }
+
+    public static byte sortableBytesToByte(byte[] bytes) {
+        assert bytes.length == 1;
+        byte value = bytes[0];
+        value -= FULL_BYTE;
+        return value;
+    }
+
+    public static byte[] longToBytes(long value) {
+        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
+        buffer.putLong(value);
+        return buffer.array();
+    }
+
+    public static long bytesToLong(byte[] bytes) {
+        assert bytes.length == Long.BYTES;
+        return ByteBuffer.wrap(bytes).getLong();
+    }
+
+    public static byte[] intToBytes(int value) {
+        ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
+        buffer.putInt(value);
+        return buffer.array();
+    }
+
+    public static int bytesToInt(byte[] bytes) {
+        assert bytes.length == Integer.BYTES;
+        return ByteBuffer.wrap(bytes).getInt();
+    }
+
+    public static boolean isNumber(Object value) {
+        if (value == null) {
+            return false;
+        }
+        return isNumber(value.getClass());
+    }
+
+    public static boolean isNumber(Class<?> clazz) {
+        if (clazz.isPrimitive()) {
+            return clazz == int.class || clazz == long.class ||
+                   clazz == float.class || clazz == double.class ||
+                   clazz == short.class || clazz == byte.class;
+        }
+        return Number.class.isAssignableFrom(clazz);
+    }
+
+    public static Number convertToNumber(Object value) {
+        if (value == null) {
+            return null;
+        }
+
+        Number number;
+        if (isNumber(value)) {
+            number = (Number) value;
+        } else {
+            if (value instanceof Date) {
+                number = ((Date) value).getTime();
+            } else {
+                // TODO: add some more types to convert
+                number = new BigDecimal(value.toString());
+            }
+        }
+        return number;
+    }
+
+    /**
+     * Compare object with a number, the object should be a number,
+     * or it can be converted to a BigDecimal
+     * @param first   might be number or string
+     * @param second  must be number
+     * @return  0 if first is numerically equal to second;
+     *          a negative int if first is numerically less than second;
+     *          a positive int if first is numerically greater than second.
+     */
+    public static int compareNumber(Object first, Number second) {
+        if (first == null) {
+            E.checkArgument(first != null,
+                            "The first parameter can't be null");
+        }
+        if (second == null) {
+            E.checkArgument(second != null,
+                            "The second parameter can't be null");
+        }
+
+        if (first instanceof Number && first instanceof Comparable &&
+            first.getClass().equals(second.getClass())) {
+            @SuppressWarnings("unchecked")
+            Comparable<Number> cmpFirst = (Comparable<Number>) first;
+            return cmpFirst.compareTo(second);
+        }
+
+        Function<Object, BigDecimal> toBig = (number) -> {
+            try {
+                return new BigDecimal(number.toString());
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException(String.format(
+                          "Can't compare between '%s' and '%s', " +
+                          "they must be numbers", first, second));
+            }
+        };
+
+        BigDecimal n1 = toBig.apply(first);
+        BigDecimal n2 = toBig.apply(second);
+
+        return n1.compareTo(n2);
+    }
+
+    private static IllegalArgumentException unsupportedNumberType(Class<?> c) {
+        return new IllegalArgumentException(String.format(
+                   "Unsupported number type: %s", c.getSimpleName()));
+    }
+
+    private static IllegalArgumentException unsupportedNumberType(Number num) {
+        return new IllegalArgumentException(String.format(
+                   "Unsupported number type: %s(%s)",
+                   num.getClass().getSimpleName(), num));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/OrderLimitMap.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/OrderLimitMap.java
new file mode 100644
index 0000000000..b711e3e585
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/OrderLimitMap.java
@@ -0,0 +1,103 @@
+/*
+ * 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.hugegraph.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.Ordering;
+
+public class OrderLimitMap<K extends Comparable<K>, V extends Comparable<V>> extends TreeMap<K, V> {
+
+    private static final long serialVersionUID = 756490437953358633L;
+
+    private final int capacity;
+    private final Map<K, V> valueMap;
+
+    private static <V extends Comparable<V>> Ordering<? super V> incr() {
+        return Ordering.from(Comparable::compareTo);
+    }
+
+    private static <V extends Comparable<V>> Ordering<? super V> decr() {
+        return Ordering.from((V o1, V o2) -> -o1.compareTo(o2));
+    }
+
+    public OrderLimitMap(int capacity) {
+        this(capacity, false);
+    }
+
+    public OrderLimitMap(int capacity, boolean incr) {
+        this(capacity, incr ? incr() : decr(), new HashMap<>());
+    }
+
+    private OrderLimitMap(int capacity, Ordering<? super V> ordering,
+                          HashMap<K, V> valueMap) {
+        /*
+         * onResultOf: for getting the value for the key from value map
+         * compound: keep insertion order
+         */
+        super(ordering.onResultOf(Functions.forMap(valueMap))
+                      .compound(Ordering.natural()));
+        E.checkArgument(capacity > 0, "The capacity must be > 0");
+        this.capacity = capacity;
+        this.valueMap = valueMap;
+    }
+
+    @Override
+    public V put(K k, V v) {
+        if (this.valueMap.containsKey(k)) {
+            super.remove(k);
+        } else if (this.valueMap.size() >= this.capacity) {
+            K key = super.lastKey();
+            super.remove(key);
+            this.valueMap.remove(key);
+        }
+        this.valueMap.put(k, v);
+        return super.put(k, v);
+    }
+
+    @Override
+    public V get(Object key) {
+        return this.valueMap.get(key);
+    }
+
+    @Override
+    public V getOrDefault(Object key, V defaultValue) {
+        return this.valueMap.getOrDefault(key, defaultValue);
+    }
+
+    @Override
+    public boolean containsKey(Object key) {
+        return this.valueMap.containsKey(key);
+    }
+
+    public Map<K, V> topN(int n) {
+        E.checkArgument(n > 0, "'N' Must be positive, but got '%s'", n);
+        Map<K, V> top = InsertionOrderUtil.newMap();
+        int i = 0;
+        for (Map.Entry<K, V> entry : this.entrySet()) {
+            top.put(entry.getKey(), entry.getValue());
+            if (++i >= n) {
+                break;
+            }
+        }
+        return top;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ReflectionUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ReflectionUtil.java
new file mode 100644
index 0000000000..f48d5b6c78
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/ReflectionUtil.java
@@ -0,0 +1,124 @@
+/*
+ * 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.hugegraph.util;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.hugegraph.iterator.ExtendableIterator;
+import com.google.common.collect.Lists;
+import com.google.common.reflect.ClassPath;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+
+public final class ReflectionUtil {
+
+    public static boolean isSimpleType(Class<?> type) {
+        return type.isPrimitive() ||
+               type.equals(String.class) ||
+               type.equals(Boolean.class) ||
+               type.equals(Character.class) ||
+               NumericUtil.isNumber(type);
+    }
+
+    public static List<Method> getMethodsAnnotatedWith(
+                               Class<?> type,
+                               Class<? extends Annotation> annotation,
+                               boolean withSuperClass) {
+        final List<Method> methods = new LinkedList<>();
+        Class<?> klass = type;
+        do {
+            for (Method method : klass.getDeclaredMethods()) {
+                if (method.isAnnotationPresent(annotation)) {
+                    methods.add(method);
+                }
+            }
+            klass = klass.getSuperclass();
+        } while (klass != Object.class && withSuperClass);
+        return methods;
+    }
+
+    public static List<CtMethod> getMethodsAnnotatedWith(
+                                 CtClass type,
+                                 Class<? extends Annotation> annotation,
+                                 boolean withSuperClass)
+                                 throws NotFoundException {
+        final List<CtMethod> methods = new LinkedList<>();
+
+        CtClass klass = type;
+        do {
+            for (CtMethod method : klass.getDeclaredMethods()) {
+                if (method.hasAnnotation(annotation)) {
+                    methods.add(method);
+                }
+            }
+            klass = klass.getSuperclass();
+        } while (klass != null && withSuperClass);
+        return methods;
+    }
+
+    public static Iterator<ClassInfo> classes(String... packages)
+                                              throws IOException {
+        ClassPath path = ClassPath.from(ReflectionUtil.class.getClassLoader());
+        ExtendableIterator<ClassInfo> results = new ExtendableIterator<>();
+        for (String p : packages) {
+            results.extend(path.getTopLevelClassesRecursive(p).iterator());
+        }
+        return results;
+    }
+
+    public static List<String> superClasses(String clazz)
+                                            throws NotFoundException {
+        CtClass klass = ClassPool.getDefault().get(clazz);
+        CtClass parent = klass.getSuperclass();
+
+        List<String> results = new LinkedList<>();
+        while (parent != null) {
+            results.add(parent.getName());
+            parent = parent.getSuperclass();
+        }
+        return Lists.reverse(results);
+    }
+
+    public static List<String> nestedClasses(String clazz)
+                                             throws NotFoundException {
+        CtClass klass = ClassPool.getDefault().get(clazz);
+
+        List<String> results = new LinkedList<>();
+        for (CtClass nested : klass.getNestedClasses()) {
+            results.add(nested.getName());
+        }
+        return results;
+    }
+
+    public static String packageName(String clazz) {
+        int offset = clazz.lastIndexOf(".");
+        if (offset > 0) {
+            return clazz.substring(0, offset);
+        }
+        return "";
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/StringUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/StringUtil.java
new file mode 100644
index 0000000000..f144957db5
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/StringUtil.java
@@ -0,0 +1,123 @@
+/*
+ * 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.hugegraph.util;
+
+public final class StringUtil {
+
+    public static Chars[] splitToCharsArray(String text, String delimiter) {
+        E.checkArgument(delimiter.length() > 0,
+                        "The delimiter can't be empty");
+        Chars[] buffer = new Chars[text.length()];
+        int count = Chars.split(text, delimiter, buffer);
+        if (count == buffer.length) {
+            return buffer;
+        }
+        Chars[] result = new Chars[count];
+        System.arraycopy(buffer, 0, result, 0, count);
+        return result;
+    }
+
+    public static String[] split(String text, String delimiter) {
+        E.checkArgument(delimiter.length() > 0,
+                        "The delimiter can't be empty");
+        Chars[] buffer = new Chars[text.length()];
+        int count = Chars.split(text, delimiter, buffer);
+        String[] result = new String[count];
+        for (int i = 0; i < count; i++) {
+            result[i] = buffer[i].toString();
+        }
+        return result;
+    }
+
+    public static class Chars implements CharSequence {
+
+        private final char[] chars;
+        private final int start;
+        private final int end;
+
+        public Chars(char[] chars, int start, int end) {
+            E.checkArgument(0 < start && start < chars.length || start == 0,
+                            "Invalid start parameter %s", start);
+            E.checkArgument(start <= end && end <= chars.length,
+                            "Invalid end parameter %s", end);
+            this.chars = chars;
+            this.start = start;
+            this.end = end;
+        }
+
+        @Override
+        public int length() {
+            return this.end - this.start;
+        }
+
+        @Override
+        public char charAt(int index) {
+            return this.chars[this.start + index];
+        }
+
+        @Override
+        public CharSequence subSequence(int start, int end) {
+            return new Chars(this.chars, this.start + start, this.start + end);
+        }
+
+        @Override
+        public boolean equals(Object object) {
+            if (!(object instanceof Chars)) {
+                return false;
+            }
+            Chars other = (Chars) object;
+            return this.toString().equals(other.toString());
+        }
+
+        @Override
+        public int hashCode() {
+            return this.toString().hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return new String(this.chars, this.start, this.length());
+        }
+
+        public static Chars of(String string) {
+            return new Chars(string.toCharArray(), 0, string.length());
+        }
+
+        public static Chars[] of(String... strings) {
+            Chars[] results = new Chars[strings.length];
+            for (int i = 0; i < strings.length; i++) {
+                results[i] = Chars.of(strings[i]);
+            }
+            return results;
+        }
+
+        public static int split(String text, String delimiter, Chars[] buffer) {
+            int count = 0;
+            int from = 0;
+            char[] chars = text.toCharArray();
+            for (int to; (to = text.indexOf(delimiter, from)) >= 0;
+                 from = to + delimiter.length()) {
+                buffer[count++] = new Chars(chars, from, to);
+            }
+            if (from < text.length()) {
+                buffer[count++] = new Chars(chars, from, text.length());
+            }
+            return count;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/TimeUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/TimeUtil.java
new file mode 100644
index 0000000000..8a6b9abeb2
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/TimeUtil.java
@@ -0,0 +1,59 @@
+/*
+ * 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.hugegraph.util;
+
+import java.time.Duration;
+import java.util.Date;
+
+public final class TimeUtil {
+
+    @SuppressWarnings("deprecation")
+    public static long BASE_TIME = new Date(2017 - 1900, 10, 28).getTime();
+
+    public static long timeGen() {
+        return System.currentTimeMillis() - BASE_TIME;
+    }
+
+    public static long timeGen(Date date) {
+        return date.getTime() - BASE_TIME;
+    }
+
+    public static long timeGen(long time) {
+        return time - BASE_TIME;
+    }
+
+    public static long tillNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    public static String readableTime(long time) {
+        if (time > 60 * 1000) {
+            // Remove the milliseconds part
+            time = time / 1000 * 1000;
+        }
+        Duration duration = Duration.ofMillis(time);
+        return duration.toString()
+                       .substring(2)
+                       .replaceAll("(\\d[HMS])(?!$)", "$1 ")
+                       .toLowerCase();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/UnitUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/UnitUtil.java
new file mode 100644
index 0000000000..09e1ff6379
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/UnitUtil.java
@@ -0,0 +1,181 @@
+/*
+ * 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.hugegraph.util;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.Duration;
+
+public final class UnitUtil {
+
+    public static double bytesToMB(long bytes) {
+        return doubleWith2Scale(bytes / (double) Bytes.MB);
+    }
+
+    public static double bytesToGB(long bytes) {
+        return doubleWith2Scale(bytes / (double) Bytes.GB);
+    }
+
+    public static double doubleWith2Scale(double value) {
+        BigDecimal decimal = new BigDecimal(value);
+        return decimal.setScale(2, RoundingMode.HALF_UP).doubleValue();
+    }
+
+    public static String bytesToReadableString(long bytes) {
+        // NOTE: FileUtils.byteCountToDisplaySize() lost decimal precision
+        final String[] units = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};
+        if (bytes <= 0L) {
+            return "0 B";
+        }
+        int i = (int) (Math.log(bytes) / Math.log(1024));
+        E.checkArgument(i < units.length,
+                        "The bytes parameter is out of %s unit: %s",
+                        units[units.length - 1], bytes);
+        double value = bytes / Math.pow(1024, i);
+        if (value % 1L == 0L) {
+            return ((long) value) + " " + units[i];
+        } else {
+            return doubleWith2Scale(value) + " " + units[i];
+        }
+    }
+
+    public static long bytesFromReadableString(String valueWithUnit) {
+        int spacePos = valueWithUnit.indexOf(" ");
+        E.checkArgument(spacePos >= 0,
+                        "Invalid readable bytes '%s', " +
+                        "expect format like '10 MB'", valueWithUnit);
+        String unit = valueWithUnit.substring(spacePos + 1);
+
+        long factor;
+        switch (unit.trim().toUpperCase()) {
+            case "B":
+            case "BYTE":
+            case "BYTES":
+                factor = 1L;
+                break;
+            case "KB":
+            case "KIB":
+                factor = Bytes.KB;
+                break;
+            case "MB":
+            case "MIB":
+                factor = Bytes.MB;
+                break;
+            case "GB":
+            case "GIB":
+                factor = Bytes.GB;
+                break;
+            case "TB":
+            case "TIB":
+                factor = Bytes.TB;
+                break;
+            case "PB":
+            case "PIB":
+                factor = Bytes.PB;
+                break;
+            case "EB":
+            case "EIB":
+                factor = Bytes.EB;
+                break;
+            default:
+                throw new IllegalArgumentException("Unrecognized unit " + unit);
+        }
+
+        double value;
+        try {
+            value = Double.parseDouble(valueWithUnit.substring(0, spacePos));
+        } catch (Exception e) {
+            throw new IllegalArgumentException(String.format(
+                      "Invalid parameter(not number): '%s'", valueWithUnit), e);
+        }
+        value = value * factor;
+        E.checkArgument(value <= Long.MAX_VALUE,
+                        "The value %s from parameter '%s' is out of range",
+                        value, valueWithUnit);
+        return (long) value;
+    }
+
+    public static String timestampToReadableString(long time) {
+        Duration duration = Duration.ofMillis(time);
+        long days = duration.toDays();
+        long hours = duration.toHours();
+        long minutes = duration.toMinutes();
+        long seconds = duration.getSeconds();
+
+        if (days > 0) {
+            return String.format("%dd%dh%dm%ds",
+                                 days,
+                                 hours % 24,
+                                 minutes % 60,
+                                 seconds % 60);
+        } else if (hours > 0) {
+            return String.format("%dh%dm%ds",
+                                 hours,
+                                 minutes % 60,
+                                 seconds % 60);
+        } else if (minutes > 0) {
+            return String.format("%dm%ds",
+                                 minutes,
+                                 seconds % 60);
+        } else if (seconds > 0) {
+            long ms = duration.toMillis() % 1000L;
+            if (ms > 0L) {
+                return String.format("%ds%dms", seconds, ms);
+            } else {
+                return String.format("%ds", seconds);
+            }
+        } else {
+            return String.format("%dms", duration.toMillis());
+        }
+    }
+
+    public static long timestampFromReadableString(String valueWithUnit) {
+        long ms = 0L;
+        // Adapt format 'nDnHnMnS' to 'PnYnMnDTnHnMnS'
+        String formatDuration = valueWithUnit.toUpperCase();
+        if (formatDuration.indexOf('D') >= 0) {
+            // Contains days
+            assert !formatDuration.contains("MS");
+            formatDuration = "P" + formatDuration.replace("D", "DT");
+        } else {
+            // Not exists days
+            int msPos = formatDuration.indexOf("MS");
+            // If contains ms, remove the ms part
+            if (msPos >= 0) {
+                int sPos = formatDuration.indexOf("S");
+                if (0 <= sPos && sPos < msPos) {
+                    // If contains second part
+                    sPos += 1;
+                    ms = Long.parseLong(formatDuration.substring(sPos, msPos));
+                    ms %= 1000L;
+                    formatDuration = formatDuration.substring(0, sPos);
+                } else {
+                    // Not contains second part, only exists ms
+                    ms = Long.parseLong(formatDuration.substring(0, msPos));
+                    return ms;
+                }
+            } else {
+                assert formatDuration.endsWith("S");
+            }
+            formatDuration = "PT" + formatDuration;
+        }
+
+        Duration duration = Duration.parse(formatDuration);
+        return duration.toMillis() + ms;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/VersionUtil.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/VersionUtil.java
new file mode 100644
index 0000000000..b49adda87a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/VersionUtil.java
@@ -0,0 +1,236 @@
+/*
+ * 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.hugegraph.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Objects;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+public final class VersionUtil {
+
+    /**
+     * Compare if a version is inside a range [begin, end)
+     * @param version   The version to be compared
+     * @param begin     The lower bound of the range
+     * @param end       The upper bound of the range
+     * @return          true if belong to the range, otherwise false
+     */
+    public static boolean match(Version version, String begin, String end) {
+        E.checkArgumentNotNull(version, "The version to match is null");
+        return version.compareTo(new Version(begin)) >= 0 &&
+               version.compareTo(new Version(end)) < 0;
+    }
+
+    /**
+     * Compare if a version is greater than the other one (inclusive)
+     * @param version   The version to be compared
+     * @param other     The lower bound of the range
+     * @return          true if it's greater than the other, otherwise false
+     */
+    public static boolean gte(String version, String other) {
+        E.checkArgumentNotNull(version, "The version to match is null");
+        return new Version(version).compareTo(new Version(other)) >= 0;
+    }
+
+    /**
+     * Check whether a component version is matched expected range,
+     * throw an exception if it's not matched.
+     * @param version   The version to be checked
+     * @param begin     The lower bound of the range
+     * @param end       The upper bound of the range
+     * @param component The owner component of version
+     */
+    public static void check(Version version, String begin, String end,
+                             String component) {
+        E.checkState(VersionUtil.match(version, begin, end),
+                     "The version %s of '%s' is not in [%s, %s)",
+                     version, component, begin, end);
+    }
+
+    /**
+     * Get implementation version from manifest in jar
+     * @param clazz The class to be load from jar package
+     * @return      The implementation version
+     */
+    public static String getImplementationVersion(Class<?> clazz) {
+        /*
+         * We don't use Package.getImplementationVersion() due to
+         * a duplicate package would override the origin package info.
+         */
+        String className = clazz.getSimpleName() + ".class";
+        String classPath = Objects.requireNonNull(clazz.getResource(className)).toString();
+        if (!classPath.startsWith("jar:file:")) {
+            // Class not from JAR
+            return null;
+        }
+        int offset = classPath.lastIndexOf("!");
+        assert offset > 0;
+        // Get manifest file path
+        String manifestPath = classPath.substring(0, offset + 1);
+        return getImplementationVersion(manifestPath);
+    }
+
+    public static String getImplementationVersion(String manifestPath) {
+        manifestPath += "/META-INF/MANIFEST.MF";
+
+        Manifest manifest;
+        try {
+            manifest = new Manifest(new URL(manifestPath).openStream());
+        } catch (IOException ignored) {
+            return null;
+        }
+        return manifest.getMainAttributes()
+                       .getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+    }
+
+    /**
+     * Get version from pom.xml
+     * @return      The pom version
+     */
+    public static String getPomVersion() {
+        String cmd = "mvn help:evaluate -Dexpression=project.version " +
+                     "-q -DforceStdout";
+        Process process = null;
+        InputStreamReader isr = null;
+        try {
+            process = Runtime.getRuntime().exec(cmd);
+            process.waitFor();
+
+            isr = new InputStreamReader(process.getInputStream());
+            BufferedReader br = new BufferedReader(isr);
+            return br.readLine();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (isr != null) {
+                try {
+                    isr.close();
+                } catch (Exception ignored) {
+                    // pass
+                }
+            }
+
+            // Destroy child process
+            if (process != null) {
+                process.destroy();
+            }
+        }
+    }
+
+    public static class Version implements Comparable<Version> {
+
+        public static Version of(Class<?> clazz) {
+            return Version.of(clazz, null);
+        }
+
+        public static Version of(Class<?> clazz, String defaultValue) {
+            String v = getImplementationVersion(clazz);
+            if (v == null) {
+                v = defaultValue;
+            }
+            return v == null ? null : new Version(v);
+        }
+
+        public static Version of(String version) {
+            return new Version(version);
+        }
+
+        /************************** Version define **************************/
+
+        private final String version;
+        private final int[] parts;
+
+        public Version(String version) {
+            E.checkArgumentNotNull(version, "The version is null");
+            E.checkArgument(version.matches("[0-9]+(\\.[0-9]+)*"),
+                            "Invalid version format: %s", version);
+            this.version = version;
+            this.parts = parseVersion(version);
+        }
+
+        private static int[] parseVersion(String version) {
+            String[] parts = version.split("\\.");
+            int[] partsNumber = new int[parts.length];
+            for (int i = 0; i < parts.length; i++) {
+                partsNumber[i] = Integer.parseInt(parts[i]);
+            }
+            return partsNumber;
+        }
+
+        public final String get() {
+            return this.version;
+        }
+
+        @Override
+        public int compareTo(Version that) {
+            if (that == null) {
+                return 1;
+            }
+            int[] thisParts = this.parts;
+            int[] thatParts = that.parts;
+            int length = Math.max(thisParts.length, thatParts.length);
+            for (int i = 0; i < length; i++) {
+                int thisPart = i < thisParts.length ? thisParts[i] : 0;
+                int thatPart = i < thatParts.length ? thatParts[i] : 0;
+                if (thisPart < thatPart) {
+                    return -1;
+                }
+                if (thisPart > thatPart) {
+                    return 1;
+                }
+            }
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object that) {
+            if (this == that) {
+                return true;
+            }
+            if (that == null) {
+                return false;
+            }
+            if (this.getClass() != that.getClass()) {
+                return false;
+            }
+            return this.compareTo((Version) that) == 0;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 0;
+            for (int i = this.parts.length - 1; i >= 0; i--) {
+                int part = this.parts[i];
+                if (part == 0 && hash == 0) {
+                    continue;
+                }
+                hash = 31 * hash + Integer.hashCode(part);
+            }
+            return hash;
+        }
+
+        @Override
+        public String toString() {
+            return this.version;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/version/CommonVersion.java b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/version/CommonVersion.java
new file mode 100644
index 0000000000..73342fdaaa
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/version/CommonVersion.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.hugegraph.version;
+
+import org.apache.hugegraph.util.VersionUtil.Version;
+
+public class CommonVersion {
+
+    public static final String NAME = "hugegraph-common";
+
+    // The second parameter of Version.of() is for all-in-one JAR
+    public static final Version VERSION = Version.of(CommonVersion.class, "1.5.0");
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/testutil/AssertTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/testutil/AssertTest.java
new file mode 100644
index 0000000000..53f60247e9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/testutil/AssertTest.java
@@ -0,0 +1,444 @@
+/*
+ * 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.hugegraph.testutil;
+
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.junit.Test;
+
+public class AssertTest extends BaseUnitTest {
+
+    @Test
+    public void testAssertEquals() {
+        Assert.assertEquals((byte) 1, Byte.valueOf("1"));
+        Assert.assertEquals((short) 1, Short.valueOf("1"));
+        Assert.assertEquals('1', Character.valueOf('1'));
+        Assert.assertEquals(1, Integer.valueOf("1"));
+        Assert.assertEquals(1L, Long.valueOf("1"));
+        Assert.assertEquals(1f, Float.valueOf("1"));
+        Assert.assertEquals(1d, Double.valueOf("1"));
+    }
+
+    @Test
+    public void testAssertEqualsWithError() {
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals((byte) 1, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Byte",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals((short) 1, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Short",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals('1', "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Character",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1L, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Long",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1f, "1.0");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Float",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1d, "1.0");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Double",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1f, "1");
+        }, e -> {
+            Assert.assertContains("expected:<1.0> but was:<1>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1d, "1");
+        }, e -> {
+            Assert.assertContains("expected:<1.0> but was:<1>",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertEqualsOfIntWithError() {
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Byte) (byte) 1);
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Short) (short) 1);
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Character) '1');
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Long) 1L);
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Float) 1f);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<1.0>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Double) 1d);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<1.0>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, "1.0");
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<1.0>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Byte) (byte) 2);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<2>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, null);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<null>",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertThrows() {
+        Assert.assertThrows(NullPointerException.class, () -> {
+            throw new NullPointerException();
+        });
+        Assert.assertThrows(RuntimeException.class, () -> {
+            throw new RuntimeException();
+        });
+
+        Throwable exception = Assert.assertThrows(RuntimeException.class, () -> {
+            throw new RuntimeException("fake-error");
+        });
+        Assert.assertInstanceOf(RuntimeException.class, exception);
+        Assert.assertEquals("fake-error", exception.getMessage());
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            throw new RuntimeException("fake-error");
+        }, e -> {
+            Assert.assertEquals("fake-error", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertThrowsWithTypeError() {
+        try {
+            Assert.assertThrows(NullPointerException.class, () -> {
+                // pass
+            });
+            Assert.fail("Expect error");
+        } catch (AssertionError e) {
+            Assert.assertContains("java.lang.NullPointerException", e.getMessage());
+        }
+
+        try {
+            Assert.assertThrows(NullPointerException.class, () -> {
+                throw new RuntimeException();
+            });
+            Assert.fail("Expect error");
+        } catch (AssertionError e) {
+            Assert.assertContains("java.lang.NullPointerException", e.getMessage());
+            Assert.assertContains("java.lang.RuntimeException", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAssertThrowsWithMessageError() {
+        try {
+            Assert.assertThrows(RuntimeException.class, () -> {
+                throw new RuntimeException("fake-error");
+            }, e -> {
+                Assert.assertEquals("fake-error-typo", e.getMessage());
+            });
+            Assert.fail("Expect error");
+        } catch (AssertionError e) {
+            Assert.assertContains("expected:<fake-error[-typo]> but was:<fake-error[]>",
+                                  e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAssertGt() {
+        Assert.assertGt((byte) 1, Byte.valueOf("2"));
+        Assert.assertGt((short) 1, Short.valueOf("2"));
+        Assert.assertGt(1, Integer.valueOf("2"));
+        Assert.assertGt(1L, Long.valueOf("2"));
+        Assert.assertGt(1f, Float.valueOf("1.01"));
+        Assert.assertGt(1d, Double.valueOf("1.01"));
+
+        Assert.assertGt((byte) 1, (byte) 2);
+        Assert.assertGt((short) 1, (short) 2);
+        Assert.assertGt(1, 2);
+        Assert.assertGt(1L, 2L);
+        Assert.assertGt(1f, 1.01f);
+        Assert.assertGt(1d, 1.01d);
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, 0);
+        }, e -> {
+            Assert.assertContains("Expected: a number > 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, null);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, (byte) 2);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, 1.1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, '2');
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(0.9, 1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Double",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(0.9d, 0.98f);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Double",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(0.9f, 0.98d);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Float",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertGte() {
+        Assert.assertGte((byte) 1, Byte.valueOf("2"));
+        Assert.assertGte((short) 1, Short.valueOf("2"));
+        Assert.assertGte(1, Integer.valueOf("2"));
+        Assert.assertGte(1L, Long.valueOf("2"));
+        Assert.assertGte(1f, Float.valueOf("1.01"));
+        Assert.assertGte(1d, Double.valueOf("1.01"));
+
+        Assert.assertGte((byte) 1, Byte.valueOf("1"));
+        Assert.assertGte((short) 1, Short.valueOf("1"));
+        Assert.assertGte(1, Integer.valueOf("1"));
+        Assert.assertGte(1L, Long.valueOf("1"));
+        Assert.assertGte(1f, Float.valueOf("1"));
+        Assert.assertGte(1d, Double.valueOf("1"));
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGte(1, 0);
+        }, e -> {
+            Assert.assertContains("Expected: a number >= 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGte(1, 1.1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGte(1, '2');
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertLt() {
+        Assert.assertLt((byte) 1, Byte.valueOf("0"));
+        Assert.assertLt((short) 1, Short.valueOf("0"));
+        Assert.assertLt(1, Integer.valueOf("0"));
+        Assert.assertLt(1L, Long.valueOf("0"));
+        Assert.assertLt(1f, Float.valueOf("0.99"));
+        Assert.assertLt(1d, Double.valueOf("0.99"));
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLt(1, 2);
+        }, e -> {
+            Assert.assertContains("Expected: a number < 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, 0.9);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, '0');
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertLte() {
+        Assert.assertLte((byte) 1, Byte.valueOf("0"));
+        Assert.assertLte((short) 1, Short.valueOf("0"));
+        Assert.assertLte(1, Integer.valueOf("0"));
+        Assert.assertLte(1L, Long.valueOf("0"));
+        Assert.assertLte(1f, Float.valueOf("0.99"));
+        Assert.assertLte(1d, Double.valueOf("0.99"));
+
+        Assert.assertLte((byte) 1, Byte.valueOf("1"));
+        Assert.assertLte((short) 1, Short.valueOf("1"));
+        Assert.assertLte(1, Integer.valueOf("1"));
+        Assert.assertLte(1L, Long.valueOf("1"));
+        Assert.assertLte(1f, Float.valueOf("1"));
+        Assert.assertLte(1d, Double.valueOf("1"));
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLte(1, 2);
+        }, e -> {
+            Assert.assertContains("Expected: a number <= 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLte(1, 0.9);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLte(1, '0');
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertContains() {
+        Assert.assertContains("test", "test");
+        Assert.assertContains("test", "hellotest");
+        Assert.assertContains("test", "test123");
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertContains("test123", "test");
+        }, e -> {
+            Assert.assertContains("Expected: a string containing",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertContains("null", null);
+        }, e -> {
+            Assert.assertContains("Expected: a string containing",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(NullPointerException.class, () -> {
+            Assert.assertContains(null, "null");
+        }, e -> {
+            Assert.assertNull(e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertInstanceOf() {
+        Assert.assertInstanceOf(Integer.class, 1);
+        Assert.assertInstanceOf(Double.class, 1.0);
+        Assert.assertInstanceOf(String.class, "1.0");
+        Assert.assertInstanceOf(BaseUnitTest.class, this);
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertInstanceOf(Float.class, 1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Float",
+                                  e.getMessage());
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/testutil/WhiteboxTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/testutil/WhiteboxTest.java
new file mode 100644
index 0000000000..15124edbcc
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/testutil/WhiteboxTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.hugegraph.testutil;
+
+import org.junit.Test;
+
+public class WhiteboxTest {
+
+    @Test
+    public void testGetStaticInternalState() {
+        Assert.assertEquals(1, Whitebox.getInternalState(Test1.class,
+                                                         "staticValue"));
+        Test1 test1 = newTest();
+        Assert.assertEquals(1, Whitebox.getInternalState(test1, "staticValue"));
+        Assert.assertEquals(2, Whitebox.getInternalState(test1,
+                                                         "test2.staticValue"));
+    }
+
+    @Test
+    public void testSetStaticInternalState() {
+        try {
+            Whitebox.setInternalState(Test1.class, "staticValue", 11);
+            Assert.assertEquals(11, Test1.staticValue);
+
+            Test1 test1 = newTest();
+            Whitebox.setInternalState(test1, "staticValue", 111);
+            Assert.assertEquals(111, Test1.staticValue);
+
+            Whitebox.setInternalState(test1, "test2.staticValue", 22);
+            Assert.assertEquals(22, Test2.staticValue);
+        } finally {
+            Whitebox.setInternalState(Test1.class, "staticValue", 1);
+            Whitebox.setInternalState(Test2.class, "staticValue", 2);
+        }
+    }
+
+    @Test
+    public void testGetInternalState() {
+        Test1 test1 = newTest();
+        Assert.assertEquals(1, Whitebox.getInternalState(test1, "ivalue"));
+        Assert.assertEquals(2f, Whitebox.getInternalState(test1,
+                                                          "test2.finalValue"));
+        Assert.assertEquals("3",  Whitebox.getInternalState(test1,
+                                                            "test2.test3.str"));
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.getInternalState(test1, "ivalue2");
+        });
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.getInternalState(test1, "test2.valueNotExist");
+        });
+    }
+
+    @Test
+    public void testSetInternalState() {
+        Test1 test1 = newTest();
+
+        Whitebox.setInternalState(test1, "ivalue", 11);
+        Assert.assertEquals(11, Whitebox.getInternalState(test1, "ivalue"));
+        Assert.assertEquals(11, test1.ivalue);
+
+        Whitebox.setInternalState(test1, "test2.finalValue", 22f);
+        Assert.assertEquals(22f, Whitebox.getInternalState(test1,
+                                                          "test2.finalValue"));
+
+        Whitebox.setInternalState(test1, "test2.test3.str", "33");
+        Assert.assertEquals("33",  Whitebox.getInternalState(test1,
+                                                            "test2.test3.str"));
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.setInternalState(test1, "ivalue2", 11);
+        });
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.setInternalState(test1, "test2.valueNotExist", 22f);
+        });
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.setInternalState(test1, "test2.finalValue", 22d);
+        });
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            test1.test2 = null;
+            Whitebox.setInternalState(test1, "test2.finalValue", 22f);
+        }, e -> {
+            Assert.assertContains("Can't set value on null field",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testSetInternalFinalState() {
+        Test1 test1 = newTest();
+        Assert.assertEquals(1, test1.finalValue);
+
+        Whitebox.setInternalState(test1, "finalValue", 2);
+        Assert.assertEquals(2, Whitebox.getInternalState(test1, "finalValue"));
+
+        Whitebox.setInternalState(test1, "finalValue", 3);
+        Assert.assertEquals(3, Whitebox.getInternalState(test1, "finalValue"));
+
+        Whitebox.setInternalState(test1, "test2.finalValue", 22f);
+        Assert.assertEquals(22f, Whitebox.getInternalState(test1,
+                                                           "test2.finalValue"));
+
+        // FIXME: seems don't take effect!!!
+        Assert.assertEquals(1, test1.finalValue);
+        Assert.assertEquals(2f, test1.test2.finalValue, 0f);
+    }
+
+    @Test
+    public void testInvokeStatic() {
+        Assert.assertEquals(1, Whitebox.invokeStatic(Test1.class, "svalue"));
+        Assert.assertEquals(2, Whitebox.invokeStatic(Test1.class, "svalue", 2));
+        Assert.assertEquals(2, Whitebox.invokeStatic(Test1.class, "svalue",
+                                                     new Integer(2)));
+        Assert.assertEquals(2d, Whitebox.invokeStatic(Test1.class,
+                                                      new Class[]{Object.class},
+                                                      "svalue", 2d));
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.invokeStatic(Test1.class, "svalue2");
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            Whitebox.invokeStatic(Test1.class, "throwfunc1");
+        });
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.invokeStatic(Test1.class, "throwfunc2");
+        });
+    }
+
+    @Test
+    public void testInvoke() {
+        Test1 test1 = newTest();
+        Assert.assertEquals(1, Whitebox.invoke(test1.getClass(),
+                                               "value", test1));
+        Assert.assertEquals(3, Whitebox.invoke(test1.getClass(),
+                                               "addValue", test1, 2));
+        Assert.assertEquals(2f, Whitebox.invoke(test1, "test2", "value"));
+        Assert.assertEquals(2, Whitebox.invoke(test1, "test2",
+                                               new Class[]{Object.class},
+                                               "value", 2));
+        Assert.assertEquals(3, Whitebox.invoke(test1, "test4", "addValue", 2));
+        Assert.assertEquals(4, Whitebox.invoke(test1, "test4", "value"));
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.invoke(test1.getClass(), "value2", test1);
+        });
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.invoke(test1, "test22", "value");
+        });
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.invoke(test1, "test2", "value", 2);
+        });
+        Assert.assertThrows(RuntimeException.class, () -> {
+            Whitebox.invoke(test1.getClass(), "addValue", test1, 2.0);
+        });
+    }
+
+    private static Test1 newTest() {
+        Test1 test1 = new Test1();
+        test1.test2 = new Test2();
+        test1.test2.test3 = new Test3();
+        test1.test4 = new TestSubClass();
+        return test1;
+    }
+
+    @SuppressWarnings("unused")
+    private static class Test1 {
+
+        private static int staticValue = 1;
+
+        private int ivalue = 1;
+        private final int finalValue = 1;
+
+        private Test2 test2;
+        private TestSubClass test4;
+
+        private int value() {
+            return this.ivalue;
+        }
+
+        private int addValue(int i) {
+            return this.ivalue + i;
+        }
+
+        private static int svalue() {
+            return 1;
+        }
+
+        private static int svalue(int i) {
+            return i;
+        }
+
+        private static <T> T svalue(T o) {
+            return o;
+        }
+
+        private static int throwfunc1() {
+            throw new IllegalArgumentException("fake runtime exception");
+        }
+
+        private static int throwfunc2() throws Exception {
+            throw new Exception("fake exception");
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static class Test2 {
+
+        private static int staticValue = 2;
+        private final float finalValue = 2f;
+        private Test3 test3;
+
+        private float value() {
+            return this.finalValue;
+        }
+
+        private <T> T value(T o) {
+            return o;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static class Test3 {
+
+        private String str = "3";
+
+        private String value() {
+            return this.str;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static class TestSubClass extends Test1 {
+
+        private int value() {
+            return 4;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/BaseUnitTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/BaseUnitTest.java
new file mode 100644
index 0000000000..6b9ffcc869
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/BaseUnitTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.hugegraph.unit;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.hugegraph.util.ExceptionUtil;
+import org.apache.hugegraph.util.TimeUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class BaseUnitTest {
+
+    @BeforeClass
+    public static void init() {
+        // pass
+    }
+
+    @AfterClass
+    public static void clear() throws Exception {
+        // pass
+    }
+
+    protected static void runWithThreads(int threads, Runnable task) {
+        ExecutorService executor = Executors.newFixedThreadPool(threads);
+        List<Future<?>> futures = new ArrayList<>();
+        for (int i = 0; i < threads; i++) {
+            futures.add(executor.submit(task));
+        }
+        for (Future<?> future : futures) {
+            ExceptionUtil.futureGet(future);
+        }
+    }
+
+    protected static void waitTillNext(long seconds) {
+        TimeUtil.tillNextMillis(TimeUtil.timeGen() + seconds * 1000);
+    }
+
+    public static void downloadFileByUrl(String url, String destPath) {
+        int connectTimeout = 5000;
+        int readTimeout = 5000;
+        try {
+            FileUtils.copyURLToFile(new URL(url), new File(destPath), connectTimeout, readTimeout);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
new file mode 100644
index 0000000000..80095d1ccc
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
@@ -0,0 +1,127 @@
+/*
+ * 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.hugegraph.unit;
+
+import org.apache.hugegraph.testutil.AssertTest;
+import org.apache.hugegraph.testutil.WhiteboxTest;
+import org.apache.hugegraph.unit.config.HugeConfigTest;
+import org.apache.hugegraph.unit.config.OptionSpaceTest;
+import org.apache.hugegraph.unit.event.EventHubTest;
+import org.apache.hugegraph.unit.rest.AbstractRestClientTest;
+import org.apache.hugegraph.unit.version.VersionTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import org.apache.hugegraph.unit.concurrent.AtomicLockTest;
+import org.apache.hugegraph.unit.concurrent.BarrierEventTest;
+import org.apache.hugegraph.unit.concurrent.KeyLockTest;
+import org.apache.hugegraph.unit.concurrent.LockGroupTest;
+import org.apache.hugegraph.unit.concurrent.LockManagerTest;
+import org.apache.hugegraph.unit.concurrent.PausableScheduledThreadPoolTest;
+import org.apache.hugegraph.unit.concurrent.RowLockTest;
+import org.apache.hugegraph.unit.date.SafeDateFormatTest;
+import org.apache.hugegraph.unit.iterator.BatchMapperIteratorTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest;
+import org.apache.hugegraph.unit.iterator.FilterIteratorTest;
+import org.apache.hugegraph.unit.iterator.FlatMapperFilterIteratorTest;
+import org.apache.hugegraph.unit.iterator.FlatMapperIteratorTest;
+import org.apache.hugegraph.unit.iterator.LimitIteratorTest;
+import org.apache.hugegraph.unit.iterator.ListIteratorTest;
+import org.apache.hugegraph.unit.iterator.MapperIteratorTest;
+import org.apache.hugegraph.unit.license.LicenseExtraParamTest;
+import org.apache.hugegraph.unit.license.LicenseCreateParamTest;
+import org.apache.hugegraph.unit.license.LicenseInstallParamTest;
+import org.apache.hugegraph.unit.license.LicenseParamsTest;
+import org.apache.hugegraph.unit.license.MachineInfoTest;
+import org.apache.hugegraph.unit.perf.PerfUtilTest;
+import org.apache.hugegraph.unit.perf.StopwatchTest;
+import org.apache.hugegraph.unit.rest.RestClientTest;
+import org.apache.hugegraph.unit.rest.RestResultTest;
+import org.apache.hugegraph.unit.util.BytesTest;
+import org.apache.hugegraph.unit.util.CollectionUtilTest;
+import org.apache.hugegraph.unit.util.DateUtilTest;
+import org.apache.hugegraph.unit.util.EcheckTest;
+import org.apache.hugegraph.unit.util.HashUtilTest;
+import org.apache.hugegraph.unit.util.InsertionOrderUtilTest;
+import org.apache.hugegraph.unit.util.LogTest;
+import org.apache.hugegraph.unit.util.LongEncodingTest;
+import org.apache.hugegraph.unit.util.NumericUtilTest;
+import org.apache.hugegraph.unit.util.OrderLimitMapTest;
+import org.apache.hugegraph.unit.util.ReflectionUtilTest;
+import org.apache.hugegraph.unit.util.StringUtilTest;
+import org.apache.hugegraph.unit.util.TimeUtilTest;
+import org.apache.hugegraph.unit.util.UnitUtilTest;
+import org.apache.hugegraph.unit.util.VersionUtilTest;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    LockManagerTest.class,
+    LockGroupTest.class,
+    AtomicLockTest.class,
+    KeyLockTest.class,
+    RowLockTest.class,
+    PausableScheduledThreadPoolTest.class,
+
+    HugeConfigTest.class,
+    OptionSpaceTest.class,
+    SafeDateFormatTest.class,
+    BarrierEventTest.class,
+    EventHubTest.class,
+    PerfUtilTest.class,
+    StopwatchTest.class,
+    AbstractRestClientTest.class,
+    RestClientTest.class,
+    RestResultTest.class,
+    VersionTest.class,
+
+    ExtendableIteratorTest.class,
+    FilterIteratorTest.class,
+    LimitIteratorTest.class,
+    MapperIteratorTest.class,
+    FlatMapperIteratorTest.class,
+    FlatMapperFilterIteratorTest.class,
+    ListIteratorTest.class,
+    BatchMapperIteratorTest.class,
+
+    BytesTest.class,
+    CollectionUtilTest.class,
+    EcheckTest.class,
+    HashUtilTest.class,
+    InsertionOrderUtilTest.class,
+    LogTest.class,
+    NumericUtilTest.class,
+    ReflectionUtilTest.class,
+    StringUtilTest.class,
+    TimeUtilTest.class,
+    VersionUtilTest.class,
+    LongEncodingTest.class,
+    OrderLimitMapTest.class,
+    DateUtilTest.class,
+    UnitUtilTest.class,
+
+    LicenseExtraParamTest.class,
+    LicenseCreateParamTest.class,
+    LicenseInstallParamTest.class,
+    LicenseParamsTest.class,
+    MachineInfoTest.class,
+
+    AssertTest.class,
+    WhiteboxTest.class
+})
+public class UnitTestSuite {
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/AtomicLockTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/AtomicLockTest.java
new file mode 100644
index 0000000000..1b2807aa30
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/AtomicLockTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.hugegraph.unit.concurrent;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.concurrent.AtomicLock;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class AtomicLockTest extends BaseUnitTest {
+
+    @Test
+    public void testLockUnlock() {
+        AtomicLock lock = new AtomicLock("lock");
+        Assert.assertEquals("lock", lock.name());
+
+        Assert.assertTrue(lock.lock(0));
+        try {
+            Assert.assertFalse(lock.lock(1));
+            // lock in other threads
+            runWithThreads(2, () -> {
+                Assert.assertFalse(lock.tryLock());
+            });
+            lock.unlock();
+        } finally {
+            lock.unlock();
+            // unlock multi times is OK
+            lock.unlock();
+            lock.unlock();
+        }
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            lock.lock(-1);
+        }, e -> {
+            Assert.assertContains("Locking retry times should be in [0, 10], " +
+                                  "but got -1", e.getMessage());
+        });
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            lock.lock(11);
+        }, e -> {
+            Assert.assertContains("Locking retry times should be in [0, 10], " +
+                                  "but got 11", e.getMessage());
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/BarrierEventTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/BarrierEventTest.java
new file mode 100644
index 0000000000..254f3eb3de
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/BarrierEventTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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.hugegraph.unit.concurrent;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.concurrent.BarrierEvent;
+import org.apache.hugegraph.testutil.Assert;
+
+public class BarrierEventTest {
+    
+    private static final int WAIT_THREADS_COUNT = 10;
+
+    @Test(timeout = 5000)
+    public void testAWait() throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        AtomicInteger result = new AtomicInteger(0);
+        CountDownLatch latch = new CountDownLatch(2);
+        Thread awaitThread = new Thread(() -> {
+            try {
+                barrierEvent.await();
+                result.incrementAndGet();
+            } catch (InterruptedException e) {
+                // Do nothing.
+            } finally {
+                latch.countDown();
+            }
+        });
+        awaitThread.start();
+        Thread signalThread = new Thread(() -> {
+            barrierEvent.signalAll();
+            latch.countDown();
+        });
+        signalThread.start();
+        latch.await();
+        Assert.assertEquals(1, result.get());
+    }
+
+    @Test
+    public void testAWaitWithTimeout() throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        boolean signaled = barrierEvent.await(1L);
+        Assert.assertFalse(signaled);
+    }
+
+    @Test
+    public void testReset() throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        boolean signaled = barrierEvent.await(1L);
+        Assert.assertFalse(signaled);
+        barrierEvent.signal();
+        signaled = barrierEvent.await(1L);
+        Assert.assertTrue(signaled);
+        barrierEvent.reset();
+        signaled = barrierEvent.await(1L);
+        Assert.assertFalse(signaled);
+    }
+
+    @Test
+    public void testSignal() throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        boolean signaled = barrierEvent.await(1L);
+        Assert.assertFalse(signaled);
+        barrierEvent.signal();
+        signaled = barrierEvent.await(1L);
+        Assert.assertTrue(signaled);
+    }
+
+    @Test
+    public void testSignalByMultiThreadWithSignalFirst()
+                throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        AtomicInteger eventCount = new AtomicInteger(0);
+        AtomicInteger waitThreadInterruptedCount = new AtomicInteger(0);
+        ExecutorService executorService =
+                        Executors.newFixedThreadPool(WAIT_THREADS_COUNT + 1);
+        CountDownLatch waitLatch = new CountDownLatch(WAIT_THREADS_COUNT);
+        CountDownLatch signalLatch = new CountDownLatch(1);
+        for (int i = 0; i < WAIT_THREADS_COUNT; i++) {
+            executorService.submit(() -> {
+                try {
+                    signalLatch.await();
+                    barrierEvent.await();
+                    eventCount.incrementAndGet();
+                } catch (InterruptedException e) {
+                    waitThreadInterruptedCount.incrementAndGet();
+                } finally {
+                    waitLatch.countDown();
+                }
+            });
+        }
+
+        executorService.submit(() -> {
+            barrierEvent.signal();
+            signalLatch.countDown();
+        });
+
+        executorService.shutdown();
+        executorService.awaitTermination(2L, TimeUnit.SECONDS);
+        waitLatch.await();
+        Assert.assertEquals(10, eventCount.get());
+        Assert.assertEquals(0, waitThreadInterruptedCount.get());
+    }
+
+    @Test
+    public void testSignalByMultiThreadWithSignalLast()
+                throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        AtomicInteger eventCount = new AtomicInteger(0);
+        AtomicInteger waitThreadInterruptedCount = new AtomicInteger(0);
+        AtomicInteger signalThreadInterruptedCount = new AtomicInteger(0);
+        ExecutorService executorService =
+                        Executors.newFixedThreadPool(WAIT_THREADS_COUNT + 1);
+        CountDownLatch waitLatch = new CountDownLatch(WAIT_THREADS_COUNT);
+        CountDownLatch signalLatch = new CountDownLatch(1);
+        for (int i = 0; i < WAIT_THREADS_COUNT; i++) {
+            executorService.submit(() -> {
+                try {
+                    waitLatch.countDown();
+                    barrierEvent.await();
+                    eventCount.incrementAndGet();
+                } catch (InterruptedException e) {
+                    waitThreadInterruptedCount.incrementAndGet();
+                }
+            });
+        }
+
+        executorService.submit(() -> {
+            try {
+                waitLatch.await();
+            } catch (InterruptedException e) {
+                signalThreadInterruptedCount.incrementAndGet();
+            }
+            barrierEvent.signal();
+            signalLatch.countDown();
+        });
+        signalLatch.await();
+        executorService.shutdownNow();
+        executorService.awaitTermination(1L, TimeUnit.SECONDS);
+        Assert.assertEquals(1, eventCount.get());
+        Assert.assertEquals(WAIT_THREADS_COUNT - 1,
+                            waitThreadInterruptedCount.get());
+        Assert.assertEquals(0, signalThreadInterruptedCount.get());
+    }
+
+    @Test
+    public void testSignalAll() throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        boolean signaled = barrierEvent.await(1L);
+        Assert.assertFalse(signaled);
+        barrierEvent.signalAll();
+        signaled = barrierEvent.await(1L);
+        Assert.assertTrue(signaled);
+    }
+
+    @Test
+    public void testSignalAllByMultiThreadWithSignalFirst()
+                throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        AtomicInteger eventCount = new AtomicInteger(0);
+        AtomicInteger waitThreadInterruptedCount = new AtomicInteger(0);
+        ExecutorService executorService =
+                        Executors.newFixedThreadPool(WAIT_THREADS_COUNT + 1);
+        CountDownLatch waitLatch = new CountDownLatch(WAIT_THREADS_COUNT);
+        CountDownLatch signalLatch = new CountDownLatch(1);
+        for (int i = 0; i < WAIT_THREADS_COUNT; i++) {
+            executorService.submit(() -> {
+                try {
+                    signalLatch.await();
+                    waitLatch.countDown();
+                    barrierEvent.await();
+                    eventCount.incrementAndGet();
+                } catch (InterruptedException e) {
+                    waitThreadInterruptedCount.incrementAndGet();
+                }
+            });
+        }
+
+        executorService.submit(() -> {
+            barrierEvent.signalAll();
+            signalLatch.countDown();
+        });
+
+        executorService.shutdown();
+        executorService.awaitTermination(1L, TimeUnit.SECONDS);
+        Assert.assertEquals(10, eventCount.get());
+        Assert.assertEquals(0, waitThreadInterruptedCount.get());
+    }
+
+    @Test
+    public void testSignalAllByMultiThreadWithSignalLast()
+                throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        AtomicInteger eventCount = new AtomicInteger(0);
+        AtomicInteger waitThreadInterruptedCount = new AtomicInteger(0);
+        AtomicInteger signalThreadInterruptedCount = new AtomicInteger(0);
+        ExecutorService executorService =
+                        Executors.newFixedThreadPool(WAIT_THREADS_COUNT + 1);
+        CountDownLatch waitLatch = new CountDownLatch(WAIT_THREADS_COUNT);
+        CountDownLatch signalLatch = new CountDownLatch(1);
+        for (int i = 0; i < WAIT_THREADS_COUNT; i++) {
+            executorService.submit(() -> {
+                try {
+                    waitLatch.countDown();
+                    barrierEvent.await();
+                    eventCount.incrementAndGet();
+                } catch (InterruptedException e) {
+                    waitThreadInterruptedCount.incrementAndGet();
+                }
+            });
+        }
+
+        executorService.submit(() -> {
+            try {
+                waitLatch.await();
+            } catch (InterruptedException e) {
+                signalThreadInterruptedCount.incrementAndGet();
+            }
+            barrierEvent.signalAll();
+            signalLatch.countDown();
+        });
+        signalLatch.await();
+        executorService.shutdown();
+        executorService.awaitTermination(1L, TimeUnit.SECONDS);
+        Assert.assertEquals(WAIT_THREADS_COUNT, eventCount.get());
+        Assert.assertEquals(0, waitThreadInterruptedCount.get());
+        Assert.assertEquals(0, signalThreadInterruptedCount.get());
+    }
+
+    @Test
+    public void testSignalAllByMultiThreadWithSignalAwaitConcurrent()
+                throws InterruptedException {
+        BarrierEvent barrierEvent = new BarrierEvent();
+        AtomicInteger eventCount = new AtomicInteger(0);
+        AtomicInteger waitThreadInterruptedCount = new AtomicInteger(0);
+        AtomicInteger signalThreadInterruptedCount = new AtomicInteger(0);
+        ExecutorService executorService =
+                        Executors.newFixedThreadPool(WAIT_THREADS_COUNT + 1);
+        CountDownLatch syncLatch = new CountDownLatch(1);
+        for (int i = 0; i < WAIT_THREADS_COUNT; i++) {
+            executorService.submit(() -> {
+                try {
+                    syncLatch.await();
+                    barrierEvent.await();
+                    eventCount.incrementAndGet();
+                } catch (InterruptedException e) {
+                    waitThreadInterruptedCount.incrementAndGet();
+                }
+            });
+        }
+
+        executorService.submit(() -> {
+            try {
+                syncLatch.await();
+            } catch (InterruptedException e) {
+                signalThreadInterruptedCount.incrementAndGet();
+            }
+            barrierEvent.signalAll();
+        });
+        syncLatch.countDown();
+        executorService.shutdown();
+        executorService.awaitTermination(1L, TimeUnit.SECONDS);
+        Assert.assertEquals(WAIT_THREADS_COUNT, eventCount.get());
+        Assert.assertEquals(0, waitThreadInterruptedCount.get());
+        Assert.assertEquals(0, signalThreadInterruptedCount.get());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/KeyLockTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/KeyLockTest.java
new file mode 100644
index 0000000000..3f142be764
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/KeyLockTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.hugegraph.unit.concurrent;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.locks.Lock;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.concurrent.KeyLock;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class KeyLockTest extends BaseUnitTest {
+
+    @Test
+    public void testLockUnlock() {
+        KeyLock locks = new KeyLock();
+
+        locks.lock("1");
+        try {
+            // lock again is OK
+            locks.lock("1");
+            // lock in other threads
+            runWithThreads(1, () -> {
+                locks.lock("2");
+            });
+            locks.unlock("1");
+        } finally {
+            locks.unlock("1");
+        }
+
+        Assert.assertThrows(IllegalMonitorStateException.class, () -> {
+            locks.unlock("2");
+        });
+
+        Assert.assertThrows(IllegalMonitorStateException.class, () -> {
+            locks.unlock("3");
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.lock(null);
+        }, e -> {
+            Assert.assertContains("Lock key can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.unlock(null);
+        }, e -> {
+            Assert.assertContains("Unlock key can't be null", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testLockUnlockAll() {
+        KeyLock locks = new KeyLock();
+
+        List<Lock> ls = locks.lockAll("1", 2);
+        locks.unlockAll(ls);
+
+        runWithThreads(1, () -> {
+            List<Lock> ls2 = locks.lockAll("1", 3);
+            locks.unlockAll(ls2);
+        });
+
+        List<Lock> ls3 = locks.lockAll("1", 2, 3);
+        locks.unlockAll(ls3);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.lockAll("1", null);
+        }, e -> {
+            Assert.assertContains("Lock key can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.lockAll(null, "1");
+        }, e -> {
+            Assert.assertContains("Lock key can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.lockAll(Arrays.asList("1", null, 2).toArray());
+        }, e -> {
+            Assert.assertContains("Lock key can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.lockAll(Collections.emptyList().toArray());
+        }, e -> {
+            Assert.assertContains("Lock keys can't be null or empty",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.lockAll((Object[]) null);
+        }, e -> {
+            Assert.assertContains("Lock keys can't be null or empty",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            locks.unlockAll(null);
+        }, e -> {
+            Assert.assertContains("Unlock locks can't be null", e.getMessage());
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/LockGroupTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/LockGroupTest.java
new file mode 100644
index 0000000000..961fdde7e8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/LockGroupTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.hugegraph.unit.concurrent;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.concurrent.AtomicLock;
+import org.apache.hugegraph.concurrent.KeyLock;
+import org.apache.hugegraph.concurrent.LockGroup;
+import org.apache.hugegraph.concurrent.RowLock;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class LockGroupTest extends BaseUnitTest {
+
+    private static final String GROUP = "LockGroupTest-test-group";
+
+    private final LockGroup group = new LockGroup(GROUP);
+
+    @Test
+    public void testLock() {
+        Lock lock = this.group.lock("lock");
+        Assert.assertTrue(lock instanceof ReentrantLock);
+        Lock lock1 = this.group.lock("lock");
+        Assert.assertSame(lock, lock1);
+
+        lock1.lock();
+        try {
+            // lock again is OK
+            lock1.lock();
+            // lock in other threads
+            runWithThreads(2, () -> {
+                Assert.assertFalse(lock1.tryLock());
+            });
+            lock1.unlock();
+        } finally {
+            lock1.unlock();
+        }
+    }
+
+    @Test
+    public void testAtomicLock() {
+        AtomicLock lock = this.group.atomicLock("lock");
+        Assert.assertNotNull(lock);
+        AtomicLock lock1 = this.group.atomicLock("lock");
+        Assert.assertSame(lock, lock1);
+        Assert.assertEquals("lock", lock1.name());
+    }
+
+    @Test
+    public void testReadWriteLock() {
+        ReadWriteLock lock = this.group.readWriteLock("lock");
+        Assert.assertTrue(lock instanceof ReentrantReadWriteLock);
+        ReadWriteLock lock1 = this.group.readWriteLock("lock");
+        Assert.assertSame(lock, lock1);
+    }
+
+    @Test
+    public void testKeyLock() {
+        KeyLock lock = this.group.keyLock("lock");
+        Assert.assertNotNull(lock);
+        KeyLock lock1 = this.group.keyLock("lock");
+        Assert.assertSame(lock, lock1);
+    }
+
+    @Test
+    public void testKeyLockWithSize() {
+        KeyLock lock = this.group.keyLock("lock", 10);
+        Assert.assertNotNull(lock);
+        KeyLock lock1 = this.group.keyLock("lock");
+        Assert.assertSame(lock, lock1);
+    }
+
+    @Test
+    public void testRowLock() {
+        RowLock<?> lock = this.group.rowLock("lock");
+        Assert.assertNotNull(lock);
+        RowLock<?> lock1 = this.group.rowLock("lock");
+        Assert.assertSame(lock, lock1);
+    }
+
+    @Test
+    public void testName() {
+        Assert.assertEquals(GROUP, this.group.name());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/LockManagerTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/LockManagerTest.java
new file mode 100644
index 0000000000..e0efa80645
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/LockManagerTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.hugegraph.unit.concurrent;
+
+import org.junit.After;
+import org.junit.Test;
+
+import org.apache.hugegraph.concurrent.LockGroup;
+import org.apache.hugegraph.concurrent.LockManager;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class LockManagerTest extends BaseUnitTest {
+
+    private static final String GROUP = "LockManagerTest-test-group";
+    private static final String GROUP2 = GROUP + 2;
+
+    @After
+    public void teardown() {
+        LockManager manager = LockManager.instance();
+
+        if (manager.exists(GROUP)) {
+            manager.destroy(GROUP);
+        }
+
+        if (manager.exists(GROUP2)) {
+            manager.destroy(GROUP2);
+        }
+    }
+
+    @Test
+    public void testCreate() {
+        LockManager manager = LockManager.instance();
+
+        LockGroup lockGroup = manager.create(GROUP);
+        Assert.assertNotNull(lockGroup);
+        Assert.assertEquals(GROUP, lockGroup.name());
+        Assert.assertTrue(manager.exists(GROUP));
+
+        Assert.assertFalse(manager.exists(GROUP2));
+        LockGroup lockGroup2 = manager.create(GROUP2);
+        Assert.assertNotNull(lockGroup2);
+        Assert.assertEquals(GROUP2, lockGroup2.name());
+        Assert.assertTrue(manager.exists(GROUP2));
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            manager.create(GROUP);
+        }, e -> {
+            Assert.assertContains("LockGroup 'LockManagerTest-test-group' " +
+                                  "already exists", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testGet() {
+        LockManager manager = LockManager.instance();
+
+        LockGroup lockGroup = manager.create(GROUP);
+        LockGroup lockGroup2 = manager.create(GROUP2);
+
+        Assert.assertSame(lockGroup, manager.get(GROUP));
+        Assert.assertSame(lockGroup2, manager.get(GROUP2));
+        Assert.assertSame(lockGroup, manager.get(GROUP));
+        Assert.assertSame(lockGroup2, manager.get(GROUP2));
+
+        Assert.assertThrows(RuntimeException.class, () -> {
+            manager.get("fake-lock-group");
+        }, e -> {
+            Assert.assertContains("LockGroup 'fake-lock-group' " +
+                                  "does not exists", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testDestroy() {
+        LockManager manager = LockManager.instance();
+
+        LockGroup lockGroup = manager.create(GROUP);
+        LockGroup lockGroup2 = manager.create(GROUP2);
+
+        Assert.assertTrue(manager.exists(GROUP));
+        Assert.assertTrue(manager.exists(GROUP2));
+        Assert.assertSame(lockGroup, manager.get(GROUP));
+        Assert.assertSame(lockGroup2, manager.get(GROUP2));
+
+        manager.destroy(GROUP);
+        Assert.assertFalse(manager.exists(GROUP));
+        Assert.assertTrue(manager.exists(GROUP2));
+        Assert.assertThrows(RuntimeException.class, () -> {
+            manager.get(GROUP);
+        }, e -> {
+            Assert.assertContains("does not exists", e.getMessage());
+        });
+        Assert.assertSame(lockGroup2, manager.get(GROUP2));
+
+        manager.destroy(GROUP2);
+        Assert.assertFalse(manager.exists(GROUP));
+        Assert.assertFalse(manager.exists(GROUP2));
+        Assert.assertThrows(RuntimeException.class, () -> {
+            manager.get(GROUP);
+        }, e -> {
+            Assert.assertContains("does not exists", e.getMessage());
+        });
+        Assert.assertThrows(RuntimeException.class, () -> {
+            manager.get(GROUP2);
+        }, e -> {
+            Assert.assertContains("does not exists", e.getMessage());
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/PausableScheduledThreadPoolTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/PausableScheduledThreadPoolTest.java
new file mode 100644
index 0000000000..c10b3b8756
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/PausableScheduledThreadPoolTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.hugegraph.unit.concurrent;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.hugegraph.util.ExecutorUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.hugegraph.concurrent.PausableScheduledThreadPool;
+
+public class PausableScheduledThreadPoolTest {
+
+    @Test
+    public void testScheduleWithFixedDelay() throws InterruptedException {
+        PausableScheduledThreadPool executor =
+                ExecutorUtil.newPausableScheduledThreadPool("test");
+        long period = 500L;
+        AtomicInteger counter = new AtomicInteger(0);
+        executor.scheduleWithFixedDelay(() -> {
+            System.out.println("counter: " + counter.incrementAndGet());
+        }, period, period, TimeUnit.MILLISECONDS);
+
+        Thread.sleep((long) (2.1 * period));
+        Assert.assertEquals(2, counter.get());
+
+        // pause
+        executor.pauseSchedule();
+        Thread.sleep(period);
+        Assert.assertEquals(2, counter.get());
+
+        // resume
+        executor.resumeSchedule();
+        Thread.sleep((long) (0.5 * period));
+        Assert.assertEquals(3, counter.get());
+
+        Thread.sleep((long) (0.6 * period));
+        Assert.assertEquals(4, counter.get());
+
+        // pause again
+        executor.pauseSchedule();
+
+        executor.shutdown();
+        executor.awaitTermination(3L, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void testScheduleWithFixedRate() throws InterruptedException {
+        PausableScheduledThreadPool executor =
+                ExecutorUtil.newPausableScheduledThreadPool(2, "test");
+        long period = 500L;
+        AtomicInteger counter = new AtomicInteger(0);
+        executor.scheduleAtFixedRate(() -> {
+            System.out.println("counter: " + counter.incrementAndGet());
+        }, period, period, TimeUnit.MILLISECONDS);
+
+        Thread.sleep((long) (2.1 * period));
+        Assert.assertEquals(2, counter.get());
+
+        // pause
+        executor.pauseSchedule();
+        Thread.sleep(period);
+        Assert.assertEquals(2, counter.get());
+
+        // resume
+        executor.resumeSchedule();
+        Thread.sleep((long) (1.1 * period));
+        Assert.assertEquals(4, counter.get());
+
+        // pause again
+        executor.pauseSchedule();
+
+        executor.shutdownNow();
+        executor.awaitTermination(3L, TimeUnit.SECONDS);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/RowLockTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/RowLockTest.java
new file mode 100644
index 0000000000..b845da46d3
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/concurrent/RowLockTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.hugegraph.unit.concurrent;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.concurrent.RowLock;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import com.google.common.collect.ImmutableSet;
+
+public class RowLockTest extends BaseUnitTest {
+
+    private static final int THREADS_NUM = 8;
+
+    @Test
+    public void testRowLock() {
+        RowLock<Integer> lock = new RowLock<>();
+        // Regular lock and unlock
+        lock.lock(1);
+        lock.unlock(1);
+
+        // Lock one lock multiple times
+        lock.lock(1);
+        lock.lock(1);
+        lock.unlock(1);
+        lock.unlock(1);
+
+        // Unlock one lock multiple times
+        lock.lock(1);
+        lock.unlock(1);
+        lock.unlock(1);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            lock.lock(null);
+        }, e -> {
+            Assert.assertContains("Lock key can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            lock.unlock(null);
+        }, e -> {
+            Assert.assertContains("Unlock key can't be null", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testRowLockMultiRows() {
+        RowLock<Integer> lock = new RowLock<>();
+        lock.lockAll(ImmutableSet.of(1, 2, 3));
+        lock.unlockAll(ImmutableSet.of(1, 2, 3));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            lock.lockAll(null);
+        }, e -> {
+            Assert.assertContains("Lock keys can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            lock.unlockAll(null);
+        }, e -> {
+            Assert.assertContains("Unlock keys can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            lock.lockAll(ImmutableSet.of());
+        }, e -> {
+            Assert.assertContains("Lock keys can't be null or empty",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            lock.unlockAll(ImmutableSet.of());
+        }, e -> {
+            Assert.assertContains("Unlock keys can't be null or empty",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testRowLockWithMultiThreads() {
+        RowLock<Integer> lock = new RowLock<>();
+        Set<String> names = new HashSet<>(THREADS_NUM);
+        List<Integer> keys = new ArrayList<>(5);
+        Random random = new Random();
+        for (int i = 0; i < 5; i++) {
+            keys.add(random.nextInt(THREADS_NUM));
+        }
+
+        Assert.assertEquals(0, names.size());
+
+        runWithThreads(THREADS_NUM, () -> {
+            lock.lockAll(new HashSet<>(keys));
+            names.add(Thread.currentThread().getName());
+            lock.unlockAll(new HashSet<>(keys));
+        });
+
+        Assert.assertEquals(THREADS_NUM, names.size());
+    }
+
+    @Test
+    public void testRowLockWithMultiThreadsLockOneKey() {
+        RowLock<Integer> lock = new RowLock<>();
+        Set<String> names = new HashSet<>(THREADS_NUM);
+
+        Assert.assertEquals(0, names.size());
+
+        Integer key = 1;
+        runWithThreads(THREADS_NUM, () -> {
+            lock.lock(key);
+            names.add(Thread.currentThread().getName());
+            lock.unlock(key);
+        });
+
+        Assert.assertEquals(THREADS_NUM, names.size());
+    }
+
+    @Test
+    public void testRowLockWithMultiThreadsWithRandomKey() {
+        RowLock<Integer> lock = new RowLock<>();
+        Set<String> names = new HashSet<>(THREADS_NUM);
+
+        Assert.assertEquals(0, names.size());
+
+        runWithThreads(THREADS_NUM, () -> {
+            List<Integer> keys = new ArrayList<>(5);
+            Random random = new Random();
+            for (int i = 0; i < 5; i++) {
+                keys.add(random.nextInt(THREADS_NUM));
+            }
+            lock.lockAll(new HashSet<>(keys));
+            names.add(Thread.currentThread().getName());
+            lock.unlockAll(new HashSet<>(keys));
+        });
+
+        Assert.assertEquals(THREADS_NUM, names.size());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/HugeConfigTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/HugeConfigTest.java
new file mode 100644
index 0000000000..4cc04cb4d0
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/HugeConfigTest.java
@@ -0,0 +1,673 @@
+/*
+ * 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.hugegraph.unit.config;
+
+import static org.apache.hugegraph.config.OptionChecker.allowValues;
+import static org.apache.hugegraph.config.OptionChecker.disallowEmpty;
+import static org.apache.hugegraph.config.OptionChecker.inValues;
+import static org.apache.hugegraph.config.OptionChecker.nonNegativeInt;
+import static org.apache.hugegraph.config.OptionChecker.positiveInt;
+import static org.apache.hugegraph.config.OptionChecker.rangeDouble;
+import static org.apache.hugegraph.config.OptionChecker.rangeInt;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.hugegraph.config.ConfigConvOption;
+import org.apache.hugegraph.config.ConfigException;
+import org.apache.hugegraph.config.ConfigListConvOption;
+import org.apache.hugegraph.config.ConfigListOption;
+import org.apache.hugegraph.config.ConfigOption;
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.config.OptionHolder;
+import org.apache.hugegraph.config.OptionSpace;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.commons.configuration2.PropertiesConfiguration;
+import org.apache.commons.configuration2.convert.DisabledListDelimiterHandler;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.commons.configuration2.io.FileHandler;
+import org.apache.commons.io.FileUtils;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class HugeConfigTest extends BaseUnitTest {
+
+    private static final String PATH =
+                         "src/test/java/org/apache/hugegraph/unit/config/";
+    private static final String CONF = PATH + "test.conf";
+
+    @BeforeClass
+    public static void init() {
+        OptionSpace.register("test", TestOptions.class.getName());
+    }
+
+    @Test
+    public void testOptionDataType() {
+        Assert.assertEquals(String.class, TestOptions.text1.dataType());
+        Assert.assertEquals(Integer.class, TestOptions.int1.dataType());
+        Assert.assertEquals(Long.class, TestOptions.long1.dataType());
+        Assert.assertEquals(Float.class, TestOptions.float1.dataType());
+        Assert.assertEquals(Double.class, TestOptions.double1.dataType());
+        Assert.assertEquals(Boolean.class, TestOptions.bool.dataType());
+
+        Assert.assertEquals(Class.class, TestOptions.clazz.dataType());
+
+        Assert.assertEquals(List.class, TestOptions.list.dataType());
+        Assert.assertEquals(List.class, TestOptions.map.dataType());
+
+        Assert.assertEquals(String.class, TestOptions.weekday.dataType());
+        Assert.assertEquals(List.class, TestOptions.weekdays.dataType());
+    }
+
+    @Test
+    public void testOptionDesc() {
+        Assert.assertEquals("description of group1.text1",
+                            TestOptions.text1.desc());
+        Assert.assertEquals("description of group1.text2 sub",
+                            TestSubOptions.text2.desc());
+    }
+
+    @Test
+    public void testOptionRequired() {
+        Assert.assertFalse(TestOptions.text1.required());
+        Assert.assertTrue(TestSubOptions.text2.required());
+    }
+
+    @Test
+    public void testOptionsToString() {
+        Assert.assertEquals("[String]group1.text1=text1-value",
+                            TestOptions.text1.toString());
+        Assert.assertEquals("[Integer]group1.int1=1",
+                            TestOptions.int1.toString());
+        Assert.assertEquals("[Long]group1.long1=100",
+                            TestOptions.long1.toString());
+        Assert.assertEquals("[Float]group1.float1=100.0",
+                            TestOptions.float1.toString());
+        Assert.assertEquals("[Double]group1.double1=100.0",
+                            TestOptions.double1.toString());
+        Assert.assertEquals("[Boolean]group1.bool=true",
+                            TestOptions.bool.toString());
+        Assert.assertEquals("[Class]group1.class=class java.lang.Object",
+                            TestOptions.clazz.toString());
+        Assert.assertEquals("[List]group1.list=[list-value1, list-value2]",
+                            TestOptions.list.toString());
+        Assert.assertEquals("[List]group1.map=[key1:value1, key2:value2]",
+                            TestOptions.map.toString());
+
+        Assert.assertEquals("[String]group1.text1=text1-value",
+                            TestSubOptions.text1.toString());
+        Assert.assertEquals("[String]group1.text2=text2-value-override",
+                            TestSubOptions.text2.toString());
+        Assert.assertEquals("[String]group1.textsub=textsub-value",
+                            TestSubOptions.textsub.toString());
+    }
+
+    @Test
+    public void testOptionWithError() {
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.text",
+                    "description of group1.text",
+                    disallowEmpty(),
+                    ""
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.choice",
+                    "description of group1.choice",
+                    allowValues("CHOICE-1", "CHOICE-2", "CHOICE-3"),
+                    "CHOICE-4"
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigListOption<>(
+                    "group1.list",
+                    true,
+                    "description of group1.list",
+                    disallowEmpty(),
+                    String.class,
+                    ImmutableList.of()
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.int",
+                    "description of group1.int",
+                    positiveInt(),
+                    0
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.int",
+                    "description of group1.int",
+                    nonNegativeInt(),
+                    -1
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.long",
+                    "description of group1.long",
+                    rangeInt(1L, 100L),
+                    0L
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.long",
+                    "description of group1.long",
+                    rangeInt(1L, 100L),
+                    101L
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.double",
+                    "description of group1.double",
+                    rangeDouble(1D, 10D),
+                    0D
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.double",
+                    "description of group1.double",
+                    rangeDouble(1D, 10D),
+                    11D
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigOption<>(
+                    "group1.class",
+                    "description of group1.class",
+                    input -> input != null && input.equals(Long.class),
+                    Integer.class
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigListOption<>(
+                    "group1.list",
+                    "description of list with invalid default values",
+                    disallowEmpty()
+            );
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            new ConfigListOption<>(
+                    "group1.list",
+                    "description of list with invalid default values",
+                    null
+            );
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new ConfigListConvOption<String, WeekDay>(
+                    "group1.list_conv",
+                    "description of list_conv with invalid default values",
+                    disallowEmpty(),
+                    s -> WeekDay.valueOf(s)
+            );
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            new ConfigListConvOption<String, WeekDay>(
+                    "group1.list_conv",
+                    "description of list_conv with invalid default values",
+                    null,
+                    s -> WeekDay.valueOf(s)
+            );
+        });
+    }
+
+    @Test
+    public void testHugeConfig() throws Exception {
+        Configuration conf = new PropertiesConfiguration();
+        Assert.assertEquals(DisabledListDelimiterHandler.INSTANCE,
+               ((AbstractConfiguration) conf).getListDelimiterHandler());
+
+        HugeConfig config = new HugeConfig(conf);
+
+        Assert.assertEquals("text1-value", config.get(TestOptions.text1));
+        Assert.assertEquals("text2-value", config.get(TestOptions.text2));
+        Assert.assertEquals("CHOICE-1", config.get(TestOptions.text3));
+
+        Assert.assertEquals(1, (int) config.get(TestOptions.int1));
+        Assert.assertEquals(10, (int) config.get(TestOptions.int2));
+        Assert.assertEquals(10, (int) config.get(TestOptions.int3));
+
+        Assert.assertEquals(100L, (long) config.get(TestOptions.long1));
+
+        Assert.assertEquals(100.0f, config.get(TestOptions.float1), 0f);
+        Assert.assertEquals(100.0f, config.get(TestOptions.double1), 0d);
+
+        Assert.assertEquals(true, config.get(TestOptions.bool));
+
+        Assert.assertEquals(Object.class, config.get(TestOptions.clazz));
+        Assert.assertThrows(ConfigException.class, () -> {
+            config.setProperty(TestOptions.clazz.name(),
+                               "org.apache.hugegraph.HugeGraph");
+        }, e -> {
+            Assert.assertTrue(e.getCause() instanceof ClassNotFoundException);
+        });
+
+        Assert.assertEquals(Arrays.asList("list-value1", "list-value2"),
+                            config.get(TestOptions.list));
+
+        Assert.assertEquals(ImmutableMap.of("key1", "value1", "key2", "value2"),
+                            config.getMap(TestOptions.map));
+
+        Assert.assertEquals(WeekDay.WEDNESDAY, config.get(TestOptions.weekday));
+        Assert.assertEquals(Arrays.asList(WeekDay.SATURDAY, WeekDay.SUNDAY),
+                            config.get(TestOptions.weekdays));
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new HugeConfig((Configuration) null);
+        });
+    }
+
+    @Test
+    public void testHugeConfigWithFile() throws Exception {
+        HugeConfig config = new HugeConfig(CONF);
+
+        Assert.assertEquals("file-text1-value", config.get(TestOptions.text1));
+        Assert.assertEquals("file-text2-value", config.get(TestOptions.text2));
+        Assert.assertEquals("CHOICE-3", config.get(TestOptions.text3));
+
+        Assert.assertEquals(2, (int) config.get(TestOptions.int1));
+        Assert.assertEquals(0, (int) config.get(TestOptions.int2));
+        Assert.assertEquals(1, (int) config.get(TestOptions.int3));
+
+        Assert.assertEquals(99L, (long) config.get(TestOptions.long1));
+
+        Assert.assertEquals(66.0f, config.get(TestOptions.float1), 0f);
+        Assert.assertEquals(66.0f, config.get(TestOptions.double1), 0d);
+
+        Assert.assertEquals(false, config.get(TestOptions.bool));
+
+        Assert.assertEquals(String.class, config.get(TestOptions.clazz));
+
+        Assert.assertEquals(Arrays.asList("file-v1", "file-v2", "file-v3"),
+                            config.get(TestOptions.list));
+
+        Assert.assertEquals(ImmutableMap.of("key1", "value1", "key3", "value3"),
+                            config.getMap(TestOptions.map));
+
+        Assert.assertEquals(WeekDay.SUNDAY, config.get(TestOptions.weekday));
+        Assert.assertEquals(Arrays.asList(WeekDay.SATURDAY, WeekDay.FRIDAY),
+                            config.get(TestOptions.weekdays));
+    }
+
+    @Test
+    public void testHugeConfigWithConfiguration() throws Exception {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        FileHandler fileHandler = new FileHandler(configuration);
+        fileHandler.load(CONF);
+        HugeConfig config = new HugeConfig(configuration);
+
+        Assert.assertEquals("file-text1-value", config.get(TestOptions.text1));
+        Assert.assertEquals("file-text2-value", config.get(TestOptions.text2));
+        Assert.assertEquals("CHOICE-3", config.get(TestOptions.text3));
+    }
+
+    @Test
+    public void testHugeConfigWithOverride() throws Exception {
+        Configuration conf = new PropertiesConfiguration();
+        Assert.assertEquals(DisabledListDelimiterHandler.INSTANCE,
+               ((AbstractConfiguration) conf).getListDelimiterHandler());
+
+        HugeConfig config = new HugeConfig(conf);
+
+        Assert.assertEquals("text1-value", config.get(TestSubOptions.text1));
+
+        Assert.assertEquals("text2-value-override",
+                            config.get(TestSubOptions.text2));
+        Assert.assertEquals("textsub-value",
+                            config.get(TestSubOptions.textsub));
+    }
+
+    @Test
+    public void testHugeConfigWithTypeError() {
+        OptionSpace.register("test-type-error",
+                             TestOptionsWithTypeError.class.getName());
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new HugeConfig(PATH + "test-type-error.conf");
+        });
+    }
+
+    @Test
+    public void testHugeConfigWithCheckError() throws Exception {
+        OptionSpace.register("test-check-error",
+                             TestOptionsWithCheckError.class.getName());
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            new HugeConfig(PATH + "test-check-error.conf");
+        });
+    }
+
+    @Test
+    public void testHugeConfigWithListOptionError() throws Exception {
+        OptionSpace.register("test-list-error",
+                             TestOptionsWithListError.class.getName());
+
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            new HugeConfig(PATH + "test-list-error.conf");
+        });
+    }
+
+    @Test
+    public void testSaveHugeConfig() throws ConfigurationException,
+                                            IOException {
+        HugeConfig config = new HugeConfig(CONF);
+        Assert.assertEquals("file-text1-value", config.get(TestOptions.text1));
+
+        File copiedFile = new File("copied.conf");
+        config.save(copiedFile);
+        Assert.assertTrue(copiedFile.exists());
+        Assert.assertTrue(copiedFile.length() > 0);
+
+        try {
+            HugeConfig copiedConfig = new HugeConfig(copiedFile.getPath());
+            Assert.assertEquals(IteratorUtils.toList(config.getKeys()),
+                                IteratorUtils.toList(copiedConfig.getKeys()));
+            Assert.assertEquals(config.get(TestOptions.text1),
+                                copiedConfig.get(TestOptions.text1));
+        } finally {
+            FileUtils.forceDelete(copiedFile);
+        }
+    }
+
+    @Test
+    public void testFromMapConfigurationWithList() {
+        Map<String, String> options = new HashMap<>();
+        options.put(TestOptions.list.name(), "[a, b]");
+        MapConfiguration mapConfiguration = new MapConfiguration(options);
+        HugeConfig hugeConfig = new HugeConfig(mapConfiguration);
+        List<String> values = hugeConfig.get(TestOptions.list);
+        Assert.assertEquals(2, values.size());
+        Assert.assertTrue(values.contains("a"));
+        Assert.assertTrue(values.contains("b"));
+    }
+
+    public static class TestOptions extends OptionHolder {
+
+        private static volatile TestOptions instance;
+
+        public static synchronized TestOptions instance() {
+            if (instance == null) {
+                instance = new TestOptions();
+                instance.registerOptions();
+            }
+            return instance;
+        }
+
+        public static final ConfigOption<String> text1 =
+                new ConfigOption<>(
+                        "group1.text1",
+                        "description of group1.text1",
+                        disallowEmpty(),
+                        "text1-value"
+                );
+
+        public static final ConfigOption<String> text2 =
+                new ConfigOption<>(
+                        "group1.text2",
+                        "description of group1.text2",
+                        "text2-value"
+                );
+
+        public static final ConfigOption<String> text3 =
+                new ConfigOption<>(
+                        "group1.text3",
+                        "description of group1.text3",
+                        allowValues("CHOICE-1", "CHOICE-2", "CHOICE-3"),
+                        "CHOICE-1"
+                );
+
+        public static final ConfigOption<Integer> int1 =
+                new ConfigOption<>(
+                        "group1.int1",
+                        "description of group1.int1",
+                        rangeInt(1, 100),
+                        1
+                );
+
+        public static final ConfigOption<Integer> int2 =
+                new ConfigOption<>(
+                        "group1.int2",
+                        "description of group1.int2",
+                        nonNegativeInt(),
+                        10
+                );
+
+        public static final ConfigOption<Integer> int3 =
+                new ConfigOption<>(
+                        "group1.int3",
+                        "description of group1.int3",
+                        positiveInt(),
+                        10
+                );
+
+        public static final ConfigOption<Long> long1 =
+                new ConfigOption<>(
+                        "group1.long1",
+                        "description of group1.long1",
+                        rangeInt(1L, 100L),
+                        100L
+                );
+
+        public static final ConfigOption<Float> float1 =
+                new ConfigOption<>(
+                        "group1.float1",
+                        "description of group1.float1",
+                        rangeDouble(1.0f, 100.0f),
+                        100.0f
+                );
+
+        public static final ConfigOption<Double> double1 =
+                new ConfigOption<>(
+                        "group1.double1",
+                        "description of group1.double1",
+                        rangeDouble(1.0, 100.0),
+                        100.0
+                );
+
+        public static final ConfigOption<Boolean> bool =
+                new ConfigOption<>(
+                        "group1.bool",
+                        "description of group1.bool",
+                        disallowEmpty(),
+                        true
+                );
+
+        public static final ConfigOption<Class<?>> clazz =
+                new ConfigOption<>(
+                        "group1.class",
+                        "description of group1.class",
+                        disallowEmpty(),
+                        Object.class
+                );
+
+        public static final ConfigConvOption<String, WeekDay> weekday =
+                new ConfigConvOption<>(
+                        "group1.weekday",
+                        "description of group1.weekday",
+                        allowValues("SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
+                                    "THURSDAY", "FRIDAY", "SATURDAY"),
+                        WeekDay::valueOf,
+                        "WEDNESDAY"
+                );
+
+        public static final ConfigListConvOption<String, WeekDay> weekdays =
+                new ConfigListConvOption<>(
+                        "group1.weekdays",
+                        "description of group1.weekdays",
+                        inValues("SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
+                                 "THURSDAY", "FRIDAY", "SATURDAY"),
+                        WeekDay::valueOf,
+                        "SATURDAY", "SUNDAY"
+                );
+
+        public static final ConfigListOption<String> list =
+                new ConfigListOption<>(
+                        "group1.list",
+                        "description of group1.list",
+                        disallowEmpty(),
+                        "list-value1", "list-value2"
+                );
+
+        public static final ConfigListOption<String> map =
+                new ConfigListOption<>(
+                        "group1.map",
+                        "description of group1.map",
+                        disallowEmpty(),
+                        "key1:value1", "key2:value2"
+                );
+    }
+
+    public static class TestSubOptions extends TestOptions {
+
+        public static final ConfigOption<String> text2 =
+                new ConfigOption<>(
+                        "group1.text2",
+                        true,
+                        "description of group1.text2 sub",
+                        disallowEmpty(),
+                        String.class,
+                        "text2-value-override"
+                );
+
+        public static final ConfigOption<String> textsub =
+                new ConfigOption<>(
+                        "group1.textsub",
+                        "description of group1.textsub",
+                        disallowEmpty(),
+                        "textsub-value"
+                );
+    }
+
+    public static class TestOptionsWithTypeError extends OptionHolder {
+
+        private static volatile TestOptionsWithTypeError instance;
+
+        public static synchronized TestOptionsWithTypeError instance() {
+            if (instance == null) {
+                instance = new TestOptionsWithTypeError();
+                instance.registerOptions();
+            }
+            return instance;
+        }
+
+        public static final ConfigOption<Integer> intError =
+                new ConfigOption<>(
+                        "group1.int_type_error",
+                        "description of group1.int_type_error",
+                        rangeInt(1, 100),
+                        1
+                );
+    }
+
+    public static class TestOptionsWithCheckError extends OptionHolder {
+
+        private static volatile TestOptionsWithCheckError instance;
+
+        public static synchronized TestOptionsWithCheckError instance() {
+            if (instance == null) {
+                instance = new TestOptionsWithCheckError();
+                instance.registerOptions();
+            }
+            return instance;
+        }
+
+        public static final ConfigOption<Integer> intError =
+                new ConfigOption<>(
+                        "group1.int_check_error",
+                        "description of group1.int_check_error",
+                        rangeInt(1, 100),
+                        1
+                );
+    }
+
+    public static class TestOptionsWithListError extends OptionHolder {
+
+        private static volatile TestOptionsWithListError instance;
+
+        public static synchronized TestOptionsWithListError instance() {
+            if (instance == null) {
+                instance = new TestOptionsWithListError();
+                instance.registerOptions();
+            }
+            return instance;
+        }
+
+        public static final InvalidConfigListOption<Integer> listError =
+                new InvalidConfigListOption<>(
+                        "group1.list_for_list_error",
+                        "description of group1.list_for_list_error",
+                        disallowEmpty(),
+                        1
+                );
+
+        static class InvalidConfigListOption<T> extends ConfigOption<List<T>> {
+
+            @SuppressWarnings("unchecked")
+            public InvalidConfigListOption(String name, String desc,
+                                           Predicate<List<T>> pred,
+                                           T... values) {
+                super(name, false, desc, pred,
+                      (Class<List<T>>) Arrays.asList(values).getClass(),
+                      Arrays.asList(values));
+            }
+
+            @Override
+            protected boolean forList() {
+                return false;
+            }
+        }
+    }
+
+    public enum WeekDay {
+
+        SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/OptionSpaceTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/OptionSpaceTest.java
new file mode 100644
index 0000000000..ab794faf5d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/OptionSpaceTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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.hugegraph.unit.config;
+
+import static org.apache.hugegraph.config.OptionChecker.disallowEmpty;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.config.OptionSpace;
+import org.apache.hugegraph.config.OptionHolder;
+import org.apache.hugegraph.config.ConfigException;
+import org.apache.hugegraph.config.ConfigOption;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import com.google.common.base.Predicate;
+
+public class OptionSpaceTest extends BaseUnitTest {
+
+    @Test
+    public void tesRegister() {
+        int oldSize = OptionSpace.keys().size();
+
+        OptionSpace.register("testgroup1", OptionHolder1.class.getName());
+        Assert.assertEquals(oldSize + 2, OptionSpace.keys().size());
+        Assert.assertTrue(OptionSpace.containKey("testgroup1.text1"));
+        Assert.assertTrue(OptionSpace.containKey("testgroup1.text2"));
+
+        OptionSpace.register("testgroup1", new OptionHolder1());
+        Assert.assertEquals(oldSize + 2, OptionSpace.keys().size());
+        Assert.assertTrue(OptionSpace.containKey("testgroup1.text1"));
+        Assert.assertTrue(OptionSpace.containKey("testgroup1.text2"));
+
+        OptionSpace.register("testgroup2", OptionHolder2.class.getName());
+        Assert.assertEquals(oldSize + 4, OptionSpace.keys().size());
+
+        Assert.assertTrue(OptionSpace.containKey("testgroup1.text1"));
+        Assert.assertTrue(OptionSpace.containKey("testgroup1.text2"));
+        Assert.assertTrue(OptionSpace.containKey("testgroup2.text1"));
+        Assert.assertTrue(OptionSpace.containKey("testgroup2.text2"));
+
+        Assert.assertEquals("text1 value",
+                            OptionSpace.get("testgroup1.text1").defaultValue());
+        Assert.assertEquals("text2 value",
+                            OptionSpace.get("testgroup1.text2").defaultValue());
+        Assert.assertEquals("text1 value",
+                            OptionSpace.get("testgroup2.text1").defaultValue());
+        Assert.assertEquals("text2 value",
+                            OptionSpace.get("testgroup2.text2").defaultValue());
+    }
+
+    @Test
+    public void testRegisterWithError() {
+        Assert.assertThrows(ConfigException.class, () -> {
+            OptionSpace.register("test-error", "fake");
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            OptionSpace.register("test-error", Exception.class.getName());
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            OptionSpace.register("test-error",
+                                 OptionHolderWithoutInstance.class.getName());
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            OptionSpace.register("test-error", OptionHolderWithNonStaticInstance
+                                               .class.getName());
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            OptionSpace.register("test-error",
+                                 OptionHolderWithInstanceNull.class.getName());
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            OptionSpace.register("test-error",
+                                 OptionHolderWithInstanceThrow.class.getName());
+        });
+
+        Assert.assertThrows(ConfigException.class, () -> {
+            OptionSpace.register("test-error",
+                                 OptionHolderWithInvalidOption.class.getName());
+        });
+    }
+
+    public static class OptionHolderWithoutInstance extends OptionHolder {
+        // no instance()
+    }
+
+    public static class OptionHolderWithNonStaticInstance extends OptionHolder {
+
+        // not static instance()
+        public OptionHolderWithNonStaticInstance instance() {
+            return new OptionHolderWithNonStaticInstance();
+        }
+    }
+
+    public static class OptionHolderWithInstanceNull extends OptionHolder {
+
+        public static OptionHolderWithInstanceNull instance() {
+            return null;
+        }
+    }
+
+    public static class OptionHolderWithInstanceThrow extends OptionHolder {
+
+        public static OptionHolderWithInstanceNull instance() {
+            throw new RuntimeException("test error");
+        }
+    }
+
+    public static class OptionHolderWithInvalidOption extends OptionHolder {
+
+        public static OptionHolderWithInvalidOption instance() {
+            return new OptionHolderWithInvalidOption();
+        }
+
+        private OptionHolderWithInvalidOption() {
+            this.registerOptions();
+        }
+
+        public static final String fake = "fake";
+
+        public static final ConfigOption<String> invalid =
+                new InvalidOption<>(
+                        "group1.text1",
+                        "description of group1.text1",
+                        disallowEmpty(),
+                        "value"
+                );
+
+        public static class InvalidOption<T> extends ConfigOption<T> {
+
+            public InvalidOption(String name, String desc,
+                                 Predicate<T> pred, T value) {
+                super(name, desc, pred, value);
+            }
+
+            @Override
+            public String name() {
+                throw new RuntimeException("fake");
+            }
+        }
+    }
+
+    public static class OptionHolder1 extends OptionHolder {
+
+        public static OptionHolder1 instance() {
+            return new OptionHolder1();
+        }
+
+        OptionHolder1() {
+            this.registerOptions();
+        }
+
+        public static final ConfigOption<String> text1 =
+                new ConfigOption<>(
+                        "testgroup1.text1",
+                        "description of testgroup1.text1",
+                        disallowEmpty(),
+                        "text1 value"
+                );
+
+        public static final ConfigOption<String> text2 =
+                new ConfigOption<>(
+                        "testgroup1.text2",
+                        "description of testgroup1.text2",
+                        disallowEmpty(),
+                        "text2 value"
+                );
+    }
+
+    public static class OptionHolder2 extends OptionHolder {
+
+        public static OptionHolder2 instance() {
+            return new OptionHolder2();
+        }
+
+        OptionHolder2() {
+            this.registerOptions();
+        }
+
+        public static final ConfigOption<String> text1 =
+                new ConfigOption<>(
+                        "testgroup2.text1",
+                        "description of testgroup2.text1",
+                        disallowEmpty(),
+                        "text1 value"
+                );
+
+        public static final ConfigOption<String> text2 =
+                new ConfigOption<>(
+                        "testgroup2.text2",
+                        "description of testgroup2.text2",
+                        disallowEmpty(),
+                        "text2 value"
+                );
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-check-error.conf b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-check-error.conf
new file mode 100644
index 0000000000..53aec18463
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-check-error.conf
@@ -0,0 +1 @@
+group1.int_check_error=101
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-list-error.conf b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-list-error.conf
new file mode 100644
index 0000000000..907b197f44
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-list-error.conf
@@ -0,0 +1,2 @@
+group1.list_for_list_error=[1,2,3]
+
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-type-error.conf b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-type-error.conf
new file mode 100644
index 0000000000..ac70d48913
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test-type-error.conf
@@ -0,0 +1 @@
+group1.int_type_error=string
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test.conf b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test.conf
new file mode 100644
index 0000000000..9ee10b0a34
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/config/test.conf
@@ -0,0 +1,23 @@
+group1.text1=file-text1-value
+group1.text2=file-text2-value
+group1.text3=CHOICE-3
+
+group1.int1=2
+group1.int2=0
+group1.int3=1
+group1.long1=99
+
+group1.float1=66
+group1.double1=66
+
+group1.bool=false
+
+group1.class=java.lang.String
+
+group1.list=[file-v1, file-v2, file-v3]
+group1.map=[key1:value1, key3:value3]
+
+group1.weekday=SUNDAY
+group1.weekdays=[SATURDAY, FRIDAY]
+
+group1.no-used=value
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/date/SafeDateFormatTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/date/SafeDateFormatTest.java
new file mode 100644
index 0000000000..30729ebab4
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/date/SafeDateFormatTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.hugegraph.unit.date;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.hugegraph.date.SafeDateFormat;
+import org.junit.Test;
+
+import org.apache.hugegraph.testutil.Assert;
+import com.google.common.collect.ImmutableList;
+
+public class SafeDateFormatTest {
+
+    @Test
+    @SuppressWarnings("deprecation")
+    public void testSafeDateFormatInConcurrency() throws Exception {
+        SafeDateFormat format = new SafeDateFormat("yyyy-MM-dd");
+        List<String> sources = ImmutableList.of(
+                "2010-01-01",
+                "2011-02-02",
+                "2012-03-03",
+                "2013-04-04",
+                "2014-05-05",
+                "2015-06-06",
+                "2016-07-07",
+                "2017-08-08",
+                "2018-09-09",
+                "2019-10-10"
+        );
+        List<Date> dates = new ArrayList<>(sources.size());
+
+        for (int i = 0; i < sources.size(); i++) {
+            Date date = format.parse(sources.get(i));
+            Assert.assertEquals(2010 + i, 1900 + date.getYear());
+            Assert.assertEquals(i, date.getMonth());
+            Assert.assertEquals(1 + i, date.getDate());
+            dates.add(date);
+        }
+
+        List<Exception> exceptions = new ArrayList<>();
+        final CountDownLatch latch = new CountDownLatch(1);
+        int threadCount = 10;
+        List<Thread> threads = new ArrayList<>(threadCount);
+        for (int t = 0; t < threadCount; t++) {
+            Thread thread = new Thread(() -> {
+                try {
+                    latch.await();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+
+                for (int i = 0; i < sources.size(); i++) {
+                    try {
+                        Assert.assertEquals(dates.get(i),
+                                            format.parse(sources.get(i)));
+                        Assert.assertEquals(sources.get(i),
+                                            format.format(dates.get(i)));
+                    } catch (Exception e) {
+                        exceptions.add(e);
+                    }
+                }
+            });
+            threads.add(thread);
+        }
+
+        for (Thread thread : threads) {
+            thread.start();
+        }
+
+        latch.countDown();
+
+        for (Thread thread : threads) {
+            thread.join();
+        }
+
+        Assert.assertTrue(exceptions.isEmpty());
+    }
+
+    @Test
+    public void testTimeZone() throws ParseException {
+        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        df.setTimeZone(TimeZone.getTimeZone("GMT+10"));
+
+        SafeDateFormat sdf = new SafeDateFormat("yyyy-MM-dd HH:mm:ss");
+        sdf.setTimeZone("GMT+10");
+
+        Assert.assertEquals(df.getTimeZone(), sdf.getTimeZone());
+        Assert.assertEquals(df.parse("2019-08-10 00:00:00"),
+                            sdf.parse("2019-08-10 00:00:00"));
+        Assert.assertEquals("2019-08-10 00:00:00",
+                            sdf.format(sdf.parse("2019-08-10 00:00:00")));
+        Assert.assertEquals(df.format(df.parse("2019-08-10 00:00:00")),
+                            sdf.format(sdf.parse("2019-08-10 00:00:00")));
+
+        sdf.setTimeZone("GMT+11");
+        Assert.assertNotEquals(df.getTimeZone(), sdf.getTimeZone());
+        Assert.assertNotEquals(df.parse("2019-08-10 00:00:00"),
+                               sdf.parse("2019-08-10 00:00:00"));
+        Assert.assertEquals("2019-08-10 00:00:00",
+                            sdf.format(sdf.parse("2019-08-10 00:00:00")));
+        Assert.assertEquals(df.format(df.parse("2019-08-10 00:00:00")),
+                            sdf.format(sdf.parse("2019-08-10 00:00:00")));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/event/EventHubTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/event/EventHubTest.java
new file mode 100644
index 0000000000..dff0227022
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/event/EventHubTest.java
@@ -0,0 +1,462 @@
+/*
+ * 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.hugegraph.unit.event;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.event.Event;
+import org.apache.hugegraph.event.EventHub;
+import org.apache.hugegraph.event.EventListener;
+
+public class EventHubTest extends BaseUnitTest {
+
+    private static final int THREADS_NUM = 8;
+
+    private EventHub eventHub = null;
+
+    @BeforeClass
+    public static void init() {
+        EventHub.init(THREADS_NUM);
+    }
+
+    @AfterClass
+    public static void clear() throws InterruptedException {
+        EventHub.destroy(30);
+    }
+
+    @Before
+    public void setup() {
+        this.eventHub = new EventHub("test");
+        Assert.assertEquals("test", this.eventHub.name());
+    }
+
+    @After
+    public void teardown() {
+        this.eventHub = null;
+    }
+
+    private void wait100ms() {
+        try {
+            Thread.sleep(100);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testEventGetListenerNonResult() {
+        Assert.assertFalse(this.eventHub.containsListener("not-exist"));
+        Assert.assertEquals(0, this.eventHub.listeners("not-exist").size());
+    }
+
+    @Test
+    public void testEventAddListener() {
+        final String event = "event-test";
+
+        EventListener listener = (Event e) -> null;
+
+        this.eventHub.listen(event, listener);
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(1, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
+    }
+
+    @Test
+    public void testEventAddListenerTwice() {
+        final String event = "event-test";
+
+        EventListener listener = (Event e) -> null;
+
+        this.eventHub.listen(event, listener);
+        this.eventHub.listen(event, listener);
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(2, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
+        Assert.assertEquals(listener, this.eventHub.listeners(event).get(1));
+    }
+
+    @Test
+    public void testEventRemoveListener() {
+        final String event = "event-test";
+
+        EventListener listener = (Event e) -> null;
+
+        this.eventHub.listen(event, listener);
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(1, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
+
+        Assert.assertEquals(1, this.eventHub.unlisten(event, listener));
+
+        Assert.assertFalse(this.eventHub.containsListener(event));
+        Assert.assertEquals(0, this.eventHub.listeners(event).size());
+    }
+
+    @Test
+    public void testEventRemoveListenerButNonResult() {
+        final String event = "event-test";
+
+        EventListener listener = (Event e) -> null;
+
+        this.eventHub.listen(event, listener);
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(1, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
+
+        Assert.assertEquals(0, this.eventHub.unlisten(event, null));
+        Assert.assertEquals(0, this.eventHub.unlisten("event-fake", listener));
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(1, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
+    }
+
+    @Test
+    public void testEventRemoveListenerOfOneInTwo() {
+        final String event1 = "event-test1";
+        final String event2 = "event-test2";
+
+        EventListener listener = (Event e) -> null;
+
+        this.eventHub.listen(event1, listener);
+        this.eventHub.listen(event2, listener);
+
+        Assert.assertTrue(this.eventHub.containsListener(event1));
+        Assert.assertEquals(1, this.eventHub.listeners(event1).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event1).get(0));
+
+        Assert.assertTrue(this.eventHub.containsListener(event2));
+        Assert.assertEquals(1, this.eventHub.listeners(event2).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event2).get(0));
+
+        Assert.assertEquals(1, this.eventHub.unlisten(event1, listener));
+
+        Assert.assertFalse(this.eventHub.containsListener(event1));
+        Assert.assertFalse(this.eventHub.containsListener(event1));
+        Assert.assertEquals(0, this.eventHub.listeners(event1).size());
+
+        Assert.assertTrue(this.eventHub.containsListener(event2));
+        Assert.assertEquals(1, this.eventHub.listeners(event2).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event2).get(0));
+    }
+
+    @Test
+    public void testEventRemoveListenerByEvent() {
+        final String event = "event-test";
+
+        EventListener listener1 = (Event e) -> null;
+        EventListener listener2 = (Event e) -> null;
+
+        this.eventHub.listen(event, listener1);
+        this.eventHub.listen(event, listener2);
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(2, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener1, this.eventHub.listeners(event).get(0));
+        Assert.assertEquals(listener2, this.eventHub.listeners(event).get(1));
+
+        Assert.assertEquals(2, this.eventHub.unlisten(event).size());
+
+        Assert.assertFalse(this.eventHub.containsListener(event));
+        Assert.assertEquals(0, this.eventHub.listeners(event).size());
+    }
+
+    @Test
+    public void testEventRemoveListenerByEventButNonResult() {
+        final String event = "event-test";
+
+        EventListener listener1 = (Event e) -> null;
+        EventListener listener2 = (Event e) -> null;
+
+        this.eventHub.listen(event, listener1);
+        this.eventHub.listen(event, listener2);
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(2, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener1, this.eventHub.listeners(event).get(0));
+        Assert.assertEquals(listener2, this.eventHub.listeners(event).get(1));
+
+        Assert.assertEquals(0, this.eventHub.unlisten("event-fake").size());
+
+        Assert.assertEquals(2, this.eventHub.listeners(event).size());
+    }
+
+    @Test
+    public void testEventRemoveListenerByEventOf2SameListener() {
+        final String event = "event-test";
+
+        EventListener listener = (Event e) -> null;
+
+        this.eventHub.listen(event, listener);
+        this.eventHub.listen(event, listener);
+
+        Assert.assertTrue(this.eventHub.containsListener(event));
+        Assert.assertEquals(2, this.eventHub.listeners(event).size());
+        Assert.assertEquals(listener, this.eventHub.listeners(event).get(0));
+
+        Assert.assertEquals(2, this.eventHub.unlisten(event, listener));
+
+        Assert.assertFalse(this.eventHub.containsListener(event));
+        Assert.assertEquals(0, this.eventHub.listeners(event).size());
+    }
+
+    @Test
+    public void testEventCallWithoutArg() {
+        final String call = "event-call";
+
+        this.eventHub.listen(call, event -> {
+            Assert.assertEquals(call, event.name());
+            Assert.assertEquals(0, event.args().length);
+            return "fake-event-result";
+        });
+
+        Assert.assertEquals("fake-event-result", this.eventHub.call(call));
+    }
+
+    @Test
+    public void testEventCallWithArg1() {
+        final String call = "event-call";
+
+        this.eventHub.listen(call, event -> {
+            Assert.assertEquals(call, event.name());
+
+            event.checkArgs(Float.class);
+
+            Object[] args = event.args();
+            Assert.assertEquals(1, args.length);
+            Assert.assertEquals(3.14f, args[0]);
+
+            return "fake-event-result";
+        });
+
+        Assert.assertEquals("fake-event-result",
+                            this.eventHub.call(call, 3.14f));
+    }
+
+    @Test
+    public void testEventCallWithArg2() {
+        final String call = "event-call";
+
+        this.eventHub.listen(call, event -> {
+            Assert.assertEquals(call, event.name());
+
+            event.checkArgs(String.class, Integer.class);
+
+            Object[] args = event.args();
+            Assert.assertEquals(2, args.length);
+            Assert.assertEquals("fake-arg0", args[0]);
+            Assert.assertEquals(123, args[1]);
+
+            return "fake-event-result";
+        });
+
+        Assert.assertEquals("fake-event-result",
+                            this.eventHub.call(call, "fake-arg0", 123));
+    }
+
+    @Test
+    public void testEventCallWithArg2ButArgNotMatched() {
+        final String call = "event-call";
+
+        this.eventHub.listen(call, event -> {
+            Assert.assertEquals(call, event.name());
+
+            event.checkArgs(String.class, Integer.class);
+
+            Object[] args = event.args();
+            Assert.assertEquals(2, args.length);
+            Assert.assertEquals("fake-arg0", args[0]);
+            Assert.assertEquals(123, args[1]);
+
+            return "fake-event-result";
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            this.eventHub.call(call, "fake-arg0");
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            this.eventHub.call(call, "fake-arg0", 123, "456");
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            this.eventHub.call(call, 123, "fake-arg0");
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            this.eventHub.call(call, "fake-arg0", 123f);
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            this.eventHub.call(call, "fake-arg0", "123");
+        });
+    }
+
+    @Test
+    public void testEventNotify() {
+        final String notify = "event-notify";
+        AtomicInteger count = new AtomicInteger();
+
+        this.eventHub.listen(notify, event -> {
+            Assert.assertEquals(notify, event.name());
+            Assert.assertEquals(0, event.args().length);
+            count.incrementAndGet();
+            return true;
+        });
+
+        this.eventHub.notify(notify);
+
+        // Maybe should improve
+        this.wait100ms();
+
+        Assert.assertEquals(1, count.get());
+    }
+
+    @Test
+    public void testEventNotifyAny() {
+        AtomicInteger count = new AtomicInteger();
+
+        this.eventHub.listen(EventHub.ANY_EVENT, event -> {
+            Assert.assertTrue(ImmutableList.of("event1", "event2")
+                                           .contains(event.name()));
+            Assert.assertEquals(0, event.args().length);
+            count.incrementAndGet();
+            return true;
+        });
+
+        this.eventHub.notify("event1");
+        this.eventHub.notify("event2");
+
+        // Maybe should improve
+        this.wait100ms();
+
+        Assert.assertEquals(2, count.get());
+    }
+
+    @Test
+    public void testEventNotifyWithArg2() {
+        final String notify = "event-notify";
+        AtomicInteger count = new AtomicInteger();
+
+        this.eventHub.listen(notify, event -> {
+            Assert.assertEquals(notify, event.name());
+
+            event.checkArgs(String.class, Integer.class);
+
+            Object[] args = event.args();
+            Assert.assertEquals("fake-arg0", args[0]);
+            Assert.assertEquals(123, args[1]);
+
+            count.incrementAndGet();
+            return true;
+        });
+
+        this.eventHub.notify(notify, "fake-arg0", 123);
+
+        // Maybe should improve
+        this.wait100ms();
+
+        Assert.assertEquals(1, count.get());
+    }
+
+    @Test
+    public void testEventNotifyWithMultiThreads() throws InterruptedException {
+        final String notify = "event-notify";
+
+        EventListener listener1 = event -> {
+            Assert.assertEquals(notify, event.name());
+            event.checkArgs(Integer.class);
+            return null;
+        };
+
+        EventListener listener2 = event -> {
+            Assert.assertEquals(notify, event.name());
+
+            event.checkArgs(Integer.class);
+            int i = (int) event.args()[0];
+            if (i % 10000 == 0) {
+                System.out.println("On event '" + notify + "': " + i);
+            }
+            return null;
+        };
+
+        Thread listenerUpdateThread = new Thread(() -> {
+            // This will cost about 1s
+            for (int i = 0; i < 10; i++) {
+                this.eventHub.listen(notify, listener1);
+                if (!this.eventHub.listeners(notify).contains(listener2)) {
+                    this.eventHub.listen(notify, listener2);
+                }
+
+                this.wait100ms();
+
+                if (i % 2 == 0) {
+                    this.eventHub.unlisten(notify);
+                } else {
+                    this.eventHub.unlisten(notify, listener1);
+                }
+            }
+        });
+        listenerUpdateThread.start();
+
+        runWithThreads(THREADS_NUM, () -> {
+            // This will cost about 1s ~ 2s
+            for (int i = 0; i < 10000 * 10; i++) {
+                this.eventHub.notify(notify, i);
+                Thread.yield();
+            }
+        });
+
+        listenerUpdateThread.join();
+    }
+
+    @Test
+    public void testEventCallWithMultiThreads() {
+        final String call = "event-call";
+
+        EventListener listener = event -> {
+            Assert.assertEquals(call, event.name());
+
+            event.checkArgs(Integer.class);
+            int i = (int) event.args()[0];
+            return i;
+        };
+
+        this.eventHub.listen(call, listener);
+
+        runWithThreads(THREADS_NUM, () -> {
+            for (int i = 0; i < 10000 * 1000; i++) {
+                Assert.assertEquals(i, this.eventHub.call(call, i));
+            }
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/BatchMapperIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/BatchMapperIteratorTest.java
new file mode 100644
index 0000000000..52bc632c0a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/BatchMapperIteratorTest.java
@@ -0,0 +1,337 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.BatchMapperIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor;
+import com.google.common.collect.ImmutableList;
+
+@SuppressWarnings("resource")
+public class BatchMapperIteratorTest extends BaseUnitTest {
+
+    private static final Iterator<Integer> EMPTY = Collections.emptyIterator();
+
+    private static final List<Integer> DATA1 = ImmutableList.of(1);
+    private static final List<Integer> DATA2 = ImmutableList.of(2, 3);
+    private static final List<Integer> DATA3 = ImmutableList.of(4, 5, 6);
+
+    private static final Function<List<Integer>, Iterator<Integer>> MAPPER =
+                         batch -> batch.iterator();
+
+    @Test
+    public void testBatchMapper() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA1.iterator(), MAPPER);
+        Assert.assertEquals(ImmutableList.of(1), ImmutableList.copyOf(results));
+
+        results = new BatchMapperIterator<>(1, DATA2.iterator(), MAPPER);
+        Assert.assertEquals(ImmutableList.of(2, 3),
+                            ImmutableList.copyOf(results));
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), MAPPER);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6),
+                            ImmutableList.copyOf(results));
+    }
+
+    @Test
+    public void testBatch() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(2, DATA2.iterator(), MAPPER);
+        Assert.assertEquals(ImmutableList.of(2, 3),
+                            ImmutableList.copyOf(results));
+
+        results = new BatchMapperIterator<>(2, DATA3.iterator(), MAPPER);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6),
+                            ImmutableList.copyOf(results));
+
+        results = new BatchMapperIterator<>(3, DATA3.iterator(), MAPPER);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6),
+                            ImmutableList.copyOf(results));
+
+        results = new BatchMapperIterator<>(4, DATA3.iterator(), MAPPER);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6),
+                            ImmutableList.copyOf(results));
+    }
+
+    @Test
+    public void testInvalidBatch() {
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            new BatchMapperIterator<>(0, DATA1.iterator(), MAPPER);
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            new BatchMapperIterator<>(-1, DATA1.iterator(), MAPPER);
+        });
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, EMPTY, MAPPER);
+        Assert.assertFalse(results.hasNext());
+
+        results = new BatchMapperIterator<>(1, DATA1.iterator(), MAPPER);
+        Assert.assertTrue(results.hasNext());
+    }
+
+    @Test
+    public void testHasNextAndNextWithMultiTimes() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), MAPPER);
+
+        for (int i = 0; i < 5; i++) {
+            Assert.assertTrue(results.hasNext());
+        }
+
+        for (int i = 0; i < 3; i++) {
+            results.next();
+        }
+
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA1.iterator(), MAPPER);
+        // Call next() without hasNext()
+        Assert.assertEquals(1, results.next());
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), MAPPER);
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+
+        results = new BatchMapperIterator<>(2, DATA3.iterator(), MAPPER);
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA2.iterator(), MAPPER);
+
+        for (int i = 0; i < 2; i++) {
+            results.next();
+        }
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testMapperWithBatch() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            Assert.assertEquals(1, batch.size());
+            return batch.iterator();
+        });
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+
+        results = new BatchMapperIterator<>(2, DATA3.iterator(), batch -> {
+            if (batch.size() == 1) {
+                Assert.assertEquals(6, batch.get(0));
+            } else {
+                Assert.assertEquals(2, batch.size());
+            }
+            return batch.iterator();
+        });
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+
+        results = new BatchMapperIterator<>(3, DATA3.iterator(), batch -> {
+            Assert.assertEquals(3, batch.size());
+            return batch.iterator();
+        });
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+
+        results = new BatchMapperIterator<>(4, DATA3.iterator(), batch -> {
+            Assert.assertEquals(3, batch.size());
+            return batch.iterator();
+        });
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testMapperThenReturn2X() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            List<Integer> list = new ArrayList<>();
+            for (int i : batch) {
+                list.add(2 * i);
+            }
+            return list.iterator();
+        });
+
+        Assert.assertEquals(8, results.next());
+        Assert.assertEquals(10, results.next());
+        Assert.assertEquals(12, results.next());
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testMapperReturnNullThenHasNext() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            return null;
+        });
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+
+        AtomicInteger count1 = new AtomicInteger(0);
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            if (count1.incrementAndGet() == 1) {
+                return null;
+            }
+            return batch.iterator();
+        });
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+
+        AtomicInteger count2 = new AtomicInteger(0);
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            if (count2.incrementAndGet() == 2) {
+                return null;
+            }
+            return batch.iterator();
+        });
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+
+        AtomicInteger count3 = new AtomicInteger(0);
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            if (count3.incrementAndGet() == 3) {
+                return null;
+            }
+            return batch.iterator();
+        });
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testMapperReturnNullThenNext() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            return null;
+        });
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testMapperReturnEmptyThenHasNext() {
+        Iterator<Integer> results;
+
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            return Collections.emptyIterator();
+        });
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+
+        AtomicInteger count1 = new AtomicInteger(0);
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            if (count1.incrementAndGet() == 1) {
+                return Collections.emptyIterator();
+            }
+            return batch.iterator();
+        });
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(5, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+
+        AtomicInteger count2 = new AtomicInteger(0);
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            if (count2.incrementAndGet() == 2) {
+                return Collections.emptyIterator();
+            }
+            return batch.iterator();
+        });
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(6, results.next());
+        Assert.assertFalse(results.hasNext());
+
+        AtomicInteger count3 = new AtomicInteger(0);
+        results = new BatchMapperIterator<>(1, DATA3.iterator(), batch -> {
+            if (count3.incrementAndGet() == 3) {
+                return Collections.emptyIterator();
+            }
+            return batch.iterator();
+        });
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(4, results.next());
+        Assert.assertEquals(5, results.next());
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<Integer> vals = new CloseableItor<>(DATA1.iterator());
+
+        Iterator<Integer> results = new BatchMapperIterator<>(1, vals, MAPPER);
+
+        Assert.assertFalse(vals.closed());
+        ((BatchMapperIterator<?, ?>) results).close();
+        Assert.assertTrue(vals.closed());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/ExtendableIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/ExtendableIteratorTest.java
new file mode 100644
index 0000000000..5e08f2d9c8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/ExtendableIteratorTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.ExtendableIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import com.google.common.collect.ImmutableList;
+
+@SuppressWarnings("resource")
+public class ExtendableIteratorTest extends BaseUnitTest {
+
+    private static final List<Integer> DATA1 = ImmutableList.of(1);
+    private static final List<Integer> DATA2 = ImmutableList.of(2, 3);
+    private static final List<Integer> DATA3 = ImmutableList.of(4, 5, 6);
+
+    @Test
+    public void testConcatTwoIterators() {
+        Iterator<Integer> results = new ExtendableIterator<>(DATA1.iterator(),
+                                                             DATA2.iterator());
+
+        List<Integer> actual = new ArrayList<>();
+        while (results.hasNext()) {
+            actual.add(results.next());
+        }
+
+        Assert.assertEquals(3, actual.size());
+        Assert.assertEquals(ImmutableList.of(1, 2, 3), actual);
+    }
+
+    @Test
+    public void testExtendIterators() {
+        ExtendableIterator<Integer> results = new ExtendableIterator<>();
+        results.extend(DATA1.iterator())
+               .extend(DATA2.iterator())
+               .extend(DATA3.iterator());
+
+        List<Integer> actual = new ArrayList<>();
+        while (results.hasNext()) {
+            actual.add(results.next());
+        }
+
+        Assert.assertEquals(6, actual.size());
+        Assert.assertEquals(ImmutableList.of(1, 2, 3, 4, 5, 6), actual);
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<Integer> results = new ExtendableIterator<>(DATA1.iterator());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertTrue(results.hasNext());
+    }
+
+    @Test
+    public void testExtendAfterHasNext() {
+        ExtendableIterator<Integer> results = new ExtendableIterator<>(
+                                              DATA1.iterator());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            results.extend(DATA2.iterator());
+        });
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<Integer> results = new ExtendableIterator<>(DATA1.iterator());
+        Assert.assertEquals(1, (int) results.next());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<Integer> results = new ExtendableIterator<>(DATA1.iterator(),
+                                                             DATA2.iterator());
+        Assert.assertEquals(1, (int) results.next());
+        Assert.assertEquals(2, (int) results.next());
+        Assert.assertEquals(3, (int) results.next());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testHasNextAndNext() {
+        Iterator<Integer> results = new ExtendableIterator<>(DATA1.iterator());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(1, (int) results.next());
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testRemove() {
+        List<Integer> list1 = new ArrayList<>(DATA1);
+        List<Integer> list3 = new ArrayList<>(DATA3);
+        Iterator<Integer> results = new ExtendableIterator<>(
+                                    list1.iterator(), list3.iterator());
+
+        Assert.assertEquals(ImmutableList.of(1), list1);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), list3);
+
+        results.next();
+        results.remove();
+
+        results.next();
+        results.next();
+        results.remove();
+
+        Assert.assertEquals(0, list1.size());
+        Assert.assertEquals(ImmutableList.of(4, 6), list3);
+    }
+
+    @Test
+    public void testRemoveWithoutResult() {
+        Iterator<Integer> results = new ExtendableIterator<>();
+        Assert.assertThrows(NoSuchElementException.class, results::remove);
+
+        List<Integer> list = new ArrayList<>();
+        Iterator<Integer> results2 = new ExtendableIterator<>(list.iterator());
+        Assert.assertThrows(NoSuchElementException.class, results2::remove);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<Integer> c1 = new CloseableItor<>(DATA1.iterator());
+        CloseableItor<Integer> c2 = new CloseableItor<>(DATA2.iterator());
+        CloseableItor<Integer> c3 = new CloseableItor<>(DATA3.iterator());
+
+        ExtendableIterator<Integer> results = new ExtendableIterator<>();
+        results.extend(c1).extend(c2).extend(c3);
+
+        Assert.assertFalse(c1.closed());
+        Assert.assertFalse(c2.closed());
+        Assert.assertFalse(c3.closed());
+
+        results.close();
+
+        Assert.assertTrue(c1.closed());
+        Assert.assertTrue(c2.closed());
+        Assert.assertTrue(c3.closed());
+    }
+
+    @Test
+    public void testCloseAfterNext1() throws Exception {
+        CloseableItor<Integer> c1 = new CloseableItor<>(DATA1.iterator());
+        CloseableItor<Integer> c2 = new CloseableItor<>(DATA2.iterator());
+        CloseableItor<Integer> c3 = new CloseableItor<>(DATA3.iterator());
+
+        ExtendableIterator<Integer> results = new ExtendableIterator<>();
+        results.extend(c1).extend(c2).extend(c3);
+
+        results.next();
+        results.hasNext();
+
+        Assert.assertTrue(c1.closed()); // close after iterated
+        Assert.assertFalse(c2.closed());
+        Assert.assertFalse(c3.closed());
+
+        results.close();
+
+        Assert.assertTrue(c1.closed());
+        Assert.assertTrue(c2.closed());
+        Assert.assertTrue(c3.closed());
+    }
+
+    @Test
+    public void testCloseAfterNext3() throws Exception {
+        CloseableItor<Integer> c1 = new CloseableItor<>(DATA1.iterator());
+        CloseableItor<Integer> c2 = new CloseableItor<>(DATA2.iterator());
+        CloseableItor<Integer> c3 = new CloseableItor<>(DATA3.iterator());
+
+        ExtendableIterator<Integer> results = new ExtendableIterator<>();
+        results.extend(c1).extend(c2).extend(c3);
+
+        Assert.assertFalse(c1.closed());
+        Assert.assertFalse(c2.closed());
+        Assert.assertFalse(c3.closed());
+
+        while (results.hasNext()) {
+            results.next();
+        }
+
+        Assert.assertTrue(c1.closed());
+        Assert.assertTrue(c2.closed());
+        Assert.assertFalse(c3.closed());
+
+        results.close();
+
+        Assert.assertTrue(c1.closed());
+        Assert.assertTrue(c2.closed());
+        Assert.assertTrue(c3.closed());
+    }
+
+    protected static class CloseableItor<V> implements Iterator<V>,
+                                                       AutoCloseable {
+
+        private final Iterator<V> iter;
+        private boolean closed = false;
+
+        public CloseableItor(Iterator<V> iter) {
+            this.iter = iter;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return this.iter.hasNext();
+        }
+
+        @Override
+        public V next() {
+            return this.iter.next();
+        }
+
+        @Override
+        public void close() throws Exception {
+            this.closed  = true;
+        }
+
+        public boolean closed() {
+            return this.closed;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FilterIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FilterIteratorTest.java
new file mode 100644
index 0000000000..6761ef60be
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FilterIteratorTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.FilterIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor;
+import com.google.common.collect.ImmutableList;
+
+@SuppressWarnings("resource")
+public class FilterIteratorTest extends BaseUnitTest {
+
+    private static final List<Integer> DATA = ImmutableList.of(1, 2, 3, 4);
+
+    @Test
+    public void testFilter() {
+        AtomicInteger callbackCount = new AtomicInteger(0);
+
+        Iterator<Integer> values = DATA.iterator();
+
+        Function<Integer, Boolean> filter = value -> {
+            callbackCount.incrementAndGet();
+            return (value % 2 == 0);
+        };
+
+        Iterator<Integer> results = new FilterIterator<>(values, filter);
+
+        List<Integer> actual = new ArrayList<>();
+        while (results.hasNext()) {
+            actual.add(results.next());
+        }
+
+        Assert.assertEquals(4, callbackCount.get());
+        Assert.assertEquals(ImmutableList.of(2, 4), actual);
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new FilterIterator<>(vals, val -> true);
+        Assert.assertTrue(results.hasNext());
+    }
+
+    @Test
+    public void testHasNextWithMultiTimesWithoutAnyResult() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new FilterIterator<>(vals, val -> false);
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testHasNextAndNextWithMultiTimes() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new FilterIterator<>(vals, val -> true);
+
+        for (int i = 0; i < 5; i++) {
+            Assert.assertTrue(results.hasNext());
+        }
+
+        for (int i = 0; i < 4; i++) {
+            results.next();
+        }
+
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new FilterIterator<>(vals, val -> true);
+        // Call next() without testNext()
+        results.next();
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new FilterIterator<>(vals, val -> true);
+        for (int i = 0; i < 4; i++) {
+            results.next();
+        }
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNextWithMultiTimesWithoutAnyResult() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new FilterIterator<>(vals, val -> false);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNextWithOriginIteratorReturnNullElem() {
+        List<Integer> list = new ArrayList<>();
+        list.add(1);
+        list.add(null);
+        list.add(3);
+        Iterator<Integer> vals = list.iterator();
+
+        AtomicInteger callbackCount = new AtomicInteger(0);
+
+        Iterator<Integer> results = new FilterIterator<>(vals, val -> {
+            callbackCount.incrementAndGet();
+            return true;
+        });
+
+        Assert.assertTrue(results.hasNext());
+        for (int i = 0; i < 2; i++) {
+            results.next();
+        }
+        Assert.assertFalse(results.hasNext());
+        Assert.assertEquals(2, callbackCount.get());
+    }
+
+    @Test
+    public void testRemove() {
+        List<Integer> list = new ArrayList<>(DATA);
+
+        Iterator<Integer> results = new FilterIterator<>(list.iterator(),
+                                                         val -> true);
+
+        Assert.assertEquals(ImmutableList.of(1, 2, 3, 4), list);
+
+        results.next();
+        results.next();
+        results.remove();
+
+        Assert.assertEquals(ImmutableList.of(1, 3, 4), list);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<Integer> vals = new CloseableItor<>(DATA.iterator());
+
+        FilterIterator<Integer> results = new FilterIterator<>(vals,
+                                                               val -> true);
+
+        Assert.assertFalse(vals.closed());
+        results.close();
+        Assert.assertTrue(vals.closed());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FlatMapperFilterIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FlatMapperFilterIteratorTest.java
new file mode 100644
index 0000000000..6a3b658332
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FlatMapperFilterIteratorTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.FlatMapperFilterIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@SuppressWarnings("resource")
+public class FlatMapperFilterIteratorTest extends BaseUnitTest {
+
+    private static final Map<String, List<Integer>> DATA = ImmutableMap.of(
+            "first", ImmutableList.of(11),
+            "second", ImmutableList.of(21, 22),
+            "third", ImmutableList.of(31, 32, 33),
+            "forth", ImmutableList.of(41, 42, 43, 44)
+    );
+
+    @Test
+    public void testMapperFilter() {
+
+        AtomicInteger keysCount = new AtomicInteger(0);
+        AtomicInteger valuesCount = new AtomicInteger(0);
+
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Function<String, Iterator<Integer>> mapper = key -> {
+            keysCount.incrementAndGet();
+
+            return DATA.get(key).iterator();
+        };
+
+        Function<Integer, Boolean> filter = value -> {
+            valuesCount.incrementAndGet();
+
+            double f = value / 11F;
+            return (f == (int) f);
+        };
+
+        Iterator<Integer> results = new FlatMapperFilterIterator<>(keys,
+                                                                   mapper,
+                                                                   filter);
+
+        List<Integer> actual = new ArrayList<>();
+        while (results.hasNext()) {
+            actual.add(results.next());
+        }
+
+        Assert.assertEquals(4, keysCount.get());
+        Assert.assertEquals(10, valuesCount.get());
+        Assert.assertEquals(ImmutableList.of(11, 22, 33, 44), actual);
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperFilterIterator<>(keys,
+                                        key -> DATA.get(key).iterator(),
+                                        val -> true);
+        Assert.assertTrue(results.hasNext());
+
+        Iterator<Integer> results2 = new FlatMapperFilterIterator<>(keys,
+                                         key -> DATA.get(key).iterator(),
+                                         val -> false);
+        Assert.assertFalse(results2.hasNext());
+        Assert.assertThrows(NoSuchElementException.class, results2::next);
+    }
+
+    @Test
+    public void testHasNextWithMultiTimes() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperFilterIterator<>(keys,
+                                        key -> DATA.get(key).iterator(),
+                                        val -> true);
+        for (int i = 0; i < 12; i++) {
+            Assert.assertTrue(results.hasNext());
+        }
+        for (int i = 0; i < 10; i++) {
+            results.next();
+        }
+        Assert.assertFalse(results.hasNext());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+
+        Iterator<Integer> results2 = new FlatMapperFilterIterator<>(keys,
+                                         key -> DATA.get(key).iterator(),
+                                         val -> false);
+        Assert.assertFalse(results2.hasNext());
+        Assert.assertFalse(results2.hasNext());
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperFilterIterator<>(keys,
+                                        key -> DATA.get(key).iterator(),
+                                        val -> true);
+        // Call next() without hasNext()
+        results.next();
+
+        Iterator<Integer> results2 = new FlatMapperFilterIterator<>(keys,
+                                         key -> DATA.get(key).iterator(),
+                                         val -> false);
+        Assert.assertThrows(NoSuchElementException.class, results2::next);
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperFilterIterator<>(keys,
+                                        key -> DATA.get(key).iterator(),
+                                        val -> true);
+        for (int i = 0; i < 10; i++) {
+            results.next();
+        }
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+
+        Iterator<Integer> results2 = new FlatMapperFilterIterator<>(keys,
+                                         key -> DATA.get(key).iterator(),
+                                         val -> false);
+        Assert.assertThrows(NoSuchElementException.class, results2::next);
+        Assert.assertThrows(NoSuchElementException.class, results2::next);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<String> vals = new CloseableItor<>(
+                                     DATA.keySet().iterator());
+
+        FlatMapperFilterIterator<String, Integer> results;
+        results = new FlatMapperFilterIterator<>(vals,
+                                                 k -> DATA.get(k).iterator(),
+                                                 val -> true);
+
+        Assert.assertFalse(vals.closed());
+        results.close();
+        Assert.assertTrue(vals.closed());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FlatMapperIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FlatMapperIteratorTest.java
new file mode 100644
index 0000000000..641b6fc379
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/FlatMapperIteratorTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.FlatMapperIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@SuppressWarnings("resource")
+public class FlatMapperIteratorTest extends BaseUnitTest {
+
+    private static final Map<String, List<Integer>> DATA = ImmutableMap.of(
+            "first", ImmutableList.of(11),
+            "second", ImmutableList.of(21, 22),
+            "third", ImmutableList.of(31, 32, 33),
+            "forth", ImmutableList.of(41, 42, 43, 44)
+    );
+
+    private static final Function<String, Iterator<Integer>> MAPPER = key -> {
+        List<Integer> value = DATA.get(key);
+        if (value == null) {
+            return ImmutableList.<Integer>of().iterator();
+        }
+        return value.iterator();
+    };
+
+    @Test
+    public void testFlatMapper() {
+
+        AtomicInteger keysCount = new AtomicInteger(0);
+
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Function<String, Iterator<Integer>> mapper = key -> {
+            keysCount.incrementAndGet();
+
+            return DATA.get(key).iterator();
+        };
+
+        Iterator<Integer> results = new FlatMapperIterator<>(keys, mapper);
+
+        List<Integer> actual = new ArrayList<>();
+        while (results.hasNext()) {
+            actual.add(results.next());
+        }
+
+        List<Integer> expected = ImmutableList.of(11,
+                                                  21, 22,
+                                                  31, 32, 33,
+                                                  41, 42, 43, 44);
+        Assert.assertEquals(4, keysCount.get());
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperIterator<>(keys, MAPPER);
+        Assert.assertTrue(results.hasNext());
+    }
+
+    @Test
+    public void testHasNextAndNextWithMultiTimes() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperIterator<>(keys, MAPPER);
+
+        for (int i = 0; i < 12; i++) {
+            Assert.assertTrue(results.hasNext());
+        }
+
+        for (int i = 0; i < 10; i++) {
+            results.next();
+        }
+
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperIterator<>(keys, MAPPER);
+        // Call next() without hasNext()
+        results.next();
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new FlatMapperIterator<>(keys, MAPPER);
+        for (int i = 0; i < 10; i++) {
+            results.next();
+        }
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testMapperReturnNullThenHasNext() {
+        Iterator<String> keys = ImmutableList.of("fifth").iterator();
+
+        Iterator<Integer> results = new FlatMapperIterator<>(keys, key -> {
+            Assert.assertNull(DATA.get(key));
+            return null;
+        });
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testMapperReturnNullThenNext() {
+        Iterator<String> keys = ImmutableList.of("fifth").iterator();
+
+        Iterator<Integer> results = new FlatMapperIterator<>(keys, key -> {
+            Assert.assertNull(DATA.get(key));
+            return null;
+        });
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<String> vals = new CloseableItor<>(
+                                     DATA.keySet().iterator());
+
+        FlatMapperIterator<String, Integer> results;
+        results = new FlatMapperIterator<>(vals,
+                                           key -> DATA.get(key).iterator());
+
+        Assert.assertFalse(vals.closed());
+        results.close();
+        Assert.assertTrue(vals.closed());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/LimitIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/LimitIteratorTest.java
new file mode 100644
index 0000000000..f087e7df3e
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/LimitIteratorTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.LimitIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor;
+import com.google.common.collect.ImmutableList;
+
+@SuppressWarnings("resource")
+public class LimitIteratorTest extends BaseUnitTest {
+
+    private static final List<Integer> DATA = ImmutableList.of(1, 2, 3, 4);
+
+    @Test
+    public void testLimit() {
+        AtomicInteger callbackCount = new AtomicInteger(0);
+
+        Iterator<Integer> values = DATA.iterator();
+
+        int limit = 2;
+        Function<Integer, Boolean> filter = value -> {
+            return callbackCount.incrementAndGet() > limit;
+        };
+
+        Iterator<Integer> results = new LimitIterator<>(values, filter);
+
+        List<Integer> actual = new ArrayList<>();
+        while (results.hasNext()) {
+            actual.add(results.next());
+        }
+
+        Assert.assertEquals(3, callbackCount.get());
+        Assert.assertEquals(ImmutableList.of(1, 2), actual);
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new LimitIterator<>(vals, val -> false);
+        Assert.assertTrue(results.hasNext());
+    }
+
+    @Test
+    public void testHasNextWithMultiTimesWithoutAnyResult() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new LimitIterator<>(vals, val -> true);
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testHasNextAndNextWithMultiTimes() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new LimitIterator<>(vals, val -> false);
+
+        for (int i = 0; i < 5; i++) {
+            Assert.assertTrue(results.hasNext());
+        }
+
+        for (int i = 0; i < 4; i++) {
+            results.next();
+        }
+
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+
+        Iterator<Integer> results2 = new LimitIterator<>(vals, val -> false);
+        Assert.assertFalse(results2.hasNext());
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new LimitIterator<>(vals, val -> false);
+        // Call next() without testNext()
+        results.next();
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new LimitIterator<>(vals, val -> false);
+        for (int i = 0; i < 4; i++) {
+            results.next();
+        }
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNextWithMultiTimesWithoutAnyResult() {
+        Iterator<Integer> vals = DATA.iterator();
+
+        Iterator<Integer> results = new LimitIterator<>(vals, val -> true);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNextWithOriginIteratorReturnNullElem() {
+        List<Integer> list = new ArrayList<>();
+        list.add(1);
+        list.add(null);
+        list.add(3);
+        Iterator<Integer> vals = list.iterator();
+
+        AtomicInteger callbackCount = new AtomicInteger(0);
+
+        Iterator<Integer> results = new LimitIterator<>(vals, val -> {
+            callbackCount.incrementAndGet();
+            return false;
+        });
+        Assert.assertTrue(results.hasNext());
+        for (int i = 0; i < 2; i++) {
+            results.next();
+        }
+        Assert.assertFalse(results.hasNext());
+        Assert.assertEquals(2, callbackCount.get());
+    }
+
+    @Test
+    public void testRemove() {
+        List<Integer> list = new ArrayList<>(DATA);
+
+        Iterator<Integer> results = new LimitIterator<>(list.iterator(),
+                                                        val -> false);
+
+        Assert.assertEquals(ImmutableList.of(1, 2, 3, 4), list);
+
+        results.next();
+        results.next();
+        results.remove();
+
+        Assert.assertEquals(ImmutableList.of(1, 3, 4), list);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<Integer> vals = new CloseableItor<>(DATA.iterator());
+
+        LimitIterator<Integer> results = new LimitIterator<>(vals,
+                                                             val -> true);
+
+        Assert.assertFalse(vals.closed());
+        results.close();
+        Assert.assertTrue(vals.closed());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/ListIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/ListIteratorTest.java
new file mode 100644
index 0000000000..659ab482ed
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/ListIteratorTest.java
@@ -0,0 +1,232 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.ListIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+
+@SuppressWarnings("resource")
+public class ListIteratorTest extends BaseUnitTest {
+
+    private static final Iterator<Integer> EMPTY = Collections.emptyIterator();
+
+    private static final List<Integer> DATA1 = ImmutableList.of(1);
+    private static final List<Integer> DATA2 = ImmutableList.of(2, 3);
+    private static final List<Integer> DATA3 = ImmutableList.of(4, 5, 6);
+
+    @Test
+    public void testCapacity() {
+        Iterator<Integer> results;
+
+        results = new ListIterator<>(0, EMPTY);
+        Assert.assertFalse(results.hasNext());
+        Assert.assertEquals(0, Iterators.size(results));
+
+        results = new ListIterator<>(2, DATA1.iterator());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(1, Iterators.size(results));
+
+        results = new ListIterator<>(2, DATA2.iterator());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(2, Iterators.size(results));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            new ListIterator<>(0, DATA1.iterator());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            new ListIterator<>(2, DATA3.iterator());
+        });
+    }
+
+    @Test
+    public void testList() {
+        ListIterator<Integer> results;
+
+        results = new ListIterator<>(-1, EMPTY);
+        Assert.assertEquals(ImmutableList.of(), results.list());
+
+        results = new ListIterator<>(-1, DATA1.iterator());
+        Assert.assertEquals(ImmutableList.of(1), results.list());
+
+        results = new ListIterator<>(-1, DATA2.iterator());
+        Assert.assertEquals(ImmutableList.of(2, 3), results.list());
+
+        results = new ListIterator<>(-1, DATA3.iterator());
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list());
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<Integer> origin = DATA1.iterator();
+        Assert.assertTrue(origin.hasNext());
+
+        Iterator<Integer> results = new ListIterator<>(-1, origin);
+        Assert.assertTrue(results.hasNext());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertFalse(origin.hasNext());
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<Integer> results = new ListIterator<>(-1, DATA1.iterator());
+        Assert.assertEquals(1, (int) results.next());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNextAfterList() {
+        Iterator<Integer> results = new ListIterator<>(-1, DATA1.iterator());
+        Assert.assertEquals(ImmutableList.of(1),
+                            ((ListIterator<?>) results).list());
+        Assert.assertEquals(1, (int) results.next());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<Integer> results = new ListIterator<>(-1, DATA2.iterator());
+        Assert.assertEquals(2, (int) results.next());
+        Assert.assertEquals(3, (int) results.next());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testHasNextAndNext() {
+        Iterator<Integer> results = new ListIterator<>(-1, DATA1.iterator());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertTrue(results.hasNext());
+        Assert.assertEquals(1, (int) results.next());
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testRemove() {
+        List<Integer> list = new ArrayList<>(DATA3);
+        ListIterator<Integer> results = new ListIterator<>(-1, list.iterator());
+
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), list);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list());
+
+        Assert.assertThrows(UnsupportedOperationException.class, results::remove);
+        results.next();
+        Assert.assertThrows(UnsupportedOperationException.class, results::remove);
+
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), list);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list());
+    }
+
+    @Test
+    public void testRemoveWithoutResult() {
+        Iterator<Integer> results = new ListIterator<>(-1, EMPTY);
+        Assert.assertThrows(UnsupportedOperationException.class, results::remove);
+
+        List<Integer> list0 = new ArrayList<>();
+        Iterator<Integer> results2 = new ListIterator<>(-1, list0.iterator());
+        Assert.assertThrows(UnsupportedOperationException.class, results2::remove);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<Integer> c1 = new CloseableItor<>(DATA1.iterator());
+
+        ListIterator<Integer> results = new ListIterator<>(-1, c1);
+
+        Assert.assertFalse(c1.closed());
+
+        results.close();
+
+        Assert.assertTrue(c1.closed());
+    }
+
+    @Test
+    public void testListWithConstructFromList() {
+        ListIterator<Integer> results;
+
+        results = new ListIterator<>(ImmutableList.of());
+        Assert.assertEquals(ImmutableList.of(), results.list());
+
+        results = new ListIterator<>(DATA1);
+        Assert.assertEquals(ImmutableList.of(1), results.list());
+
+        results = new ListIterator<>(DATA2);
+        Assert.assertEquals(ImmutableList.of(2, 3), results.list());
+
+        results = new ListIterator<>(DATA3);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), results.list());
+    }
+
+    @Test
+    public void testHasNextAndNextWithConstructFromList() {
+        ListIterator<Integer> results0 = new ListIterator<>(ImmutableList.of());
+        Assert.assertFalse(results0.hasNext());
+        Assert.assertThrows(NoSuchElementException.class, results0::next);
+
+        ListIterator<Integer> results1 = new ListIterator<>(DATA1);
+        Assert.assertTrue(results1.hasNext());
+        Assert.assertEquals(1, results1.next());
+        Assert.assertFalse(results1.hasNext());
+        Assert.assertThrows(NoSuchElementException.class, results1::next);
+
+        ListIterator<Integer> results3 = new ListIterator<>(DATA3);
+        Assert.assertTrue(results3.hasNext());
+        Assert.assertEquals(4, results3.next());
+        Assert.assertTrue(results3.hasNext());
+        Assert.assertEquals(5, results3.next());
+        Assert.assertTrue(results3.hasNext());
+        Assert.assertEquals(6, results3.next());
+        Assert.assertFalse(results3.hasNext());
+        Assert.assertThrows(NoSuchElementException.class, results3::next);
+    }
+
+    @Test
+    public void testNextWithConstructFromList() {
+        ListIterator<Integer> results0 = new ListIterator<>(ImmutableList.of());
+        Assert.assertThrows(NoSuchElementException.class, results0::next);
+
+        ListIterator<Integer> results3 = new ListIterator<>(DATA3);
+        Assert.assertEquals(4, results3.next());
+        Assert.assertEquals(5, results3.next());
+        Assert.assertEquals(6, results3.next());
+        Assert.assertThrows(NoSuchElementException.class, results3::next);
+    }
+
+    @Test
+    public void testNextAfterListWithConstructFromList() {
+        ListIterator<Integer> results3 = new ListIterator<>(DATA3);
+        Assert.assertEquals(ImmutableList.of(4, 5, 6), results3.list());
+        Assert.assertEquals(4, results3.next());
+        Assert.assertEquals(5, results3.next());
+        Assert.assertEquals(6, results3.next());
+        Assert.assertThrows(NoSuchElementException.class, results3::next);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/MapperIteratorTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/MapperIteratorTest.java
new file mode 100644
index 0000000000..4f36e857ce
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/iterator/MapperIteratorTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.hugegraph.unit.iterator;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.iterator.MapperIterator;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.iterator.ExtendableIteratorTest.CloseableItor;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@SuppressWarnings("resource")
+public class MapperIteratorTest extends BaseUnitTest {
+
+    private static final Map<String, Integer> DATA = ImmutableMap.of(
+            "first", 1,
+            "second", 2,
+            "third", 3,
+            "forth", 4
+    );
+
+    private static final Function<String, Integer> MAPPER = DATA::get;
+
+    @Test
+    public void testMapper() {
+
+        AtomicInteger keysCount = new AtomicInteger(0);
+
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Function<String, Integer> mapper = key -> {
+            keysCount.incrementAndGet();
+
+            return DATA.get(key);
+        };
+
+        Iterator<Integer> results = new MapperIterator<>(keys, mapper);
+
+        List<Integer> actual = new ArrayList<>();
+        while (results.hasNext()) {
+            actual.add(results.next());
+        }
+
+        List<Integer> expected = ImmutableList.of(1, 2, 3, 4);
+        Assert.assertEquals(4, keysCount.get());
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testHasNext() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new MapperIterator<>(keys, MAPPER);
+        Assert.assertTrue(results.hasNext());
+    }
+
+    @Test
+    public void testHasNextAndNextWithMultiTimes() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new MapperIterator<>(keys, MAPPER);
+
+        for (int i = 0; i < 5; i++) {
+            Assert.assertTrue(results.hasNext());
+        }
+
+        for (int i = 0; i < 4; i++) {
+            results.next();
+        }
+
+        Assert.assertFalse(results.hasNext());
+        Assert.assertFalse(results.hasNext());
+
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testNext() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new MapperIterator<>(keys, MAPPER);
+        // Call next() without hasNext()
+        results.next();
+    }
+
+    @Test
+    public void testNextWithMultiTimes() {
+        Iterator<String> keys = DATA.keySet().iterator();
+
+        Iterator<Integer> results = new MapperIterator<>(keys, MAPPER);
+        for (int i = 0; i < 4; i++) {
+            results.next();
+        }
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testMapperReturnNullThenHasNext() {
+        Iterator<String> keys = ImmutableList.of("fifth").iterator();
+
+        Iterator<Integer> results = new MapperIterator<>(keys, key -> {
+            return null;
+        });
+        Assert.assertFalse(results.hasNext());
+    }
+
+    @Test
+    public void testMapperReturnNullThenNext() {
+        Iterator<String> keys = ImmutableList.of("fifth").iterator();
+
+        Iterator<Integer> results = new MapperIterator<>(keys, key -> {
+            return null;
+        });
+        Assert.assertThrows(NoSuchElementException.class, results::next);
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        CloseableItor<String> keys = new CloseableItor<>(
+                                     ImmutableList.of("fifth").iterator());
+
+        MapperIterator<String, Integer> results = new MapperIterator<>(keys, k -> null);
+
+        Assert.assertFalse(keys.closed());
+        results.close();
+        Assert.assertTrue(keys.closed());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseCreateParamTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseCreateParamTest.java
new file mode 100644
index 0000000000..67e6a54808
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseCreateParamTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.hugegraph.unit.license;
+
+import java.io.IOException;
+
+import org.apache.hugegraph.date.SafeDateFormat;
+import org.apache.hugegraph.license.LicenseCreateParam;
+import org.apache.hugegraph.testutil.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class LicenseCreateParamTest {
+
+    @Test
+    public void testDeserializeLicenseCreateParam() throws IOException {
+        String json = "{"
+                + "\"subject\":\"hugegraph-evaluation\","
+                + "\"private_alias\":\"privatekey\","
+                + "\"key_ticket\":\"a123456\","
+                + "\"store_ticket\":\"a123456\","
+                + "\"privatekey_path\":\"./privateKeys.store\","
+                + "\"license_path\":\"./hugegraph-evaluation.license\","
+                + "\"issued_time\":\"2019-08-10 00:00:00\","
+                + "\"not_before\":\"2019-08-10 00:00:00\","
+                + "\"not_after\":\"2020-08-10 00:00:00\","
+                + "\"consumer_type\":\"user\","
+                + "\"consumer_amount\":1,"
+                + "\"description\":\"hugegraph license\","
+                + "\"extra_params\":["
+                + "{"
+                + "\"id\":\"server-1\","
+                + "\"version\":\"0.9.2\","
+                + "\"graphs\":3,"
+                + "\"ip\":\"127.0.0.1\","
+                + "\"mac\":\"00-01-6C-06-A6-29\","
+                + "\"cpus\":32,"
+                + "\"ram\":65536,"
+                + "\"threads\":96,"
+                + "\"memory\":32768,"
+                + "\"nodes\":3,"
+                + "\"data_size\":1024,"
+                + "\"vertices\":1000,"
+                + "\"edges\":2000"
+                + "},"
+                + "{"
+                + "\"id\":\"server-2\","
+                + "\"version\":\"0.10.2\","
+                + "\"graphs\":3,"
+                + "\"ip\":\"127.0.0.1\","
+                + "\"mac\":\"00-02-6C-06-A6-29\","
+                + "\"cpus\":64,"
+                + "\"ram\":65536,"
+                + "\"threads\":96,"
+                + "\"memory\":65536,"
+                + "\"nodes\":30,"
+                + "\"data_size\":10240,"
+                + "\"vertices\":10000,"
+                + "\"edges\":20000"
+                + "}"
+                + "]"
+                + "}";
+        ObjectMapper mapper = new ObjectMapper();
+        LicenseCreateParam param = mapper.readValue(json,
+                                                    LicenseCreateParam.class);
+        Assert.assertEquals("hugegraph-evaluation", param.subject());
+        Assert.assertEquals("privatekey", param.privateAlias());
+        Assert.assertEquals("a123456", param.keyPassword());
+        Assert.assertEquals("a123456", param.storePassword());
+        Assert.assertEquals("./privateKeys.store", param.privateKeyPath());
+        Assert.assertEquals("./hugegraph-evaluation.license",
+                            param.licensePath());
+
+        SafeDateFormat df = new SafeDateFormat("yyyy-MM-dd HH:mm:ss");
+        df.setTimeZone("GMT+8");
+        Assert.assertEquals(df.parse("2019-08-10 00:00:00"),
+                            param.issuedTime());
+        Assert.assertEquals(df.parse("2019-08-10 00:00:00"),
+                            param.notBefore());
+        Assert.assertEquals(df.parse("2020-08-10 00:00:00"),
+                            param.notAfter());
+        Assert.assertEquals("user", param.consumerType());
+        Assert.assertEquals(1, param.consumerAmount());
+        Assert.assertEquals("hugegraph license", param.description());
+        Assert.assertEquals(2, param.extraParams().size());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseExtraParamTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseExtraParamTest.java
new file mode 100644
index 0000000000..b24470d2a4
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseExtraParamTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.hugegraph.unit.license;
+
+import java.io.IOException;
+
+import org.apache.hugegraph.license.LicenseExtraParam;
+import org.junit.Test;
+
+import org.apache.hugegraph.testutil.Assert;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class LicenseExtraParamTest {
+
+    @Test
+    public void testDeserializeExtraParam() throws IOException {
+        String json = "{"
+                + "\"id\":\"server-1\","
+                + "\"version\":\"0.10.2\","
+                + "\"graphs\":3,"
+                + "\"ip\":\"127.0.0.1\","
+                + "\"mac\":\"00-01-6C-06-A6-29\","
+                + "\"cpus\":32,"
+                + "\"ram\":65536,"
+                + "\"threads\":96,"
+                + "\"memory\":32768,"
+                + "\"nodes\":3,"
+                + "\"data_size\":1024,"
+                + "\"vertices\":1000,"
+                + "\"edges\":2000"
+                + "}";
+        ObjectMapper mapper = new ObjectMapper();
+        LicenseExtraParam param = mapper.readValue(json, LicenseExtraParam.class);
+        Assert.assertEquals("server-1", param.id());
+        Assert.assertEquals("0.10.2", param.version());
+        Assert.assertEquals(3, param.graphs());
+        Assert.assertEquals("127.0.0.1", param.ip());
+        Assert.assertEquals("00-01-6C-06-A6-29", param.mac());
+        Assert.assertEquals(32, param.cpus());
+        Assert.assertEquals(65536, param.ram());
+        Assert.assertEquals(96, param.threads());
+        Assert.assertEquals(32768, param.memory());
+        Assert.assertEquals(3, param.nodes());
+        Assert.assertEquals(1024, param.dataSize());
+        Assert.assertEquals(1000, param.vertices());
+        Assert.assertEquals(2000, param.edges());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseInstallParamTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseInstallParamTest.java
new file mode 100644
index 0000000000..ed38d93f6f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseInstallParamTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.hugegraph.unit.license;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.license.LicenseInstallParam;
+import org.apache.hugegraph.testutil.Assert;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class LicenseInstallParamTest {
+
+    @Test
+    public void testDeserializeLicenseVerifyParam() throws IOException {
+        String json = "{"
+                + "\"subject\":\"hugegraph-evaluation\","
+                + "\"public_alias\":\"publiccert\","
+                + "\"store_ticket\":\"a123456\","
+                + "\"publickey_path\":\"./publicCerts.store\","
+                + "\"license_path\":\"./hugegraph-evaluation.license\""
+                + "}";
+        ObjectMapper mapper = new ObjectMapper();
+        LicenseInstallParam param = mapper.readValue(json,
+                                                     LicenseInstallParam.class);
+        Assert.assertEquals("hugegraph-evaluation", param.subject());
+        Assert.assertEquals("publiccert", param.publicAlias());
+        Assert.assertEquals("a123456", param.storePassword());
+        Assert.assertEquals("./publicCerts.store", param.publicKeyPath());
+        Assert.assertEquals("./hugegraph-evaluation.license",
+                            param.licensePath());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseParamsTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseParamsTest.java
new file mode 100644
index 0000000000..9a2968d6f8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/LicenseParamsTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.hugegraph.unit.license;
+
+import java.io.IOException;
+
+import org.apache.hugegraph.license.LicenseExtraParam;
+import org.apache.hugegraph.license.LicenseParams;
+import org.junit.Test;
+
+import org.apache.hugegraph.testutil.Assert;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class LicenseParamsTest {
+
+    @Test
+    public void testLicenseParams() throws IOException {
+        String json = "{"
+                + "\"subject\":\"hugegraph-evaluation\","
+                + "\"issued_time\":\"2019-08-10 00:00:00\","
+                + "\"not_before\":\"2019-08-10 00:00:00\","
+                + "\"not_after\":\"2020-08-10 00:00:00\","
+                + "\"consumer_type\":\"user\","
+                + "\"consumer_amount\":1,"
+                + "\"description\":\"hugegraph license\","
+                + "\"extra_params\":["
+                + "{"
+                + "\"id\":\"server-1\","
+                + "\"version\":\"0.9.2\","
+                + "\"graphs\":3,"
+                + "\"ip\":\"127.0.0.1\","
+                + "\"mac\":\"00-01-6C-06-A6-29\","
+                + "\"cpus\":32,"
+                + "\"ram\":65536,"
+                + "\"threads\":96,"
+                + "\"memory\":32768,"
+                + "\"nodes\":3,"
+                + "\"data_size\":1024,"
+                + "\"vertices\":1000,"
+                + "\"edges\":2000"
+                + "},"
+                + "{"
+                + "\"id\":\"server-2\","
+                + "\"version\":\"0.10.2\","
+                + "\"graphs\":3,"
+                + "\"ip\":\"127.0.0.1\","
+                + "\"mac\":\"00-02-6C-06-A6-29\","
+                + "\"cpus\":64,"
+                + "\"ram\":65536,"
+                + "\"threads\":96,"
+                + "\"memory\":65536,"
+                + "\"nodes\":30,"
+                + "\"data_size\":10240,"
+                + "\"vertices\":10000,"
+                + "\"edges\":20000"
+                + "}"
+                + "]"
+                + "}";
+        ObjectMapper mapper = new ObjectMapper();
+        LicenseParams param = mapper.readValue(json, LicenseParams.class);
+
+        LicenseExtraParam extraParam = param.matchParam("server-not-exist");
+        Assert.assertNull(extraParam);
+
+        extraParam = param.matchParam("server-1");
+        Assert.assertEquals("00-01-6C-06-A6-29", extraParam.mac());
+
+        extraParam = param.matchParam("server-2");
+        Assert.assertEquals("00-02-6C-06-A6-29", extraParam.mac());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/MachineInfoTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/MachineInfoTest.java
new file mode 100644
index 0000000000..9dc69cbdb9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/license/MachineInfoTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.hugegraph.unit.license;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.license.MachineInfo;
+import org.apache.hugegraph.testutil.Assert;
+
+public class MachineInfoTest {
+
+    private static final Pattern IPV4_PATTERN = Pattern.compile(
+            "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}" +
+            "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"
+    );
+    private static final Pattern IPV6_PATTERN = Pattern.compile(
+            "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"
+    );
+
+    private static final Pattern MAC_PATTERN = Pattern.compile(
+            "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$"
+    );
+
+    private static final MachineInfo machineInfo = new MachineInfo();
+
+    @Test
+    public void testGetIpAddressList() {
+        List<String> ipAddressList = machineInfo.getIpAddress();
+        for (String ip : ipAddressList) {
+            Assert.assertTrue(IPV4_PATTERN.matcher(ip).matches() ||
+                              IPV6_PATTERN.matcher(ip).matches());
+        }
+        Assert.assertEquals(ipAddressList, machineInfo.getIpAddress());
+    }
+
+    @Test
+    public void testGetMacAddressList() {
+        List<String> macAddressList = machineInfo.getMacAddress();
+        for (String mac : macAddressList) {
+            Assert.assertTrue(MAC_PATTERN.matcher(mac).matches());
+        }
+        Assert.assertEquals(macAddressList, machineInfo.getMacAddress());
+    }
+
+    @Test
+    public void testGetLocalAllInetAddress() {
+        List<InetAddress> addressList = machineInfo.getLocalAllInetAddress();
+        for (InetAddress address : addressList) {
+            String ip = address.getHostAddress();
+            Assert.assertTrue(IPV4_PATTERN.matcher(ip).matches() ||
+                              IPV6_PATTERN.matcher(ip).matches());
+        }
+    }
+
+    @Test
+    public void testGetMacByInetAddress() throws UnknownHostException {
+        List<InetAddress> addressList = machineInfo.getLocalAllInetAddress();
+        for (InetAddress address : addressList) {
+            String mac = machineInfo.getMacByInetAddress(address);
+            Assert.assertTrue(MAC_PATTERN.matcher(mac).matches());
+        }
+        InetAddress address = InetAddress.getByAddress(new byte[]{0, 0, 0, 0});
+        Assert.assertThrows(RuntimeException.class, () -> {
+            machineInfo.getMacByInetAddress(address);
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/PerfUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/PerfUtilTest.java
new file mode 100644
index 0000000000..1fcb50711a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/PerfUtilTest.java
@@ -0,0 +1,468 @@
+/*
+ * 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.hugegraph.unit.perf;
+
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.perf.testclass.TestClass;
+import org.apache.hugegraph.unit.perf.testclass.TestPerfLightClass;
+import org.apache.hugegraph.unit.perf.testclass2.TestClass4Package;
+import org.apache.hugegraph.perf.PerfUtil;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.perf.testclass.TestLightClass;
+import org.apache.hugegraph.unit.perf.testclass.TestPerfClass;
+
+public class PerfUtilTest extends BaseUnitTest {
+
+    private static final String prefix =
+                                "org.apache.hugegraph.unit.perf.testclass.";
+    private static final PerfUtil perf = PerfUtil.instance();
+
+    @After
+    public void teardown() {
+        perf.clear();
+    }
+
+    @Test
+    public void testPerfUtil() throws Throwable {
+        perf.profileClass(prefix + "TestClass$Foo");
+
+        TestClass.Foo obj = new TestClass.Foo();
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "foo.foo#times", 1);
+        assertContains(json, "foo.foo#name", "foo.foo");
+        assertContains(json, "foo.foo#parent", "");
+        assertContains(json, "foo.foo#total_cost");
+        assertContains(json, "foo.foo#min_cost");
+        assertContains(json, "foo.foo#max_cost");
+        assertContains(json, "foo.foo#total_self_wasted");
+        assertContains(json, "foo.foo#total_children_wasted", -1);
+        assertContains(json, "foo.foo#total_children_times", -1);
+
+        assertContains(json, "foo.foo/foo.bar#times", 1);
+        assertContains(json, "foo.foo/foo.bar#name", "foo.bar");
+        assertContains(json, "foo.foo/foo.bar#parent", "foo.foo");
+        assertContains(json, "foo.foo/foo.bar#total_cost");
+        assertContains(json, "foo.foo/foo.bar#min_cost");
+        assertContains(json, "foo.foo/foo.bar#max_cost");
+        assertContains(json, "foo.foo/foo.bar#total_self_wasted");
+        assertContains(json, "foo.foo/foo.bar#total_children_wasted", -1);
+        assertContains(json, "foo.foo/foo.bar#total_children_times", -1);
+
+        TestClass test = new TestClass();
+        test.test();
+        json = perf.toJson();
+        assertContains(json, "foo.bar#times", 1);
+        assertContains(json, "foo.foo#times", 1);
+        assertContains(json, "foo.foo/foo.bar#times", 1);
+
+        perf.clear();
+
+        obj.foo();
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "foo.foo#times", 2);
+        assertContains(json, "foo.foo/foo.bar#times", 2);
+    }
+
+    @Test
+    public void testPerfUtil4LightStopwatch() throws Throwable {
+        perf.profileClass(prefix + "TestLightClass$Foo");
+
+        PerfUtil.useLightStopwatch(true);
+
+        TestLightClass.Foo obj = new TestLightClass.Foo();
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "foo.foo#times", 1);
+        assertContains(json, "foo.foo#name", "foo.foo");
+        assertContains(json, "foo.foo#parent", "");
+        assertContains(json, "foo.foo#total_cost");
+        assertContains(json, "foo.foo#min_cost");
+        assertContains(json, "foo.foo#max_cost");
+        assertContains(json, "foo.foo#total_self_wasted");
+        assertContains(json, "foo.foo#total_children_wasted", -1);
+        assertContains(json, "foo.foo#total_children_times", -1);
+
+        assertContains(json, "foo.foo/foo.bar#times", 1);
+        assertContains(json, "foo.foo/foo.bar#name", "foo.bar");
+        assertContains(json, "foo.foo/foo.bar#parent", "foo.foo");
+        assertContains(json, "foo.foo/foo.bar#total_cost");
+        assertContains(json, "foo.foo/foo.bar#min_cost");
+        assertContains(json, "foo.foo/foo.bar#max_cost");
+        assertContains(json, "foo.foo/foo.bar#total_self_wasted");
+        assertContains(json, "foo.foo/foo.bar#total_children_wasted", -1);
+        assertContains(json, "foo.foo/foo.bar#total_children_times", -1);
+
+        perf.clear();
+
+        obj.foo();
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "foo.foo#times", 2);
+        assertContains(json, "foo.foo/foo.bar#times", 2);
+
+        perf.clear();
+        PerfUtil.useLightStopwatch(false);
+    }
+
+    @Test
+    public void testPerfUtil4LightStopwatcAndSwitch() throws Throwable {
+        perf.profileClass(prefix + "TestLightClass$Bar");
+
+        TestLightClass.Bar bar = new TestLightClass.Bar();
+        bar.foo();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "bar.foo#times", 1);
+        assertContains(json, "bar.foo/bar.bar#times", 1);
+
+        PerfUtil.useLightStopwatch(false);
+        bar.foo();
+        json = perf.toJson();
+
+        assertContains(json, "bar.foo#times", 2);
+        assertContains(json, "bar.foo/bar.bar#times", 2);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            PerfUtil.useLightStopwatch(true);
+        }, e -> {
+            Assert.assertContains("clear() before switching light-stopwatch",
+                                  e.getMessage());
+        });
+
+        // Test switch from normal-watch to light-watch
+        perf.clear();
+        PerfUtil.useLightStopwatch(true);
+        bar.foo();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "bar.foo#times", 1);
+        assertContains(json, "bar.foo/bar.bar#times", 1);
+
+        bar.foo();
+        json = perf.toJson();
+
+        assertContains(json, "bar.foo#times", 2);
+        assertContains(json, "bar.foo/bar.bar#times", 2);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            PerfUtil.useLightStopwatch(false);
+        }, e -> {
+            Assert.assertContains("clear() before switching light-stopwatch",
+                                  e.getMessage());
+        });
+
+        // Test switch from light-watch to normal-watch
+        perf.clear();
+        PerfUtil.useLightStopwatch(false);
+        bar.foo();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "bar.foo#times", 1);
+        assertContains(json, "bar.foo/bar.bar#times", 1);
+    }
+
+    @Test
+    public void testPerfUtilWithSingleThread() throws Throwable {
+        perf.profileClass(prefix + "TestClass$Bar");
+        PerfUtil.profileSingleThread(true);
+
+        TestClass.Bar obj = new TestClass.Bar();
+        obj.foo();
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "bar_foo#times", 1);
+        assertContains(json, "bar_foo/bar_bar#times", 1);
+
+        perf.clear();
+
+        obj.foo();
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "bar_foo#times", 2);
+        assertContains(json, "bar_foo/bar_bar#times", 2);
+
+        PerfUtil.profileSingleThread(false);
+
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "bar_foo#times", 3);
+        assertContains(json, "bar_foo/bar_bar#times", 3);
+    }
+
+    @Test
+    public void testPerfUtilWithProfilePackage() throws Throwable {
+        perf.profilePackage("org.apache.hugegraph.unit.perf.testclass2");
+
+        TestClass4Package.Foo obj = new TestClass4Package.Foo();
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "foo#times", 1);
+        assertContains(json, "foo/bar#times", 1);
+
+        TestClass4Package test = new TestClass4Package();
+        test.test();
+        json = perf.toJson();
+        assertContains(json, "test#times", 1);
+        assertContains(json, "test/bar#times", 1);
+        assertContains(json, "foo#times", 1);
+        assertContains(json, "foo/bar#times", 1);
+
+        perf.clear();
+
+        obj.foo();
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "foo#times", 2);
+        assertContains(json, "foo/bar#times", 2);
+    }
+
+    @Test
+    public void testPerfUtilWithProfileParentClass() throws Throwable {
+        perf.profileClass(prefix + "TestClass$Base");
+        perf.profileClass(prefix + "TestClass$Sub");
+
+        TestClass.Sub obj = new TestClass.Sub();
+        obj.func();
+        obj.func1();
+        obj.func2();
+        obj.func3();
+        obj.func3();
+        obj.func3();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+        assertContains(json, "func#times", 1);
+        assertContains(json, "func1#times", 1);
+        assertContains(json, "func3#times", 3);
+    }
+
+    @Test
+    public void testPerfUtilWithProfileManually() throws Throwable {
+        perf.profileClass(prefix + "TestClass$ManuallyProfile");
+
+        TestClass.ManuallyProfile obj = new TestClass.ManuallyProfile();
+
+        obj.foo();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "manu-foo#times", 1);
+        assertContains(json, "manu-foo/manu-bar#times", 1);
+        assertContains(json, "manu-foo/manu-bar2#times", 1);
+
+        obj.foo();
+        obj.bar();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "manu-foo#times", 2);
+        assertContains(json, "manu-foo/manu-bar#times", 2);
+        assertContains(json, "manu-bar#times", 1);
+
+        obj.foo2();
+        obj.bar2();
+
+        perf.toString();
+        perf.toECharts();
+        json = perf.toJson();
+
+        assertContains(json, "manu-foo2#times", 1);
+        assertContains(json, "manu-foo2/manu-bar#times#times", 1);
+        assertContains(json, "manu-foo2/manu-bar2#times#times", 1);
+        assertContains(json, "manu-foo#times", 2);
+        assertContains(json, "manu-foo/manu-bar#times", 2);
+        assertContains(json, "manu-bar#times", 1);
+        assertContains(json, "manu-bar2#times", 1);
+    }
+
+    @Test
+    public void testPerfUtilPerf() throws Throwable {
+        perf.profileClass(prefix + "TestPerfClass");
+        perf.profileClass(prefix + "TestPerfClass$Foo");
+
+        PerfUtil.profileSingleThread(true);
+        PerfUtil.useLocalTimer(true);
+
+        int times = 10000000;
+        TestPerfClass test = new TestPerfClass();
+        test.test(times);
+        test.testNew();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "testNew#times", 1);
+        assertContains(json, "test/testNew#times", times);
+        assertContains(json, "test/testNewAndCall#times", times);
+        assertContains(json, "test/testCall#times", times);
+        assertContains(json, "test/testCallFooThenSum#times", times);
+
+        assertContains(json, "test/testNewAndCall/sum#times", times);
+        assertContains(json, "test/testCall/sum#times", times);
+        assertContains(json, "test/testCallFooThenSum/foo#times", times);
+        assertContains(json, "test/testCallFooThenSum/foo/sum#times", times);
+
+        // Test call multi-times and Reset false
+        PerfUtil.profileSingleThread(true);
+        PerfUtil.profileSingleThread(true);
+        PerfUtil.profileSingleThread(false);
+        PerfUtil.profileSingleThread(false);
+        PerfUtil.useLocalTimer(true);
+        PerfUtil.useLocalTimer(true);
+        PerfUtil.useLocalTimer(false);
+        PerfUtil.useLocalTimer(false);
+
+        test.testNew();
+        json = perf.toJson();
+        assertContains(json, "testNew#times", 2);
+    }
+
+    @Test
+    public void testPerfUtilPerf4LightStopwatch() throws Throwable {
+        perf.profileClass(prefix + "TestPerfLightClass");
+        perf.profileClass(prefix + "TestPerfLightClass$Foo");
+
+        PerfUtil.profileSingleThread(true);
+        PerfUtil.useLightStopwatch(true);
+        PerfUtil.useLocalTimer(true);
+
+        int times = 10000000;
+        TestPerfLightClass test = new TestPerfLightClass();
+        test.test(times);
+        test.testNew();
+
+        perf.toString();
+        perf.toECharts();
+        String json = perf.toJson();
+
+        assertContains(json, "testNew#times", 1);
+        assertContains(json, "test/testNew#times", times);
+        assertContains(json, "test/testNewAndCall#times", times);
+        assertContains(json, "test/testCall#times", times);
+        assertContains(json, "test/testCallFooThenSum#times", times);
+
+        assertContains(json, "test/testNewAndCall/sum#times", times);
+        assertContains(json, "test/testCall/sum#times", times);
+        assertContains(json, "test/testCallFooThenSum/foo#times", times);
+        assertContains(json, "test/testCallFooThenSum/foo/sum#times", times);
+
+        // Test reset and call multi-times
+        PerfUtil.profileSingleThread(true);
+        PerfUtil.profileSingleThread(true);
+        PerfUtil.profileSingleThread(false);
+        PerfUtil.profileSingleThread(false);
+
+        PerfUtil.useLocalTimer(true);
+        PerfUtil.useLocalTimer(true);
+        PerfUtil.useLocalTimer(false);
+        PerfUtil.useLocalTimer(false);
+
+        perf.clear();
+        PerfUtil.useLightStopwatch(false);
+        PerfUtil.useLightStopwatch(false);
+
+        test.testNew();
+        json = perf.toJson();
+        assertContains(json, "testNew#times", 1);
+    }
+
+    private static void assertContains(String json, String key)
+                                       throws Exception {
+        Assert.assertNotNull("Not exist key " + key, actualValue(json, key));
+    }
+
+    private static void assertContains(String json, String key, Object value)
+                                       throws Exception {
+        String error = String.format("not contains key '%s' with value <%s> " +
+                                     "in json: %s.\n", key, value, json);
+        Assert.assertEquals(error, value, actualValue(json, key));
+    }
+
+    private static Object actualValue(String json, String key)
+                                      throws Exception {
+        ObjectMapper mapper = new ObjectMapper();
+        Map<?, ?> map = mapper.readValue(json, Map.class);
+        String[] keys = key.split("#");
+        Object actual = null;
+        for (String k : keys) {
+            actual = map.get(k);
+            if (actual instanceof Map) {
+                map = (Map<?, ?>) actual;
+            }
+        }
+        return actual;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/StopwatchTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/StopwatchTest.java
new file mode 100644
index 0000000000..6a6c7865d9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/StopwatchTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.hugegraph.unit.perf;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.perf.LightStopwatch;
+import org.apache.hugegraph.perf.NormalStopwatch;
+import org.apache.hugegraph.perf.Stopwatch;
+import org.apache.hugegraph.perf.Stopwatch.Path;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class StopwatchTest extends BaseUnitTest {
+
+    @Test
+    public void testNormalStopwatchChild() {
+        Stopwatch watch1 = new NormalStopwatch("w1", Path.EMPTY);
+
+        Stopwatch watch2 = new NormalStopwatch("w2", watch1);
+        Stopwatch watch3 = new NormalStopwatch("w3", watch1);
+        Stopwatch watch4 = new NormalStopwatch("w4", watch1);
+        Stopwatch watch5 = new NormalStopwatch("w5", watch1);
+
+        Assert.assertEquals(watch2, watch1.child("w2"));
+        Assert.assertEquals(watch3, watch1.child("w3"));
+        Assert.assertEquals(watch4, watch1.child("w4"));
+        Assert.assertEquals(watch5, watch1.child("w5"));
+
+        Assert.assertEquals(watch2, watch1.child("w2", null));
+        Assert.assertEquals(watch3, watch1.child("w3", null));
+        Assert.assertEquals(watch4, watch1.child("w4", null));
+        Assert.assertEquals(watch5, watch1.child("w5", null));
+
+        Assert.assertNull(watch1.child("w2"));
+        Assert.assertNull(watch1.child("w3"));
+        Assert.assertNull(watch1.child("w4"));
+        Assert.assertNull(watch1.child("w5"));
+
+        Assert.assertNull(watch1.child("w2", watch2));
+        Assert.assertNull(watch1.child("w3", watch3));
+        Assert.assertNull(watch1.child("w4", watch4));
+        Assert.assertNull(watch1.child("w5", watch5));
+
+        watch1.clear();
+        Assert.assertNull(watch1.child("w2"));
+        Assert.assertNull(watch1.child("w3"));
+        Assert.assertNull(watch1.child("w4"));
+        Assert.assertNull(watch1.child("w5"));
+    }
+
+    @Test
+    public void testLightStopwatchChild() {
+        Stopwatch watch1 = new LightStopwatch("w1", Path.EMPTY);
+
+        Stopwatch watch2 = new LightStopwatch("w2", watch1);
+        Stopwatch watch3 = new LightStopwatch("w3", watch1);
+        Stopwatch watch4 = new LightStopwatch("w4", watch1);
+        Stopwatch watch5 = new LightStopwatch("w5", watch1);
+
+        Assert.assertEquals(watch2, watch1.child("w2"));
+        Assert.assertEquals(watch3, watch1.child("w3"));
+        Assert.assertEquals(watch4, watch1.child("w4"));
+        Assert.assertEquals(watch5, watch1.child("w5"));
+
+        Assert.assertEquals(watch2, watch1.child("w2", null));
+        Assert.assertEquals(watch3, watch1.child("w3", null));
+        Assert.assertEquals(watch4, watch1.child("w4", null));
+        Assert.assertEquals(watch5, watch1.child("w5", null));
+
+        Assert.assertNull(watch1.child("w2"));
+        Assert.assertNull(watch1.child("w3"));
+        Assert.assertNull(watch1.child("w4"));
+        Assert.assertNull(watch1.child("w5"));
+
+        Assert.assertNull(watch1.child("w2", watch2));
+        Assert.assertNull(watch1.child("w3", watch3));
+        Assert.assertNull(watch1.child("w4", watch4));
+        Assert.assertNull(watch1.child("w5", watch5));
+
+        watch1.clear();
+        Assert.assertNull(watch1.child("w2"));
+        Assert.assertNull(watch1.child("w3"));
+        Assert.assertNull(watch1.child("w4"));
+        Assert.assertNull(watch1.child("w5"));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestClass.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestClass.java
new file mode 100644
index 0000000000..fcc90b9813
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestClass.java
@@ -0,0 +1,105 @@
+/*
+ * 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.hugegraph.unit.perf.testclass;
+
+import org.apache.hugegraph.perf.PerfUtil;
+import org.apache.hugegraph.perf.PerfUtil.Watched;
+
+public class TestClass {
+
+    @Watched
+    public void test() {
+        new Foo().bar();
+    }
+
+    public static class Foo {
+
+        @Watched(prefix="foo")
+        public void foo() {
+            this.bar();
+        }
+
+        @Watched(prefix="foo")
+        public void bar() {}
+    }
+
+    public static class Bar {
+
+        @Watched("bar_foo")
+        public void foo() {
+            this.bar();
+        }
+
+        @Watched("bar_bar")
+        public void bar() {}
+    }
+
+    public static class ManuallyProfile {
+
+        public void foo() {
+            PerfUtil.instance().start("manu-foo");
+            this.bar();
+            this.bar2();
+            PerfUtil.instance().end("manu-foo");
+        }
+
+        public void bar() {
+            PerfUtil.instance().start("manu-bar");
+            try {
+                Thread.sleep(0);
+            } catch (InterruptedException ignored) {
+                // pass
+            }
+            PerfUtil.instance().end("manu-bar");
+        }
+
+        public void foo2() {
+            PerfUtil.instance().start2("manu-foo2");
+            this.bar();
+            this.bar2();
+            PerfUtil.instance().end("manu-foo2");
+        }
+
+        public void bar2() {
+            PerfUtil.instance().start2("manu-bar2");
+            try {
+                Thread.sleep(0);
+            } catch (InterruptedException ignored) {
+                // pass
+            }
+            PerfUtil.instance().end("manu-bar2");
+        }
+    }
+
+    public static class Base {
+
+        @Watched
+        public void func() {}
+    }
+
+    public static class Sub extends Base {
+
+        @Watched
+        public void func1() {}
+
+        public void func2() {}
+
+        @Watched
+        public void func3() {}
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestLightClass.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestLightClass.java
new file mode 100644
index 0000000000..fd2e334bad
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestLightClass.java
@@ -0,0 +1,50 @@
+/*
+ * 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.hugegraph.unit.perf.testclass;
+
+import org.apache.hugegraph.perf.PerfUtil.Watched;
+
+public class TestLightClass {
+
+    @Watched
+    public void test() {
+        new Foo().bar();
+    }
+
+    public static class Foo {
+
+        @Watched(prefix="foo")
+        public void foo() {
+            this.bar();
+        }
+
+        @Watched(prefix="foo")
+        public void bar() {}
+    }
+
+    public static class Bar {
+
+        @Watched(prefix="bar")
+        public void foo() {
+            this.bar();
+        }
+
+        @Watched(prefix="bar")
+        public void bar() {}
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestPerfClass.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestPerfClass.java
new file mode 100644
index 0000000000..a9146f727e
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestPerfClass.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.hugegraph.unit.perf.testclass;
+
+import org.apache.hugegraph.perf.PerfUtil.Watched;
+
+public class TestPerfClass {
+
+    private Foo foo = new Foo();
+
+    @Watched
+    public void test(int times) {
+        for (int i = 0; i < times; i++) {
+            this.testNew();
+            this.testNewAndCall();
+            this.testCall();
+            this.testCallFooThenSum();
+        }
+    }
+
+    @Watched
+    public void testNew() {
+        new Foo();
+    }
+
+    @Watched
+    public void testNewAndCall() {
+        new Foo().sum(1, 2);
+    }
+
+    @Watched
+    public void testCall() {
+        this.foo.sum(1, 2);
+    }
+
+    @Watched
+    public void testCallFooThenSum() {
+        this.foo.foo();
+    }
+
+    public static class Foo {
+
+        @Watched
+        public void foo() {
+            this.sum(1, 2);
+        }
+
+        @Watched
+        public int sum(int a, int b) {
+            int sum = a;
+            for (int i = 0; i < 100; i++) {
+                sum += i;
+            }
+            return sum + b;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestPerfLightClass.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestPerfLightClass.java
new file mode 100644
index 0000000000..430b9ac97a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass/TestPerfLightClass.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.hugegraph.unit.perf.testclass;
+
+import org.apache.hugegraph.perf.PerfUtil.Watched;
+
+public class TestPerfLightClass {
+
+    private final Foo foo = new Foo();
+
+    @Watched
+    public void test(int times) {
+        for (int i = 0; i < times; i++) {
+            this.testNew();
+            this.testNewAndCall();
+            this.testCall();
+            this.testCallFooThenSum();
+        }
+    }
+
+    @Watched
+    public void testNew() {
+        new Foo();
+    }
+
+    @Watched
+    public void testNewAndCall() {
+        new Foo().sum(1, 2);
+    }
+
+    @Watched
+    public void testCall() {
+        this.foo.sum(1, 2);
+    }
+
+    @Watched
+    public void testCallFooThenSum() {
+        this.foo.foo();
+    }
+
+    public static class Foo {
+
+        @Watched
+        public void foo() {
+            this.sum(1, 2);
+        }
+
+        @Watched
+        public int sum(int a, int b) {
+            int sum = a;
+            for (int i = 0; i < 100; i++) {
+                sum += i;
+            }
+            return sum + b;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass2/TestClass4Package.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass2/TestClass4Package.java
new file mode 100644
index 0000000000..9a29c2ab56
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/perf/testclass2/TestClass4Package.java
@@ -0,0 +1,69 @@
+/*
+ * 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.hugegraph.unit.perf.testclass2;
+
+import org.apache.hugegraph.perf.PerfUtil.Watched;
+
+public class TestClass4Package {
+
+    @Watched
+    public void test() {
+        new Foo().bar();
+    }
+
+    public static class Foo extends FooBase {
+
+        @Watched
+        public void foo() {
+            this.bar();
+        }
+
+        @Watched
+        public void bar() {}
+    }
+
+    public static class FooBase {}
+
+    public static class Bar {
+
+        @Watched
+        public void foo() {
+            this.bar();
+        }
+
+        @Watched
+        public void bar() {}
+    }
+
+    public static class Base {
+
+        @Watched
+        public void func() {}
+    }
+
+    public static class Sub extends Base {
+
+        @Watched
+        public void func1() {}
+
+        public void func2() {}
+
+        @Watched
+        public void func3() {}
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/AbstractRestClientTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/AbstractRestClientTest.java
new file mode 100644
index 0000000000..b2d2b1a3bc
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/AbstractRestClientTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.hugegraph.unit.rest;
+
+import org.apache.hugegraph.rest.AbstractRestClient;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AbstractRestClientTest {
+
+    @Test
+    public void testEncodeWithSpaces() {
+        String raw = "hello world";
+        String expected = "hello%2Bworld";
+        String encoded = AbstractRestClient.encode(raw);
+        Assert.assertEquals(expected, encoded);
+    }
+
+    @Test
+    public void testEncodeWithSpecialCharacters() {
+        String raw = "hello@world!";
+        String expected = "hello%40world%21";
+        String encoded = AbstractRestClient.encode(raw);
+        Assert.assertEquals(expected, encoded);
+    }
+
+    @Test
+    public void testEncodeWithChineseCharacters() {
+        String raw = "你好";
+        String expected = "%E4%BD%A0%E5%A5%BD";
+        String encoded = AbstractRestClient.encode(raw);
+        Assert.assertEquals(expected, encoded);
+    }
+
+    @Test
+    public void testEncodeWithNullInput() {
+        String raw = null;
+        Assert.assertThrows(NullPointerException.class, () -> {
+            AbstractRestClient.encode(raw);
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestClientTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestClientTest.java
new file mode 100644
index 0000000000..712aea7ab2
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestClientTest.java
@@ -0,0 +1,521 @@
+/*
+ * 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.hugegraph.unit.rest;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+
+import org.apache.hugegraph.rest.AbstractRestClient;
+import org.apache.hugegraph.rest.ClientException;
+import org.apache.hugegraph.rest.RestClient;
+import org.apache.hugegraph.rest.RestClientConfig;
+import org.apache.hugegraph.rest.RestHeaders;
+import org.apache.hugegraph.rest.RestResult;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.testutil.Whitebox;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.net.HttpHeaders;
+
+import lombok.SneakyThrows;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class RestClientTest {
+
+    private static final String TEST_URL = "http://localhost:8080";
+
+    @Test
+    public void testPost() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    // TODO: How to verify it?
+    public void testPostWithMaxConnsAndPerRoute() {
+        RestClientConfig restClientConfig =
+                RestClientConfig.builder().timeout(1000).maxConns(10).maxConnsPerRoute(5).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPostWithUserAndPassword() {
+        RestClientConfig restClientConfig =
+                RestClientConfig.builder().user("user").password("").timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPostWithToken() {
+        RestClientConfig restClientConfig =
+                RestClientConfig.builder().token("token").timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPostWithAllParams() {
+        RestClientConfig restClientConfig =
+                RestClientConfig.builder().user("user").password("").timeout(1000).maxConns(10)
+                                .maxConnsPerRoute(5).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPostWithTokenAndAllParams() {
+        RestClientConfig restClientConfig =
+                RestClientConfig.builder().token("token").timeout(1000).maxConns(10)
+                                .maxConnsPerRoute(5).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPostHttpsWithAllParams() {
+        String url = "https://github.com/apache/incubator-hugegraph-doc/" +
+                     "raw/master/dist/commons/cacerts.jks";
+        String trustStoreFile = "src/test/resources/cacerts.jks";
+        BaseUnitTest.downloadFileByUrl(url, trustStoreFile);
+
+        String trustStorePassword = "changeit";
+        RestClientConfig restClientConfig =
+                RestClientConfig.builder().user("user").password("").timeout(1000).maxConns(10)
+                                .maxConnsPerRoute(5).trustStoreFile(trustStoreFile)
+                                .trustStorePassword(trustStorePassword).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPostHttpsWithTokenAndAllParams() {
+        String url = "https://github.com/apache/incubator-hugegraph-doc/" +
+                     "raw/master/dist/commons/cacerts.jks";
+        String trustStoreFile = "src/test/resources/cacerts.jks";
+        BaseUnitTest.downloadFileByUrl(url, trustStoreFile);
+
+        String trustStorePassword = "changeit";
+        RestClientConfig restClientConfig =
+                RestClientConfig.builder().token("token").timeout(1000).maxConns(10)
+                                .maxConnsPerRoute(5).trustStoreFile(trustStoreFile)
+                                .trustStorePassword(trustStorePassword).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testHostNameVerifier() {
+        BiFunction<String, String, Boolean> verifer = (url, hostname) -> {
+            AbstractRestClient.HostNameVerifier verifier;
+            SSLSession session;
+            try {
+                SSLSessionContext sc = SSLContext.getDefault()
+                                                 .getClientSessionContext();
+                session = sc.getSession(new byte[]{11});
+                verifier = new AbstractRestClient.HostNameVerifier(url);
+            } catch (NoSuchAlgorithmException e) {
+                throw new RuntimeException(e);
+            }
+            return verifier.verify(hostname, session);
+        };
+
+        Assert.assertTrue(verifer.apply("http://baidu.com", "baidu.com"));
+        Assert.assertTrue(verifer.apply("http://test1.baidu.com", "baidu.com"));
+        Assert.assertTrue(verifer.apply("http://test2.baidu.com", "baidu.com"));
+        Assert.assertFalse(verifer.apply("http://baidu2.com", "baidu.com"));
+        Assert.assertTrue(verifer.apply("http://baidu.com", ""));
+        Assert.assertTrue(verifer.apply("baidu.com", "baidu.com"));
+        Assert.assertTrue(verifer.apply("http://baidu.com/test", "baidu.com"));
+        Assert.assertTrue(verifer.apply("baidu.com/test/abc", "baidu.com"));
+        Assert.assertFalse(verifer.apply("baidu.com.sina.com", "baidu.com"));
+    }
+
+    @Test
+    public void testPostWithHeaderAndContent() {
+        RestHeaders headers = new RestHeaders().add("key1", "value1-1")
+                                               .add("key1", "value1-2")
+                                               .add("Content-Encoding", "gzip");
+        String content = "{\"names\": [\"marko\", \"josh\", \"lop\"]}";
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200, headers, content);
+        RestResult restResult = client.post("path", "body");
+        Assert.assertEquals(200, restResult.status());
+        Assert.assertEquals(headers, restResult.headers());
+        Assert.assertEquals(content, restResult.content());
+        Assert.assertEquals(ImmutableList.of("marko", "josh", "lop"),
+                            restResult.readList("names", String.class));
+    }
+
+    @Test
+    public void testPostWithException() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 400);
+        Assert.assertThrows(ClientException.class, () -> {
+            client.post("path", "body");
+        });
+    }
+
+    @Test
+    public void testPostWithParams() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestHeaders headers = new RestHeaders();
+
+        Map<String, Object> params = ImmutableMap.of("param1", "value1");
+        RestResult restResult = client.post("path", "body", headers,
+                                            params);
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPut() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.put("path", "id1", "body");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPutWithHeaders() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestHeaders headers = new RestHeaders().add("key1", "value1-1")
+                                               .add("key2", "value1-2")
+                                               .add("Content-Encoding", "gzip");
+        RestResult restResult = client.put("path", "id1", "body", headers);
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPutWithParams() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        Map<String, Object> params = ImmutableMap.of("param1", "value1");
+        RestResult restResult = client.put("path", "id1", "body", params);
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testPutWithException() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 400);
+        Assert.assertThrows(ClientException.class, () -> {
+            client.put("path", "id1", "body");
+        });
+    }
+
+    @Test
+    public void testGet() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.get("path");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testGetWithId() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        RestResult restResult = client.get("path", "id1");
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testGetWithParams() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        Map<String, Object> params = new HashMap<>();
+        params.put("key1", ImmutableList.of("value1-1", "value1-2"));
+        params.put("key2", "value2");
+        RestResult restResult = client.get("path", params);
+        Assert.assertEquals(200, restResult.status());
+    }
+
+    @Test
+    public void testGetWithException() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 400);
+        Assert.assertThrows(ClientException.class, () -> {
+            client.get("path", "id1");
+        });
+    }
+
+    @Test
+    public void testDeleteWithId() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 204);
+        RestResult restResult = client.delete("path", "id1");
+        Assert.assertEquals(204, restResult.status());
+    }
+
+    @Test
+    public void testDeleteWithParams() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 204);
+        Map<String, Object> params = ImmutableMap.of("param1", "value1");
+        RestResult restResult = client.delete("path", params);
+        Assert.assertEquals(204, restResult.status());
+    }
+
+    @Test
+    public void testDeleteWithException() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 400);
+        Assert.assertThrows(ClientException.class, () -> {
+            client.delete("path", "id1");
+        });
+    }
+
+    @Test
+    public void testAuthContext() {
+        RestClientConfig restClientConfig = RestClientConfig.builder().timeout(1000).build();
+        RestClientImpl client = new RestClientImpl(TEST_URL, restClientConfig, 200);
+        Assert.assertNull(client.getAuthContext());
+
+        String token = UUID.randomUUID().toString();
+        client.setAuthContext(token);
+        Assert.assertEquals(token, client.getAuthContext());
+
+        client.resetAuthContext();
+        Assert.assertNull(client.getAuthContext());
+    }
+
+    @SneakyThrows
+    @Test
+    public void testBuilderCallback() {
+        // default configs
+        MockRestClientImpl restClient = new MockRestClientImpl(TEST_URL,
+                                                               RestClientConfig.builder().build());
+        OkHttpClient okHttpClient = Whitebox.getInternalState(restClient, "client");
+        Assert.assertEquals(okHttpClient.connectTimeoutMillis(), 10000);
+        Assert.assertEquals(okHttpClient.readTimeoutMillis(), 10000);
+
+        // set config by (user)builderCallback
+        RestClientConfig config = RestClientConfig.builder().builderCallback(
+                builder -> builder.connectTimeout(5, TimeUnit.SECONDS)
+                                  .readTimeout(30, TimeUnit.SECONDS))
+                                  .build();
+
+        restClient = new MockRestClientImpl(TEST_URL, config);
+        okHttpClient = Whitebox.getInternalState(restClient, "client");
+
+        Assert.assertEquals(okHttpClient.connectTimeoutMillis(), 5000);
+        Assert.assertEquals(okHttpClient.readTimeoutMillis(), 30000);
+    }
+
+    @SneakyThrows
+    @Test
+    public void testRequest() {
+        Response response = Mockito.mock(Response.class, Mockito.RETURNS_DEEP_STUBS);
+        Mockito.when(response.code()).thenReturn(200);
+        Mockito.when(response.headers())
+               .thenReturn(new RestHeaders().toOkHttpHeader());
+        Mockito.when(response.body().string()).thenReturn("content");
+
+        Request.Builder requestBuilder = Mockito.mock(Request.Builder.class,
+                                                      Mockito.RETURNS_DEEP_STUBS);
+        Mockito.when(requestBuilder.delete()).thenReturn(requestBuilder);
+        Mockito.when(requestBuilder.get()).thenReturn(requestBuilder);
+        Mockito.when(requestBuilder.put(Mockito.any())).thenReturn(requestBuilder);
+        Mockito.when(requestBuilder.post(Mockito.any())).thenReturn(requestBuilder);
+        Mockito.when(requestBuilder.url((HttpUrl) Mockito.any())).thenReturn(requestBuilder);
+        MockRestClientImpl client = new MockRestClientImpl(TEST_URL, 1000) {
+            @Override
+            protected Request.Builder newRequestBuilder() {
+                return requestBuilder;
+            }
+        };
+
+        OkHttpClient okHttpClient = Mockito.mock(OkHttpClient.class, Mockito.RETURNS_DEEP_STUBS);
+        Mockito.when(okHttpClient.newCall(Mockito.any()).execute()).thenReturn(response);
+
+        Whitebox.setInternalState(client, "client", okHttpClient);
+
+        RestResult result;
+
+        // Test delete
+        client.setAuthContext("token1");
+        result = client.delete("test", ImmutableMap.of());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(RestHeaders.AUTHORIZATION, "token1");
+
+        client.resetAuthContext();
+
+        client.setAuthContext("token2");
+        result = client.delete("test", "id");
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token2");
+        client.resetAuthContext();
+
+        // Test get
+        client.setAuthContext("token3");
+        result = client.get("test");
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token3");
+        client.resetAuthContext();
+
+        client.setAuthContext("token4");
+        result = client.get("test", ImmutableMap.of());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token4");
+        client.resetAuthContext();
+
+        client.setAuthContext("token5");
+        result = client.get("test", "id");
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token5");
+        client.resetAuthContext();
+
+        // Test put
+        client.setAuthContext("token6");
+        result = client.post("test", null);
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token6");
+        client.resetAuthContext();
+
+        client.setAuthContext("token7");
+        result = client.post("test", null, new RestHeaders());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token7");
+        client.resetAuthContext();
+
+        client.setAuthContext("token8");
+        result = client.post("test", null, ImmutableMap.of());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token8");
+        client.resetAuthContext();
+
+        client.setAuthContext("token9");
+        result = client.post("test", null, new RestHeaders(),
+                             ImmutableMap.of());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token9");
+        client.resetAuthContext();
+
+        // Test post
+        client.setAuthContext("token10");
+        result = client.post("test", null);
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token10");
+        client.resetAuthContext();
+
+        client.setAuthContext("token11");
+        result = client.post("test", null, new RestHeaders());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token11");
+        client.resetAuthContext();
+
+        client.setAuthContext("token12");
+        result = client.post("test", null, ImmutableMap.of());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token12");
+        client.resetAuthContext();
+
+        client.setAuthContext("token13");
+        result = client.post("test", null, new RestHeaders(),
+                             ImmutableMap.of());
+        Assert.assertEquals(200, result.status());
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, "token13");
+        client.resetAuthContext();
+    }
+
+    private static class RestClientImpl extends AbstractRestClient {
+
+        private final int status;
+        private final RestHeaders headers;
+        private final String content;
+
+        public RestClientImpl(String url, RestClientConfig config, int status) {
+            this(url, config, status, new RestHeaders(), "");
+        }
+
+        public RestClientImpl(String url, RestClientConfig config, int status, RestHeaders headers,
+                              String content) {
+            super(url, config);
+            this.status = status;
+            this.headers = headers;
+            this.content = content;
+        }
+
+        @SneakyThrows
+        @Override
+        protected Response request(Request.Builder requestBuilder) {
+            Response response = Mockito.mock(Response.class, Mockito.RETURNS_DEEP_STUBS);
+            Mockito.when(response.code()).thenReturn(this.status);
+            Mockito.when(response.headers()).thenReturn(this.headers.toOkHttpHeader());
+            Mockito.when(response.body().string()).thenReturn(this.content);
+            return response;
+        }
+
+        @Override
+        protected void checkStatus(Response response, int... statuses) {
+            boolean match = false;
+            for (int status : statuses) {
+                if (status == response.code()) {
+                    match = true;
+                    break;
+                }
+            }
+            if (!match) {
+                throw new ClientException("Invalid response '%s'", response);
+            }
+        }
+    }
+
+    private static class MockRestClientImpl extends AbstractRestClient {
+
+        public MockRestClientImpl(String url, int timeout) {
+            super(url, timeout);
+        }
+
+        public MockRestClientImpl(String url, RestClientConfig config) {
+            super(url, config);
+        }
+
+        @Override
+        protected void checkStatus(Response response, int... statuses) {
+            // pass
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestResultTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestResultTest.java
new file mode 100644
index 0000000000..06eb03a11d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestResultTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.hugegraph.unit.rest;
+
+import java.util.Map;
+
+import org.apache.hugegraph.rest.RestHeaders;
+import org.apache.hugegraph.rest.RestResult;
+import org.apache.hugegraph.rest.SerializeException;
+import org.apache.hugegraph.testutil.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import lombok.SneakyThrows;
+import okhttp3.Response;
+
+public class RestResultTest {
+
+    private static RestResult newRestResult(int status) {
+        return newRestResult(status, "", new RestHeaders());
+    }
+
+    private static RestResult newRestResult(int status, String content) {
+        return newRestResult(status, content, new RestHeaders());
+    }
+
+    private static RestResult newRestResult(int status, RestHeaders headers) {
+        return newRestResult(status, "", headers);
+    }
+
+    @SneakyThrows
+    private static RestResult newRestResult(int status, String content,
+                                            RestHeaders headers) {
+        Response response = Mockito.mock(Response.class, Mockito.RETURNS_DEEP_STUBS);
+        Mockito.when(response.code()).thenReturn(status);
+        Mockito.when(response.headers()).thenReturn(headers.toOkHttpHeader());
+        Mockito.when(response.body().string())
+               .thenReturn(content);
+        return new RestResult(response);
+    }
+
+    @Test
+    public void testStatus() {
+        RestResult result = newRestResult(200);
+        Assert.assertEquals(200, result.status());
+    }
+
+    @Test
+    public void testHeaders() {
+        RestHeaders headers = new RestHeaders();
+        headers.add("key1", "value1-1");
+        headers.add("key1", "value1-2");
+        headers.add("key2", "value2");
+        RestResult result = newRestResult(200, headers);
+        Assert.assertEquals(200, result.status());
+        Assert.assertEquals(headers, result.headers());
+    }
+
+    @Test
+    public void testContent() {
+        String content = "{\"name\": \"marko\"}";
+        RestResult result = newRestResult(200, content);
+        Assert.assertEquals(200, result.status());
+        Assert.assertEquals(content, result.content());
+        Assert.assertEquals(ImmutableMap.of("name", "marko"),
+                            result.readObject(Map.class));
+    }
+
+    @Test
+    public void testContentWithException() {
+        String content = "{illegal key: \"marko\"}";
+        RestResult result = newRestResult(200, content);
+        Assert.assertEquals(200, result.status());
+        Assert.assertEquals(content, result.content());
+        Assert.assertThrows(SerializeException.class, () -> {
+            result.readObject(Map.class);
+        });
+    }
+
+    @Test
+    public void testContentList() {
+        String content = "{\"names\": [\"marko\", \"josh\", \"lop\"]}";
+        RestResult result = newRestResult(200, content);
+        Assert.assertEquals(200, result.status());
+        Assert.assertEquals(content, result.content());
+        Assert.assertEquals(ImmutableList.of("marko", "josh", "lop"),
+                            result.readList("names", String.class));
+
+        content = "[\"marko\", \"josh\", \"lop\"]";
+        result = newRestResult(200, content);
+        Assert.assertEquals(200, result.status());
+        Assert.assertEquals(content, result.content());
+        Assert.assertEquals(ImmutableList.of("marko", "josh", "lop"),
+                            result.readList(String.class));
+    }
+
+    @Test
+    public void testContentListWithException() {
+        String content = "{\"names\": [\"marko\", \"josh\", \"lop\"]}";
+        RestResult result = newRestResult(200, content);
+        Assert.assertEquals(200, result.status());
+        Assert.assertEquals(content, result.content());
+        Assert.assertThrows(SerializeException.class, () -> {
+            result.readList("unexitsed key", String.class);
+        });
+
+        content = "{\"names\": [marko, josh, \"lop\"]}";
+        RestResult result2 = newRestResult(200, content);
+        Assert.assertEquals(200, result2.status());
+        Assert.assertEquals(content, result2.content());
+        Assert.assertThrows(SerializeException.class, () -> {
+            result2.readList("names", String.class);
+        });
+
+        content = "[marko, josh, \"lop\"]";
+        RestResult result3 = newRestResult(200, content);
+        Assert.assertEquals(200, result3.status());
+        Assert.assertEquals(content, result3.content());
+        Assert.assertThrows(SerializeException.class, () -> {
+            result3.readList(String.class);
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/BytesTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/BytesTest.java
new file mode 100644
index 0000000000..7ecc59cbd0
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/BytesTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.util.Bytes;
+import org.apache.hugegraph.util.NumericUtil;
+import org.apache.hugegraph.testutil.Assert;
+
+public class BytesTest extends BaseUnitTest {
+
+    @Test
+    public void testBytesEquals() {
+        Assert.assertTrue(Bytes.equals(b("12345678"),
+                                       b("12345678")));
+        Assert.assertTrue(Bytes.equals(new byte[]{1, 3, 5, 7},
+                                       new byte[]{1, 3, 5, 7}));
+
+        Assert.assertFalse(Bytes.equals(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3, 6, 7}));
+        Assert.assertFalse(Bytes.equals(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3, 5, 7, 0}));
+    }
+
+    @Test
+    public void testBytesPrefixWith() {
+        Assert.assertTrue(Bytes.prefixWith(b("12345678"), b("12345678")));
+        Assert.assertTrue(Bytes.prefixWith(b("12345678"), b("1234567")));
+
+        Assert.assertTrue(Bytes.prefixWith(new byte[]{1, 3, 5, 7},
+                                           new byte[]{1, 3, 5, 7}));
+        Assert.assertTrue(Bytes.prefixWith(new byte[]{1, 3, 5, 7},
+                                           new byte[]{1, 3, 5}));
+        Assert.assertTrue(Bytes.prefixWith(new byte[]{1, 3, 5, 7},
+                                           new byte[]{1, 3}));
+
+        Assert.assertFalse(Bytes.prefixWith(new byte[]{1, 3, 5, 7},
+                                            new byte[]{1, 3, 6, 6}));
+        Assert.assertFalse(Bytes.prefixWith(new byte[]{1, 3, 5, 7},
+                                            new byte[]{3, 1}));
+        Assert.assertFalse(Bytes.prefixWith(new byte[]{1, 3, 5, 7},
+                                            new byte[]{1, 3, 5, 7, 0}));
+    }
+
+    @Test
+    public void testBytesCompare() {
+        Assert.assertEquals(0, Bytes.compare(b("12345678"), b("12345678")));
+        Assert.assertTrue(Bytes.compare(b("12345678"), b("1234567")) > 0);
+        Assert.assertTrue(Bytes.compare(b("12345678"), b("12345679")) < 0);
+
+        Assert.assertEquals(0,
+                            Bytes.compare(new byte[]{1, 3, 5, 7}, new byte[]{1, 3, 5, 7}));
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3, 5, 6}) > 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3, 5}) > 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 0},
+                                        new byte[]{1, 3, 5}) > 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3}) > 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3, 6, 0}) < 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 4}) < 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{3, 1}) < 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3, 5, 7, 0}) < 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
+                                        new byte[]{1, 3, 5, -1}) < 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 0},
+                                        new byte[]{1, 3, 5, -128}) < 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, -2},
+                                        new byte[]{1, 3, 5, -1}) < 0);
+
+        Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, -128},
+                                        new byte[]{1, 3, 5, -1}) < 0);
+    }
+
+    @Test
+    public void testBytesConcat() {
+        Assert.assertArrayEquals(b("12345678"),
+                                 Bytes.concat(b("1234"), b("5678")));
+        Assert.assertArrayEquals(b("12345678"),
+                                 Bytes.concat(b("12345678"), b("")));
+        Assert.assertArrayEquals(b("12345678"),
+                                 Bytes.concat(b(""), b("12345678")));
+    }
+
+    @Test
+    public void testBytesContains() {
+        Assert.assertTrue(Bytes.contains(b("1234"), (byte) '1'));
+        Assert.assertTrue(Bytes.contains(b("1234"), (byte) '3'));
+        Assert.assertTrue(Bytes.contains(b("1234"), (byte) '4'));
+
+        Assert.assertFalse(Bytes.contains(b("1234"), (byte) '0'));
+        Assert.assertFalse(Bytes.contains(b(""), (byte) '0'));
+    }
+
+    @Test
+    public void testBytesIndexOf() {
+        Assert.assertEquals(0, Bytes.indexOf(b("1234"), (byte) '1'));
+        Assert.assertEquals(2, Bytes.indexOf(b("1234"), (byte) '3'));
+        Assert.assertEquals(3, Bytes.indexOf(b("1234"), (byte) '4'));
+
+        Assert.assertEquals(-1, Bytes.indexOf(b("1234"), (byte) '0'));
+        Assert.assertEquals(-1, Bytes.indexOf(b(""), (byte) '0'));
+    }
+
+    @Test
+    public void testByteToHex() {
+        byte value = 0;
+        Assert.assertEquals("00", Bytes.toHex(value));
+
+        value = 127;
+        Assert.assertEquals("7f", Bytes.toHex(value));
+
+        value = -128;
+        Assert.assertEquals("80", Bytes.toHex(value));
+
+        value = -1;
+        Assert.assertEquals("ff", Bytes.toHex(value));
+    }
+
+    @Test
+    public void testBytesToHex() {
+        int value = 0x0103807f;
+        byte[] bytes = NumericUtil.intToBytes(value);
+        Assert.assertEquals("0103807f", Bytes.toHex(bytes));
+    }
+
+    @Test
+    public void testBytesFromHex() {
+        Assert.assertEquals(0x0103807f,
+                            NumericUtil.bytesToInt(Bytes.fromHex("0103807f")));
+    }
+
+    private static byte[] b(String string) {
+        return string.getBytes();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/CollectionUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/CollectionUtilTest.java
new file mode 100644
index 0000000000..71a440cd23
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/CollectionUtilTest.java
@@ -0,0 +1,572 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.util.CollectionUtil;
+import org.apache.hugegraph.testutil.Assert;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+public class CollectionUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testToSet() {
+        Assert.assertThrows(NullPointerException.class, () -> {
+            CollectionUtil.toSet(null);
+        });
+
+        Object array1 = new Integer[]{1, 2, 3};
+        Assert.assertEquals(ImmutableSet.of(1, 2, 3),
+                            CollectionUtil.toSet(array1));
+
+        Object array2 = new String[]{"1", "2", "3"};
+        Assert.assertEquals(ImmutableSet.of("1", "2", "3"),
+                            CollectionUtil.toSet(array2));
+
+        Set<Integer> set = ImmutableSet.of(1, 2, 3);
+        Assert.assertEquals(ImmutableSet.of(1, 2, 3),
+                            CollectionUtil.toSet(set));
+
+        List<Integer> list = ImmutableList.of(1, 2, 3);
+        Assert.assertEquals(ImmutableSet.of(1, 2, 3),
+                            CollectionUtil.toSet(list));
+
+        Assert.assertEquals(ImmutableSet.of(1), CollectionUtil.toSet(1));
+    }
+
+    @Test
+    public void testToList() {
+        Assert.assertThrows(NullPointerException.class, () -> {
+            CollectionUtil.toList(null);
+        });
+
+        Object array1 = new Integer[]{1, 2, 3};
+        Assert.assertEquals(ImmutableList.of(1, 2, 3),
+                            CollectionUtil.toList(array1));
+
+        Object array2 = new String[]{"1", "2", "3"};
+        Assert.assertEquals(ImmutableList.of("1", "2", "3"),
+                            CollectionUtil.toList(array2));
+
+        Set<Integer> set = ImmutableSet.of(1, 2, 3);
+        Assert.assertEquals(ImmutableList.of(1, 2, 3),
+                            CollectionUtil.toList(set));
+
+        List<Integer> list = ImmutableList.of(1, 2, 3);
+        Assert.assertEquals(ImmutableList.of(1, 2, 3),
+                            CollectionUtil.toList(list));
+
+        Assert.assertEquals(ImmutableList.of("123"),
+                            CollectionUtil.toList("123"));
+    }
+
+    @Test
+    public void testPrefixOf() {
+        List<Integer> list = ImmutableList.of(1, 2, 3);
+
+        List<Integer> list1 = ImmutableList.of();
+        Assert.assertTrue(CollectionUtil.prefixOf(list1, list));
+
+        List<Integer> list2 = ImmutableList.of(1, 2);
+        Assert.assertTrue(CollectionUtil.prefixOf(list2, list));
+
+        List<Integer> list3 = ImmutableList.of(1, 2, 3);
+        Assert.assertTrue(CollectionUtil.prefixOf(list3, list));
+
+        List<Integer> list4 = ImmutableList.of(1, 2, 3, 4);
+        Assert.assertFalse(CollectionUtil.prefixOf(list4, list));
+
+        List<Integer> list5 = ImmutableList.of(1, 2, 4);
+        Assert.assertFalse(CollectionUtil.prefixOf(list5, list));
+
+        List<Integer> list6 = Arrays.asList(1, 2, null);
+        Assert.assertFalse(CollectionUtil.prefixOf(list6, list));
+    }
+
+    @Test
+    public void testRandomSet() {
+        Set<Integer> set = CollectionUtil.randomSet(0, 100, 10);
+        for (int i : set) {
+            Assert.assertTrue(0 <= i && i < 100);
+        }
+
+        // invalid min
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            CollectionUtil.randomSet(200, 100, 10);
+        });
+
+        // invalid count = 0
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            CollectionUtil.randomSet(1, 100, 0);
+        });
+
+        // invalid count > max - min
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            CollectionUtil.randomSet(1, 100, 100);
+        });
+    }
+
+    @Test
+    public void testAllUnique() {
+        List<Integer> list = ImmutableList.of();
+        Assert.assertTrue(CollectionUtil.allUnique(list));
+
+        list = ImmutableList.of(1, 2, 3, 2, 3);
+        Assert.assertFalse(CollectionUtil.allUnique(list));
+
+        list = ImmutableList.of(1, 2, 3, 4, 5);
+        Assert.assertTrue(CollectionUtil.allUnique(list));
+
+        list = ImmutableList.of(1, 1, 1, 1, 1);
+        Assert.assertFalse(CollectionUtil.allUnique(list));
+    }
+
+    @Test
+    public void testSubSet() {
+        Set<Integer> originSet = ImmutableSet.of(1, 2, 3, 4, 5);
+
+        Set<Integer> subSet = CollectionUtil.subSet(originSet, 1, 1);
+        Assert.assertEquals(ImmutableSet.of(), subSet);
+
+        subSet = CollectionUtil.subSet(originSet, 2, 4);
+        Assert.assertEquals(ImmutableSet.of(3, 4), subSet);
+
+        subSet = CollectionUtil.subSet(originSet, 2, 5);
+        Assert.assertEquals(ImmutableSet.of(3, 4, 5), subSet);
+
+        subSet = CollectionUtil.subSet(originSet, 0, 5);
+        Assert.assertEquals(ImmutableSet.of(1, 2, 3, 4, 5), subSet);
+
+        subSet = CollectionUtil.subSet(originSet, 2, -1);
+        Assert.assertEquals(ImmutableSet.of(3, 4, 5), subSet);
+
+        subSet = CollectionUtil.subSet(originSet, 2, -100);
+        Assert.assertEquals(ImmutableSet.of(3, 4, 5), subSet);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            CollectionUtil.subSet(originSet, 2, 1);
+        }, e -> {
+            Assert.assertContains("Invalid to parameter ", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            CollectionUtil.subSet(originSet, -1, 2);
+        }, e -> {
+            Assert.assertContains("Invalid from parameter ", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            CollectionUtil.subSet(originSet, -10, 2);
+        }, e -> {
+            Assert.assertContains("Invalid from parameter ", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testUnion() {
+        List<Integer> first = new ArrayList<>();
+        first.add(1);
+        first.add(2);
+
+        Set<Integer> second = new HashSet<>();
+        second.add(1);
+        second.add(3);
+
+        Set<Integer> results = CollectionUtil.union(first, second);
+        Assert.assertEquals(3, results.size());
+    }
+
+    @Test
+    public void testIntersectWithoutModifying() {
+        List<Integer> first = new ArrayList<>();
+        first.add(1);
+        first.add(2);
+        first.add(3);
+
+        List<Integer> second = new ArrayList<>();
+        second.add(4);
+        second.add(5);
+
+        Collection<Integer> results = CollectionUtil.intersect(first, second);
+        Assert.assertEquals(0, results.size());
+        Assert.assertEquals(3, first.size());
+
+        second.add(3);
+        results = CollectionUtil.intersect(first, second);
+        Assert.assertEquals(1, results.size());
+        Assert.assertEquals(3, first.size());
+
+        second.add(1);
+        second.add(2);
+        results = CollectionUtil.intersect(first, second);
+        Assert.assertEquals(3, results.size());
+        Assert.assertEquals(3, first.size());
+
+        Set<Integer> set = new HashSet<>();
+        set.add(1);
+        set.add(3);
+        set.add(6);
+
+        results = CollectionUtil.intersect(set, second);
+        Assert.assertInstanceOf(HashSet.class, results);
+        Assert.assertEquals(2, results.size());
+        Assert.assertEquals(3, set.size());
+
+        set = new LinkedHashSet<>();
+        set.add(1);
+        set.add(2);
+        set.add(6);
+
+        results = CollectionUtil.intersect(set, second);
+        Assert.assertInstanceOf(LinkedHashSet.class, results);
+        Assert.assertEquals(2, results.size());
+        Assert.assertEquals(3, set.size());
+    }
+
+    @Test
+    public void testIntersectWithModifying() {
+        Set<Integer> first = new HashSet<>();
+        first.add(1);
+        first.add(2);
+        first.add(3);
+
+        Set<Integer> second = new HashSet<>();
+        second.add(1);
+        second.add(2);
+        second.add(3);
+
+        Collection<Integer> results = CollectionUtil.intersectWithModify(
+                                                     first, second);
+        Assert.assertEquals(3, results.size());
+        Assert.assertEquals(3, first.size());
+
+        // The second set has "1", "2"
+        second.remove(3);
+        results = CollectionUtil.intersectWithModify(first, second);
+        Assert.assertEquals(2, results.size());
+        Assert.assertEquals(2, first.size());
+
+        // The second set is empty
+        second.remove(1);
+        second.remove(2);
+        results = CollectionUtil.intersectWithModify(first, second);
+        Assert.assertEquals(0, results.size());
+        Assert.assertEquals(0, first.size());
+    }
+
+    @Test
+    public void testHasIntersectionBetweenListAndSet() {
+        List<Integer> first = new ArrayList<>();
+        first.add(1);
+        first.add(2);
+        first.add(3);
+
+        Set<Integer> second = new HashSet<>();
+        Assert.assertFalse(CollectionUtil.hasIntersection(first, second));
+
+        second.add(4);
+        Assert.assertFalse(CollectionUtil.hasIntersection(first, second));
+
+        second.add(1);
+        Assert.assertTrue(CollectionUtil.hasIntersection(first, second));
+
+        second = new HashSet<>();
+        second.add(4);
+        second.add(5);
+        second.add(6);
+        second.add(7);
+        Assert.assertFalse(CollectionUtil.hasIntersection(first, second));
+
+        second.add(3);
+        Assert.assertTrue(CollectionUtil.hasIntersection(first, second));
+    }
+
+    @Test
+    public void testHasIntersectionBetweenSetAndSet() {
+        Set<Integer> first = new HashSet<>();
+        first.add(1);
+        first.add(2);
+        first.add(3);
+
+        Set<Integer> second = new HashSet<>();
+        Assert.assertFalse(CollectionUtil.hasIntersection(first, second));
+
+        second.add(4);
+        Assert.assertFalse(CollectionUtil.hasIntersection(first, second));
+
+        second.add(1);
+        Assert.assertTrue(CollectionUtil.hasIntersection(first, second));
+
+        second = new HashSet<>();
+        second.add(4);
+        second.add(5);
+        second.add(6);
+        second.add(7);
+        Assert.assertFalse(CollectionUtil.hasIntersection(first, second));
+
+        second.add(3);
+        Assert.assertTrue(CollectionUtil.hasIntersection(first, second));
+    }
+
+    @Test
+    public void testMapSortByStringKey() {
+        Map<String, Integer> unordered = new HashMap<>();
+        unordered.put("D", 1);
+        unordered.put("B", 2);
+        unordered.put("E", 3);
+        unordered.put("A", 4);
+        unordered.put("C", 5);
+
+        Map<String, Integer> incrOrdered = CollectionUtil.sortByKey(unordered,
+                                                                    true);
+        Assert.assertEquals(ImmutableList.of("A", "B", "C", "D", "E"),
+                            ImmutableList.copyOf(incrOrdered.keySet()));
+
+        Map<String, Integer> decrOrdered = CollectionUtil.sortByKey(unordered,
+                                                                    false);
+        Assert.assertEquals(ImmutableList.of("E", "D", "C", "B", "A"),
+                            ImmutableList.copyOf(decrOrdered.keySet()));
+    }
+
+    @Test
+    public void testMapSortByIntegerKey() {
+        Map<Integer, String> unordered = new HashMap<>();
+        unordered.put(4, "A");
+        unordered.put(2, "B");
+        unordered.put(5, "C");
+        unordered.put(1, "D");
+        unordered.put(3, "E");
+
+        Map<Integer, String> incrOrdered = CollectionUtil.sortByKey(unordered,
+                                                                    true);
+        Assert.assertEquals(ImmutableList.of(1, 2, 3, 4, 5),
+                            ImmutableList.copyOf(incrOrdered.keySet()));
+
+        Map<Integer, String> decrOrdered = CollectionUtil.sortByKey(unordered,
+                                                                    false);
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 2, 1),
+                            ImmutableList.copyOf(decrOrdered.keySet()));
+    }
+
+    @Test
+    public void testMapSortByIntegerValue() {
+        Map<String, Integer> unordered = new HashMap<>();
+        unordered.put("A", 4);
+        unordered.put("B", 2);
+        unordered.put("C", 5);
+        unordered.put("D", 1);
+        unordered.put("E", 3);
+
+        Map<String, Integer> incrOrdered = CollectionUtil.sortByValue(unordered,
+                                                                      true);
+        Assert.assertEquals(ImmutableList.of(1, 2, 3, 4, 5),
+                            ImmutableList.copyOf(incrOrdered.values()));
+
+        Map<String, Integer> decrOrdered = CollectionUtil.sortByValue(unordered,
+                                                                      false);
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 2, 1),
+                            ImmutableList.copyOf(decrOrdered.values()));
+    }
+
+    @Test
+    public void testMapSortByStringValue() {
+        Map<Integer, String> unordered = new HashMap<>();
+        unordered.put(1, "D");
+        unordered.put(2, "B");
+        unordered.put(3, "E");
+        unordered.put(4, "A");
+        unordered.put(5, "C");
+
+        Map<Integer, String> incrOrdered = CollectionUtil.sortByValue(unordered,
+                                                                      true);
+        Assert.assertEquals(ImmutableList.of("A", "B", "C", "D", "E"),
+                            ImmutableList.copyOf(incrOrdered.values()));
+
+        Map<Integer, String> decrOrdered = CollectionUtil.sortByValue(unordered,
+                                                                      false);
+        Assert.assertEquals(ImmutableList.of("E", "D", "C", "B", "A"),
+                            ImmutableList.copyOf(decrOrdered.values()));
+    }
+
+    @Test
+    public void testCrossCombineParts() {
+        List<List<Object>> parts;
+
+        parts = ImmutableList.of(ImmutableList.of("a", "b"),
+                                 ImmutableList.of(1, 2),
+                                 ImmutableList.of('x', 'y'));
+        List<List<Object>> combs = CollectionUtil.crossCombineParts(parts);
+        Assert.assertEquals(8, combs.size());
+        Assert.assertEquals(ImmutableList.of(
+                            ImmutableList.of("a", "b", 1, 2, 'x', 'y'),
+                            ImmutableList.of("a", "b", 1, 2, 'y', 'x'),
+                            ImmutableList.of("a", "b", 2, 1, 'x', 'y'),
+                            ImmutableList.of("a", "b", 2, 1, 'y', 'x'),
+                            ImmutableList.of("b", "a", 1, 2, 'x', 'y'),
+                            ImmutableList.of("b", "a", 1, 2, 'y', 'x'),
+                            ImmutableList.of("b", "a", 2, 1, 'x', 'y'),
+                            ImmutableList.of("b", "a", 2, 1, 'y', 'x')),
+                            combs);
+
+        parts = ImmutableList.of(ImmutableList.of("a", "b", "c"),
+                                 ImmutableList.of(1, 2),
+                                 ImmutableList.of('x', 'y'));
+        Assert.assertEquals(24,
+                            CollectionUtil.crossCombineParts(parts).size());
+
+        parts = ImmutableList.of(ImmutableList.of("a", "b", "c"),
+                                 ImmutableList.of(1, 2, 3),
+                                 ImmutableList.of('x', 'y'));
+        Assert.assertEquals(72,
+                            CollectionUtil.crossCombineParts(parts).size());
+
+        parts = ImmutableList.of(ImmutableList.of("a", "b", "c"),
+                                 ImmutableList.of(1, 2, 3),
+                                 ImmutableList.of('x', 'y', 'z'));
+        Assert.assertEquals(216,
+                            CollectionUtil.crossCombineParts(parts).size());
+    }
+
+    @Test
+    public void testCnm() {
+        List<Integer> list = ImmutableList.of(1, 2, 3, 4, 5);
+
+        // Test C(5, 2) with all combinations
+        List<List<Integer>> tuples = new ArrayList<>();
+        boolean found;
+        found = CollectionUtil.cnm(list, list.size(), 2, tuple -> {
+            tuples.add(new ArrayList<>(tuple));
+            return false;
+        });
+        Assert.assertFalse(found);
+        Assert.assertEquals(10, tuples.size());
+
+        Assert.assertEquals(10,
+                            CollectionUtil.cnm(list, list.size(), 2).size());
+
+        // Test C(5, 2) with one combination
+        tuples.clear();
+        found = CollectionUtil.cnm(list, list.size(), 2, tuple -> {
+            if (tuple.equals(ImmutableList.of(2, 3))) {
+                tuples.add(new ArrayList<>(tuple));
+                return true;
+            }
+            return false;
+        });
+        Assert.assertTrue(found);
+        Assert.assertEquals(1, tuples.size());
+        Assert.assertEquals(ImmutableList.of(2, 3), tuples.get(0));
+
+        // Test C(5, 3) with all combinations
+        List<List<Integer>> triples = new ArrayList<>();
+        found = CollectionUtil.cnm(list, list.size(), 3, triple -> {
+            triples.add(new ArrayList<>(triple));
+            return false;
+        });
+        Assert.assertFalse(found);
+        Assert.assertEquals(10, triples.size());
+
+        Assert.assertEquals(10,
+                            CollectionUtil.cnm(list, list.size(), 3).size());
+
+        // Test C(5, 3) with one combination
+        triples.clear();
+        found = CollectionUtil.cnm(list, list.size(), 3, triple -> {
+            if (triple.equals(ImmutableList.of(2, 3, 5))) {
+                triples.add(new ArrayList<>(triple));
+                return true;
+            }
+            return false;
+        });
+        Assert.assertTrue(found);
+        Assert.assertEquals(1, triples.size());
+        Assert.assertEquals(ImmutableList.of(2, 3, 5), triples.get(0));
+    }
+
+    @Test
+    public void testAnm() {
+        List<Integer> list = ImmutableList.of(1, 2, 3, 4, 5);
+
+        // Test A(5, 5) with all combinations
+        Assert.assertEquals(120, CollectionUtil.anm(list).size());
+
+        // Test A(5, 2) with all combinations
+        List<List<Integer>> tuples = new ArrayList<>();
+        boolean found;
+        found = CollectionUtil.anm(list, list.size(), 2, tuple -> {
+            tuples.add(new ArrayList<>(tuple));
+            return false;
+        });
+        Assert.assertFalse(found);
+        Assert.assertEquals(20, tuples.size());
+
+        Assert.assertEquals(20,
+                            CollectionUtil.anm(list, list.size(), 2).size());
+
+        // Test A(5, 2) with one combination
+        tuples.clear();
+        found = CollectionUtil.anm(list, list.size(), 2, tuple -> {
+            if (tuple.equals(ImmutableList.of(2, 3))) {
+                tuples.add(new ArrayList<>(tuple));
+                return true;
+            }
+            return false;
+        });
+        Assert.assertTrue(found);
+        Assert.assertEquals(1, tuples.size());
+        Assert.assertEquals(ImmutableList.of(2, 3), tuples.get(0));
+
+        // Test A(5, 3) with all combinations
+        List<List<Integer>> triples = new ArrayList<>();
+        found = CollectionUtil.anm(list, list.size(), 3, triple -> {
+            triples.add(new ArrayList<>(triple));
+            return false;
+        });
+        Assert.assertFalse(found);
+        Assert.assertEquals(60, triples.size());
+
+        Assert.assertEquals(60,
+                            CollectionUtil.anm(list, list.size(), 3).size());
+
+        // Test A(5, 3) with one combination
+        triples.clear();
+        found = CollectionUtil.anm(list, list.size(), 3, triple -> {
+            if (triple.equals(ImmutableList.of(2, 3, 5))) {
+                triples.add(new ArrayList<>(triple));
+                return true;
+            }
+            return false;
+        });
+        Assert.assertTrue(found);
+        Assert.assertEquals(1, triples.size());
+        Assert.assertEquals(ImmutableList.of(2, 3, 5), triples.get(0));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/DateUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/DateUtilTest.java
new file mode 100644
index 0000000000..7c51406b36
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/DateUtilTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.util.DateUtil;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class DateUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testParse() {
+        Date date1 = DateUtil.parse("2020-06-12 12:00:00");
+        Date date2 = DateUtil.parse("2020-06-13");
+        Assert.assertNotEquals(date1, date2);
+        Assert.assertTrue(date1.before(date2));
+
+        Date date3 = DateUtil.parse("2020-06-12");
+        Date date4 = DateUtil.parse("2020-06-12 00:00:00.00");
+        Assert.assertEquals(date3, date4);
+
+        Date date5 = DateUtil.parse("2020-06-12 00:00:00.001");
+        Assert.assertNotEquals(date3, date5);
+        Assert.assertTrue(date3.before(date5));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            DateUtil.parse("2018-");
+        }, e -> {
+            Assert.assertContains("Expected date format is:", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            DateUtil.parse("2018-15-07 12:00:00.f");
+        }, e -> {
+            Assert.assertContains("Expected date format is:", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            DateUtil.parse("2018-15-07 12:00:00");
+        }, e -> {
+            Assert.assertContains("Value 15 for monthOfYear must be " +
+                                  "in the range [1,12]", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testNow() {
+        Date date1 = DateUtil.now();
+        try {
+            Thread.sleep(100);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        Date date2 = DateUtil.now();
+        Assert.assertTrue(date1.before(date2));
+    }
+
+    @Test
+    public void testParseCornerDateValue() throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        int threadCount = 10;
+        List<Thread> threads = new ArrayList<>(threadCount);
+        AtomicInteger errorCount = new AtomicInteger(0);
+        for (int t = 0; t < threadCount; t++) {
+            Thread thread = new Thread(() -> {
+                try {
+                    latch.await();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+                try {
+                    Assert.assertEquals(new Date(-62167248343000L),
+                                        DateUtil.parse("0", "yyyy"));
+                } catch (Exception e) {
+                    errorCount.incrementAndGet();
+                }
+            });
+            threads.add(thread);
+        }
+
+        for (Thread thread : threads) {
+            thread.start();
+        }
+        latch.countDown();
+        for (Thread thread : threads) {
+            thread.join();
+        }
+
+        Assert.assertEquals(0, errorCount.get());
+    }
+
+    @Test
+    public void testToPattern() {
+        Object pattern = DateUtil.toPattern("yyyyMMdd HH:mm:ss.SSS");
+        Assert.assertEquals("yyyyMMdd HH:mm:ss.SSS", pattern);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            DateUtil.toPattern("iyyyyMMdd");
+        }, e -> {
+            Assert.assertContains("Illegal pattern component: i", e.getMessage());
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/EcheckTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/EcheckTest.java
new file mode 100644
index 0000000000..c87bbf6271
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/EcheckTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+public class EcheckTest extends BaseUnitTest {
+
+    @Test
+    public void testCheckNotNull() {
+        E.checkNotNull(0, "test");
+        E.checkNotNull(new Object(), "test");
+        E.checkNotNull("1", "test");
+        E.checkNotNull(ImmutableList.of(), "test");
+
+        Assert.assertThrows(NullPointerException.class, () -> {
+            E.checkNotNull(null, "test");
+        }, e -> {
+            Assert.assertContains("The 'test' can't be null", e.getMessage());
+        });
+
+        Assert.assertThrows(NullPointerException.class, () -> {
+            E.checkNotNull(null, "test2");
+        }, e -> {
+            Assert.assertContains("The 'test2' can't be null", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testCheckNotNullWithOwner() {
+        E.checkNotNull(0, "test", "obj");
+        E.checkNotNull(new Object(), "test", "obj");
+        E.checkNotNull("1", "test", "obj");
+        E.checkNotNull(ImmutableList.of(), "test", "obj");
+
+        Assert.assertThrows(NullPointerException.class, () -> {
+            E.checkNotNull(null, "test", "obj");
+        }, e -> {
+            Assert.assertContains("The 'test' of 'obj' can't be null",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(NullPointerException.class, () -> {
+            E.checkNotNull(null, "test2", "obj2");
+        }, e -> {
+            Assert.assertContains("The 'test2' of 'obj2' can't be null",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testCheckNotEmpty() {
+        E.checkNotEmpty(ImmutableList.of(0), "test");
+        E.checkNotEmpty(ImmutableList.of(""), "test");
+        E.checkNotEmpty(ImmutableList.of(1, 2), "test");
+        E.checkNotEmpty(ImmutableSet.of(0), "test");
+        E.checkNotEmpty(ImmutableSet.of(""), "test");
+        E.checkNotEmpty(ImmutableSet.of("1", "2"), "test");
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            E.checkNotEmpty(ImmutableList.of(), "test");
+        }, e -> {
+            Assert.assertContains("The 'test' can't be empty", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            E.checkNotEmpty(ImmutableSet.of(), "test2");
+        }, e -> {
+            Assert.assertContains("The 'test2' can't be empty", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testCheckNotEmptyWithOwner() {
+        E.checkNotEmpty(ImmutableList.of(0), "test", "obj");
+        E.checkNotEmpty(ImmutableList.of(""), "test", "obj");
+        E.checkNotEmpty(ImmutableList.of(1, 2), "test", "obj");
+        E.checkNotEmpty(ImmutableSet.of(0), "test", "obj");
+        E.checkNotEmpty(ImmutableSet.of(""), "test", "obj");
+        E.checkNotEmpty(ImmutableSet.of("1", "2"), "test", "obj");
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            E.checkNotEmpty(ImmutableList.of(), "test", "obj");
+        }, e -> {
+            Assert.assertContains("The 'test' of 'obj' can't be empty",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            E.checkNotEmpty(ImmutableSet.of(), "test2", "obj2");
+        }, e -> {
+            Assert.assertContains("The 'test2' of 'obj2' can't be empty",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testCheckArgument() {
+        E.checkArgument(true, "test");
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            E.checkArgument(false, "Invalid parameter %s", 123);
+        }, e -> {
+            Assert.assertContains("Invalid parameter 123", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testCheckArgumentNotNull() {
+        E.checkArgumentNotNull("", "test");
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            E.checkArgumentNotNull(null, "Invalid parameter %s", "null");
+        }, e -> {
+            Assert.assertContains("Invalid parameter null", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testCheckState() {
+        E.checkState(true, "test");
+
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            E.checkState(false, "Invalid state '%s'", "FAIL");
+        }, e -> {
+            Assert.assertContains("Invalid state 'FAIL'", e.getMessage());
+        });
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/HashUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/HashUtilTest.java
new file mode 100644
index 0000000000..3efde1b55d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/HashUtilTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.util.Bytes;
+import org.apache.hugegraph.util.HashUtil;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class HashUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testHash() {
+        // hash 32 bits (4 bytes)
+
+        String h = HashUtil.hash("");
+        Assert.assertEquals(8, h.length());
+        Assert.assertEquals("00000000", h);
+
+        h = HashUtil.hash("q");
+        Assert.assertEquals(8, h.length());
+        Assert.assertEquals("e80982ff", h);
+
+        h = HashUtil.hash("qq");
+        Assert.assertEquals(8, h.length());
+        Assert.assertEquals("252ef918", h);
+
+        h = HashUtil.hash("qwertyuiop[]asdfghjkl;'zxcvbnm,./");
+        Assert.assertEquals(8, h.length());
+        Assert.assertEquals("fcc1f9fa", h);
+    }
+
+    @Test
+    public void testHashWithBytes() {
+        // hash 32 bits (4 bytes)
+
+        byte[] h = HashUtil.hash(b(""));
+        Assert.assertEquals(4, h.length);
+        Assert.assertEquals("00000000", hex(h));
+
+        h = HashUtil.hash(b("q"));
+        Assert.assertEquals(4, h.length);
+        Assert.assertEquals("e80982ff", hex(h));
+
+        h = HashUtil.hash(b("qq"));
+        Assert.assertEquals(4, h.length);
+        Assert.assertEquals("252ef918", hex(h));
+
+        h = HashUtil.hash(b("qwertyuiop[]asdfghjkl;'zxcvbnm,./"));
+        Assert.assertEquals(4, h.length);
+        Assert.assertEquals("fcc1f9fa", hex(h));
+    }
+
+    @Test
+    public void testHash128() {
+        // hash 128 bits (16 bytes)
+
+        String h = HashUtil.hash128("");
+        Assert.assertEquals(32, h.length());
+        Assert.assertEquals("00000000000000000000000000000000", h);
+
+        h = HashUtil.hash128("q");
+        Assert.assertEquals(32, h.length());
+        Assert.assertEquals("b1aba139b20c3ebcf667a14f41c7d17c", h);
+
+        h = HashUtil.hash128("qq");
+        Assert.assertEquals(32, h.length());
+        Assert.assertEquals("2dbabe8ac8d8ce9eedc4b97add0f7c7c", h);
+
+        h = HashUtil.hash128("qwertyuiop[]asdfghjkl;'zxcvbnm,./");
+        Assert.assertEquals(32, h.length());
+        Assert.assertEquals("49780e7800e613230520ed7b1116fef5", h);
+    }
+
+    @Test
+    public void testHash128WithBytes() {
+        // hash 128 bits (16 bytes)
+
+        byte[] h = HashUtil.hash128(b(""));
+        Assert.assertEquals(16, h.length);
+        Assert.assertEquals("00000000000000000000000000000000", hex(h));
+
+        h = HashUtil.hash128(b("q"));
+        Assert.assertEquals(16, h.length);
+        Assert.assertEquals("b1aba139b20c3ebcf667a14f41c7d17c", hex(h));
+
+        h = HashUtil.hash128(b("qq"));
+        Assert.assertEquals(16, h.length);
+        Assert.assertEquals("2dbabe8ac8d8ce9eedc4b97add0f7c7c", hex(h));
+
+        h = HashUtil.hash128(b("qwertyuiop[]asdfghjkl;'zxcvbnm,./"));
+        Assert.assertEquals(16, h.length);
+        Assert.assertEquals("49780e7800e613230520ed7b1116fef5", hex(h));
+    }
+
+    private static byte[] b(String string) {
+        return string.getBytes();
+    }
+
+    private static String hex(byte[] bytes) {
+        return Bytes.toHex(bytes);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/InsertionOrderUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/InsertionOrderUtilTest.java
new file mode 100644
index 0000000000..b2776a7d7f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/InsertionOrderUtilTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.util.InsertionOrderUtil;
+import org.apache.hugegraph.testutil.Assert;
+import com.google.common.collect.ImmutableList;
+
+public class InsertionOrderUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testSet() {
+        Set<Integer> set = InsertionOrderUtil.newSet();
+        set.add(4);
+        set.add(2);
+        set.add(5);
+        set.add(1);
+        set.add(3);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(set));
+    }
+
+    @Test
+    public void testSetWithInitialCapacity() {
+        Set<Integer> set = InsertionOrderUtil.newSet(3);
+        set.add(4);
+        set.add(2);
+        set.add(5);
+        set.add(1);
+        set.add(3);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(set));
+    }
+
+    @Test
+    public void testSetCopy() {
+        Set<Integer> set = InsertionOrderUtil.newSet();
+        set.add(4);
+        set.add(2);
+        set.add(5);
+        set.add(1);
+        set.add(3);
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(set));
+
+        Set<Integer> set2 = InsertionOrderUtil.newSet(set);
+        set2.add(6);
+        set2.add(1);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3, 6),
+                            ImmutableList.copyOf(set2));
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(set));
+    }
+
+    @Test
+    public void testList() {
+        List<Integer> list = InsertionOrderUtil.newList();
+        list.add(4);
+        list.add(2);
+        list.add(5);
+        list.add(1);
+        list.add(3);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(list));
+    }
+
+    @Test
+    public void testListWithInitialCapacity() {
+        List<Integer> list = InsertionOrderUtil.newList(3);
+        list.add(4);
+        list.add(2);
+        list.add(5);
+        list.add(1);
+        list.add(3);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(list));
+    }
+
+    @Test
+    public void testListCopy() {
+        List<Integer> list = InsertionOrderUtil.newList();
+        list.add(4);
+        list.add(2);
+        list.add(5);
+        list.add(1);
+        list.add(3);
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(list));
+
+        List<Integer> list2 = InsertionOrderUtil.newList(list);
+        list2.add(6);
+        list2.add(1);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3, 6, 1),
+                            ImmutableList.copyOf(list2));
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(list));
+    }
+
+    @Test
+    public void testMap() {
+        Map<Integer, Integer> map = InsertionOrderUtil.newMap();
+        map.put(4, 4);
+        map.put(2, 2);
+        map.put(5, 5);
+        map.put(1, 1);
+        map.put(3, 3);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testMapWithInitialCapacity() {
+        Map<Integer, Integer> map = InsertionOrderUtil.newMap(3);
+        map.put(4, 4);
+        map.put(2, 2);
+        map.put(5, 5);
+        map.put(1, 1);
+        map.put(3, 3);
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testMapCopy() {
+        Map<Integer, Integer> map = InsertionOrderUtil.newMap(3);
+        map.put(4, 4);
+        map.put(2, 2);
+        map.put(5, 5);
+        map.put(1, 1);
+        map.put(3, 3);
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(map.keySet()));
+
+        Map<Integer, Integer> map2 = InsertionOrderUtil.newMap(map);
+        map2.put(6, 6);
+        map2.put(1, 7);
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3, 6),
+                            ImmutableList.copyOf(map2.keySet()));
+
+        Assert.assertEquals(ImmutableList.of(4, 2, 5, 1, 3),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/LogTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/LogTest.java
new file mode 100644
index 0000000000..9ab55c8fd3
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/LogTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.util.Log;
+import org.apache.hugegraph.testutil.Assert;
+
+public class LogTest extends BaseUnitTest {
+
+    @Test
+    public void testLog() {
+        Logger log1 = Log.logger(LogTest.class);
+        Logger log2 = Log.logger("org.apache.hugegraph.unit.util.LogTest");
+        Logger log3 = Log.logger("test");
+
+        Assert.assertEquals(log1, log2);
+        Assert.assertNotEquals(log1, log3);
+
+        log1.info("Info: testLog({})", LogTest.class);
+        log2.info("Info: testLog({})", "org.apache.hugegraph.unit.util.LogTest");
+        log3.info("Info: testLog({})", "test");
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/LongEncodingTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/LongEncodingTest.java
new file mode 100644
index 0000000000..8e822058c8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/LongEncodingTest.java
@@ -0,0 +1,684 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+import java.util.TimeZone;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.util.Bytes;
+import org.apache.hugegraph.util.LongEncoding;
+import org.apache.hugegraph.util.NumericUtil;
+import org.apache.hugegraph.testutil.Assert;
+
+public class LongEncodingTest extends BaseUnitTest {
+
+    @Test
+    public void testValidB64Char() {
+        Assert.assertTrue(LongEncoding.validB64Char('0'));
+        Assert.assertTrue(LongEncoding.validB64Char('1'));
+        Assert.assertTrue(LongEncoding.validB64Char('9'));
+        Assert.assertTrue(LongEncoding.validB64Char('A'));
+        Assert.assertTrue(LongEncoding.validB64Char('Z'));
+        Assert.assertTrue(LongEncoding.validB64Char('_'));
+        Assert.assertTrue(LongEncoding.validB64Char('a'));
+        Assert.assertTrue(LongEncoding.validB64Char('z'));
+        Assert.assertTrue(LongEncoding.validB64Char('~'));
+
+        Assert.assertFalse(LongEncoding.validB64Char('`'));
+        Assert.assertFalse(LongEncoding.validB64Char('!'));
+        Assert.assertFalse(LongEncoding.validB64Char('@'));
+        Assert.assertFalse(LongEncoding.validB64Char('#'));
+        Assert.assertFalse(LongEncoding.validB64Char('$'));
+        Assert.assertFalse(LongEncoding.validB64Char('%'));
+        Assert.assertFalse(LongEncoding.validB64Char('^'));
+        Assert.assertFalse(LongEncoding.validB64Char('&'));
+        Assert.assertFalse(LongEncoding.validB64Char('*'));
+        Assert.assertFalse(LongEncoding.validB64Char('('));
+        Assert.assertFalse(LongEncoding.validB64Char(')'));
+        Assert.assertFalse(LongEncoding.validB64Char('-'));
+        Assert.assertFalse(LongEncoding.validB64Char('+'));
+        Assert.assertFalse(LongEncoding.validB64Char('='));
+        Assert.assertFalse(LongEncoding.validB64Char('['));
+        Assert.assertFalse(LongEncoding.validB64Char(']'));
+        Assert.assertFalse(LongEncoding.validB64Char('{'));
+        Assert.assertFalse(LongEncoding.validB64Char('}'));
+        Assert.assertFalse(LongEncoding.validB64Char('|'));
+        Assert.assertFalse(LongEncoding.validB64Char('\\'));
+        Assert.assertFalse(LongEncoding.validB64Char(';'));
+        Assert.assertFalse(LongEncoding.validB64Char(':'));
+        Assert.assertFalse(LongEncoding.validB64Char('\''));
+        Assert.assertFalse(LongEncoding.validB64Char('\"'));
+        Assert.assertFalse(LongEncoding.validB64Char('<'));
+        Assert.assertFalse(LongEncoding.validB64Char(','));
+        Assert.assertFalse(LongEncoding.validB64Char('>'));
+        Assert.assertFalse(LongEncoding.validB64Char('.'));
+        Assert.assertFalse(LongEncoding.validB64Char('?'));
+        Assert.assertFalse(LongEncoding.validB64Char('/'));
+        Assert.assertFalse(LongEncoding.validB64Char('\t'));
+        Assert.assertFalse(LongEncoding.validB64Char('\b'));
+    }
+
+    @Test
+    public void testEncode() {
+        String val0 = LongEncoding.encodeB64(0);
+        Assert.assertEquals("0", val0);
+
+        String val1 = LongEncoding.encodeB64(1);
+        Assert.assertEquals("1", val1);
+
+        String val9 = LongEncoding.encodeB64(9);
+        Assert.assertEquals("9", val9);
+
+        String val10 = LongEncoding.encodeB64(10);
+        Assert.assertEquals("A", val10);
+
+        String val35 = LongEncoding.encodeB64(35);
+        Assert.assertEquals("Z", val35);
+
+        String val36 = LongEncoding.encodeB64(36);
+        Assert.assertEquals("_", val36);
+
+        String val37 = LongEncoding.encodeB64(37);
+        Assert.assertEquals("a", val37);
+
+        String val62 = LongEncoding.encodeB64(62);
+        Assert.assertEquals("z", val62);
+
+        String val63 = LongEncoding.encodeB64(63);
+        Assert.assertEquals("~", val63);
+    }
+
+    @Test
+    public void testEncodeWithMultiString() {
+        Assert.assertEquals("0", LongEncoding.encode(0L, "0123456789"));
+        Assert.assertEquals("1", LongEncoding.encode(1L, "0123456789"));
+        Assert.assertEquals("123", LongEncoding.encode(123L, "0123456789"));
+        Assert.assertEquals("13579", LongEncoding.encode(13579L, "0123456789"));
+        Assert.assertEquals("24680", LongEncoding.encode(24680L, "0123456789"));
+
+        String val64 = LongEncoding.encodeB64(64);
+        Assert.assertEquals("10", val64);
+
+        String val65 = LongEncoding.encodeB64(65);
+        Assert.assertEquals("11", val65);
+
+        String val99 = LongEncoding.encodeB64(99);
+        Assert.assertEquals("1Z", val99);
+
+        String val100 = LongEncoding.encodeB64(100);
+        Assert.assertEquals("1_", val100);
+
+        String val126 = LongEncoding.encodeB64(126);
+        Assert.assertEquals("1z", val126);
+
+        String val127 = LongEncoding.encodeB64(127);
+        Assert.assertEquals("1~", val127);
+
+        String val128 = LongEncoding.encodeB64(128);
+        Assert.assertEquals("20", val128);
+
+        String val200 = LongEncoding.encodeB64(200);
+        Assert.assertEquals("38", val200);
+
+        String val1000 = LongEncoding.encodeB64(1000);
+        Assert.assertEquals("Fd", val1000);
+
+        String val1234 = LongEncoding.encodeB64(1234);
+        Assert.assertEquals("JI", val1234);
+
+        String val10000 = LongEncoding.encodeB64(10000);
+        Assert.assertEquals("2SG", val10000);
+
+        String val12345 = LongEncoding.encodeB64(12345);
+        Assert.assertEquals("30u", val12345);
+
+        String val22345 = LongEncoding.encodeB64(22345);
+        Assert.assertEquals("5T9", val22345);
+
+        String val92345 = LongEncoding.encodeB64(92345);
+        Assert.assertEquals("MYu", val92345);
+
+        String val12345678 = LongEncoding.encodeB64(12345678);
+        Assert.assertEquals("k65E", val12345678);
+
+        String val112345678 = LongEncoding.encodeB64(112345678);
+        Assert.assertEquals("6h_9E", val112345678);
+
+        String valIntMax = LongEncoding.encodeB64(Integer.MAX_VALUE);
+        Assert.assertEquals("1~~~~~", valIntMax);
+
+        String valLongMax = LongEncoding.encodeB64(Long.MAX_VALUE);
+        Assert.assertEquals("7~~~~~~~~~~", valLongMax);
+    }
+
+    @Test
+    public void testEncodeWithError() {
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.encode(1, "");
+        }, e -> {
+            Assert.assertEquals("The symbols parameter can't be empty",
+                                e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.encode(-1, "");
+        }, e -> {
+            Assert.assertContains("Expected non-negative number",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.encodeB64(-1);
+        }, e -> {
+            Assert.assertContains("Expected non-negative number",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.encodeB64(Long.MIN_VALUE);
+        }, e -> {
+            Assert.assertContains("Expected non-negative number",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testDecode() {
+        long valEmpty = LongEncoding.decodeB64("");
+        Assert.assertEquals(0, valEmpty);
+
+        long val0 = LongEncoding.decodeB64("0");
+        Assert.assertEquals(0, val0);
+
+        long val1 = LongEncoding.decodeB64("1");
+        Assert.assertEquals(1, val1);
+
+        long val9 = LongEncoding.decodeB64("9");
+        Assert.assertEquals(9, val9);
+
+        long val10 = LongEncoding.decodeB64("A");
+        Assert.assertEquals(10, val10);
+
+        long val35 = LongEncoding.decodeB64("Z");
+        Assert.assertEquals(35, val35);
+
+        long val36 = LongEncoding.decodeB64("_");
+        Assert.assertEquals(36, val36);
+
+        long val37 = LongEncoding.decodeB64("a");
+        Assert.assertEquals(37, val37);
+
+        long val62 = LongEncoding.decodeB64("z");
+        Assert.assertEquals(62, val62);
+
+        long val63 = LongEncoding.decodeB64("~");
+        Assert.assertEquals(63, val63);
+    }
+
+    @Test
+    public void testDecodeWithMultiString() {
+        Assert.assertEquals(0L, LongEncoding.decode("0", "0123456789"));
+        Assert.assertEquals(1L, LongEncoding.decode("1", "0123456789"));
+        Assert.assertEquals(123L, LongEncoding.decode("123", "0123456789"));
+        Assert.assertEquals(13579L, LongEncoding.decode("13579", "0123456789"));
+        Assert.assertEquals(24680L, LongEncoding.decode("24680", "0123456789"));
+
+        long val64 = LongEncoding.decodeB64("10");
+        Assert.assertEquals(64, val64);
+
+        long val65 = LongEncoding.decodeB64("11");
+        Assert.assertEquals(65, val65);
+
+        long val99 = LongEncoding.decodeB64("1Z");
+        Assert.assertEquals(99, val99);
+
+        long val100 = LongEncoding.decodeB64("1_");
+        Assert.assertEquals(100, val100);
+
+        long val126 = LongEncoding.decodeB64("1z");
+        Assert.assertEquals(126, val126);
+
+        long val127 = LongEncoding.decodeB64("1~");
+        Assert.assertEquals(127, val127);
+
+        long val128 = LongEncoding.decodeB64("20");
+        Assert.assertEquals(128, val128);
+
+        long val200 = LongEncoding.decodeB64("38");
+        Assert.assertEquals(200, val200);
+
+        long val1000 = LongEncoding.decodeB64("Fd");
+        Assert.assertEquals(1000, val1000);
+
+        long val1234 = LongEncoding.decodeB64("JI");
+        Assert.assertEquals(1234, val1234);
+
+        long val10000 = LongEncoding.decodeB64("2SG");
+        Assert.assertEquals(10000, val10000);
+
+        long val12345 = LongEncoding.decodeB64("30u");
+        Assert.assertEquals(12345, val12345);
+
+        long val22345 = LongEncoding.decodeB64("5T9");
+        Assert.assertEquals(22345, val22345);
+
+        long val92345 = LongEncoding.decodeB64("MYu");
+        Assert.assertEquals(92345, val92345);
+
+        long val12345678 = LongEncoding.decodeB64("k65E");
+        Assert.assertEquals(12345678, val12345678);
+
+        long val112345678 = LongEncoding.decodeB64("6h_9E");
+        Assert.assertEquals(112345678, val112345678);
+
+        long valIntMax = LongEncoding.decodeB64("1~~~~~");
+        Assert.assertEquals(Integer.MAX_VALUE, valIntMax);
+
+        long valLongMax = LongEncoding.decodeB64("7~~~~~~~~~~");
+        Assert.assertEquals(Long.MAX_VALUE, valLongMax);
+    }
+
+    @Test
+    public void testDecodeWithError() {
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.decode("1", "");
+        }, e -> {
+            Assert.assertEquals("The symbols parameter can't be empty",
+                                e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.decode("1a", "0123456789");
+        }, e -> {
+            Assert.assertEquals("Can't decode symbol 'a' in string '1a'",
+                                e.getMessage());
+        });
+    }
+
+    @Test
+    public void testEncodeSignedB64() {
+        String val1234 = LongEncoding.encodeSignedB64(1234);
+        Assert.assertEquals("JI", val1234);
+
+        String val23 = LongEncoding.encodeSignedB64(23);
+        Assert.assertEquals("N", val23);
+
+        String valIntMax = LongEncoding.encodeSignedB64(Integer.MAX_VALUE);
+        Assert.assertEquals("1~~~~~", valIntMax);
+
+        String valLongMax = LongEncoding.encodeSignedB64(Long.MAX_VALUE);
+        Assert.assertEquals("7~~~~~~~~~~", valLongMax);
+
+        String val0 = LongEncoding.encodeSignedB64(0);
+        Assert.assertEquals("0", val0);
+
+        String valNeg1 = LongEncoding.encodeSignedB64(-1);
+        Assert.assertEquals("-1", valNeg1);
+
+        String valIntMinP1 = LongEncoding.encodeSignedB64(Integer.MIN_VALUE +
+                                                          1L);
+        Assert.assertEquals("-1~~~~~", valIntMinP1);
+
+        String valIntMin = LongEncoding.encodeSignedB64(Integer.MIN_VALUE);
+        Assert.assertEquals("-200000", valIntMin);
+
+        String valLongMinPlus1 = LongEncoding.encodeSignedB64(Long.MIN_VALUE +
+                                                              1L);
+        Assert.assertEquals("-7~~~~~~~~~~", valLongMinPlus1);
+
+        String valLongMin = LongEncoding.encodeSignedB64(Long.MIN_VALUE);
+        Assert.assertEquals("-80000000000", valLongMin);
+    }
+
+    @Test
+    public void testDecodeSignedB64() {
+        long val1234 = LongEncoding.decodeSignedB64("JI");
+        Assert.assertEquals(1234, val1234);
+
+        long val23 = LongEncoding.decodeSignedB64("N");
+        Assert.assertEquals(23, val23);
+
+        long valIntMax = LongEncoding.decodeSignedB64("1~~~~~");
+        Assert.assertEquals(Integer.MAX_VALUE, valIntMax);
+
+        long valLongMax = LongEncoding.decodeSignedB64("7~~~~~~~~~~");
+        Assert.assertEquals(Long.MAX_VALUE, valLongMax);
+
+        long val0 = LongEncoding.decodeSignedB64("0");
+        Assert.assertEquals(0, val0);
+
+        long valn1 = LongEncoding.decodeSignedB64("-1");
+        Assert.assertEquals(-1, valn1);
+
+        long valIntMinPlus1 = LongEncoding.decodeSignedB64("-1~~~~~");
+        Assert.assertEquals(Integer.MIN_VALUE + 1L, valIntMinPlus1);
+
+        long valIntMin = LongEncoding.decodeSignedB64("-200000");
+        Assert.assertEquals(Integer.MIN_VALUE, valIntMin);
+
+        long valLongMinPlus1 = LongEncoding.decodeSignedB64("-7~~~~~~~~~~");
+        Assert.assertEquals(Long.MIN_VALUE + 1L, valLongMinPlus1);
+
+        long valLongMin = LongEncoding.decodeSignedB64("-80000000000");
+        Assert.assertEquals(Long.MIN_VALUE, valLongMin);
+    }
+
+    @Test
+    public void testDecodeSignedB64Overflow() {
+        long valOverflow = LongEncoding.decodeSignedB64("80000000000");
+        Assert.assertEquals(Long.MIN_VALUE, valOverflow);
+
+        long valOverflow2 = LongEncoding.decodeSignedB64("80000000001");
+        Assert.assertEquals(Long.MIN_VALUE + 1L, valOverflow2);
+
+        long valOverflow3 = LongEncoding.decodeSignedB64("800000000001");
+        Assert.assertEquals(1L, valOverflow3);
+
+        long valOverflow4 = LongEncoding.decodeSignedB64("80000000000JI");
+        Assert.assertEquals(1234L, valOverflow4);
+
+        long valOverflow5 = LongEncoding.decodeSignedB64("80000000000N");
+        Assert.assertEquals(23L, valOverflow5);
+
+        long valOverflow6 = LongEncoding.decodeSignedB64("80000000000" +
+                                                         "7~~~~~~~~~~");
+        Assert.assertEquals(Long.MAX_VALUE, valOverflow6);
+    }
+
+    @Test
+    public void testEncodeSortable() {
+        String val1234 = LongEncoding.encodeSortable(1234);
+        Assert.assertEquals("2JI", val1234);
+
+        String val23 = LongEncoding.encodeSortable(23);
+        Assert.assertEquals("1N", val23);
+
+        String valIntMax = LongEncoding.encodeSortable(Integer.MAX_VALUE);
+        Assert.assertEquals("61~~~~~", valIntMax);
+
+        String valLongMax = LongEncoding.encodeSortable(Long.MAX_VALUE);
+        Assert.assertEquals("B7~~~~~~~~~~", valLongMax);
+
+        String val0 = LongEncoding.encodeSortable(0);
+        Assert.assertEquals("10", val0);
+
+        String valNeg1 = LongEncoding.encodeSortable(-1);
+        Assert.assertEquals("0B7~~~~~~~~~~", valNeg1);
+
+        String valIntMin = LongEncoding.encodeSortable(Integer.MIN_VALUE);
+        Assert.assertEquals("0B7~~~~z00000", valIntMin);
+
+        String valLongMin = LongEncoding.encodeSortable(Long.MIN_VALUE);
+        Assert.assertEquals("010", valLongMin);
+    }
+
+    @Test
+    public void testDecodeSortable() {
+        long val1234 = LongEncoding.decodeSortable("2JI");
+        Assert.assertEquals(1234, val1234);
+
+        long val23 = LongEncoding.decodeSortable("1N");
+        Assert.assertEquals(23, val23);
+
+        long valIntMax = LongEncoding.decodeSortable("61~~~~~");
+        Assert.assertEquals(Integer.MAX_VALUE, valIntMax);
+
+        long valLongMax = LongEncoding.decodeSortable("B7~~~~~~~~~~");
+        Assert.assertEquals(Long.MAX_VALUE, valLongMax);
+
+        long val0 = LongEncoding.decodeSortable("10");
+        Assert.assertEquals(0, val0);
+
+        long valn1 = LongEncoding.decodeSortable("0B7~~~~~~~~~~");
+        Assert.assertEquals(-1, valn1);
+
+        long valIntMin = LongEncoding.decodeSortable("0B7~~~~z00000");
+        Assert.assertEquals(Integer.MIN_VALUE, valIntMin);
+
+        long valLongMin = LongEncoding.decodeSortable("010");
+        Assert.assertEquals(Long.MIN_VALUE, valLongMin);
+    }
+
+    @Test
+    public void testDecodeIllegalSortable() {
+        // Length is 1, actual length is 0
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.decodeSortable("1");
+        });
+
+        // Length is 1, actual length is 2
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.decodeSortable("123");
+        });
+
+        // Length is 1, actual length is 0
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.decodeSortable("01");
+        });
+
+        // Length is 1, actual length is 2
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            LongEncoding.decodeSortable("0123");
+        });
+    }
+
+    @Test
+    public void testEncodeNumber() throws ParseException {
+        String l1234 = LongEncoding.encodeNumber(1234);
+        Assert.assertEquals("2JI", l1234);
+
+        String d1234 = LongEncoding.encodeNumber(1.234);
+        Assert.assertEquals("B3~okcR8i3aO", d1234);
+
+        String d21 = LongEncoding.encodeNumber(2.1);
+        Assert.assertEquals("B400oCoCoCoD", d21);
+
+        String dpi = LongEncoding.encodeNumber(3.1415926);
+        Assert.assertEquals("B4098ViD4iXA", dpi);
+
+        String fpi = LongEncoding.encodeNumber(3.1415926f);
+        Assert.assertEquals("610IG~Q", fpi);
+
+        String fn1 = LongEncoding.encodeNumber(-1.0f);
+        Assert.assertEquals("0B7~~~~~0V~~~", fn1);
+
+        String bMax = LongEncoding.encodeNumber(Byte.MAX_VALUE);
+        Assert.assertEquals("21~", bMax);
+
+        String bMin = LongEncoding.encodeNumber(Byte.MIN_VALUE);
+        Assert.assertEquals("0B7~~~~~~~~z0", bMin);
+
+        String sMax = LongEncoding.encodeNumber(Short.MAX_VALUE);
+        Assert.assertEquals("37~~", sMax);
+
+        String sMin = LongEncoding.encodeNumber(Short.MIN_VALUE);
+        Assert.assertEquals("0B7~~~~~~~t00", sMin);
+
+        String iMax = LongEncoding.encodeNumber(Integer.MAX_VALUE);
+        Assert.assertEquals("61~~~~~", iMax);
+
+        String iMin = LongEncoding.encodeNumber(Integer.MIN_VALUE);
+        Assert.assertEquals("0B7~~~~z00000", iMin);
+
+        String lMax = LongEncoding.encodeNumber(Long.MAX_VALUE);
+        Assert.assertEquals("B7~~~~~~~~~~", lMax);
+
+        String lMin = LongEncoding.encodeNumber(Long.MIN_VALUE);
+        Assert.assertEquals("010", lMin);
+
+        String fMax = LongEncoding.encodeNumber(Float.MAX_VALUE);
+        Assert.assertEquals("61~V~~~", fMax);
+
+        String fMin = LongEncoding.encodeNumber(Float.MIN_VALUE);
+        Assert.assertEquals("11", fMin);
+
+        String dMax = LongEncoding.encodeNumber(Double.MAX_VALUE);
+        Assert.assertEquals("B7~k~~~~~~~~", dMax);
+
+        String dMin = LongEncoding.encodeNumber(Double.MIN_VALUE);
+        Assert.assertEquals("11", dMin);
+
+        String bdLong = LongEncoding.encodeNumber(new BigDecimal("1234"));
+        Assert.assertEquals("2JI", bdLong);
+
+        String bdFLong = LongEncoding.encodeNumber(new BigDecimal("1234.00"));
+        Assert.assertEquals("2JI", bdFLong);
+
+        String bdDouble = LongEncoding.encodeNumber(new BigDecimal("1.234"));
+        Assert.assertEquals("B3~okcR8i3aO", bdDouble);
+
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        dateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+        Date time = dateFormat.parse("2018-12-18");
+        String date = LongEncoding.encodeNumber(time);
+        Assert.assertEquals("7MUxuK00", date);
+    }
+
+    @Test
+    public void testDecodeNumber() {
+        Number l1234 = LongEncoding.decodeNumber("2JI", Long.class);
+        Assert.assertEquals(1234L, l1234);
+
+        Number d1234 = LongEncoding.decodeNumber("B3~okcR8i3aO", Double.class);
+        Assert.assertEquals(1.234, d1234);
+
+        Number d21 = LongEncoding.decodeNumber("B400oCoCoCoD", Double.class);
+        Assert.assertEquals(2.1, d21);
+
+        Number dpi = LongEncoding.decodeNumber("B4098ViD4iXA", Double.class);
+        Assert.assertEquals(3.1415926, dpi);
+
+        Number fpi = LongEncoding.decodeNumber("610IG~Q", Float.class);
+        Assert.assertEquals(3.1415926f, fpi);
+
+        Number fn1 = LongEncoding.decodeNumber("0B7~~~~~0V~~~", Float.class);
+        Assert.assertEquals(-1.0f, fn1);
+
+        Number bMax = LongEncoding.decodeNumber("21~", Byte.class);
+        Assert.assertEquals(Byte.MAX_VALUE, bMax);
+
+        Number bMin = LongEncoding.decodeNumber("0B7~~~~~~~~z0", Byte.class);
+        Assert.assertEquals(Byte.MIN_VALUE, bMin);
+
+        Number sMax = LongEncoding.decodeNumber("37~~", Short.class);
+        Assert.assertEquals(Short.MAX_VALUE, sMax);
+
+        Number sMin = LongEncoding.decodeNumber("0B7~~~~~~~t00", Short.class);
+        Assert.assertEquals(Short.MIN_VALUE, sMin);
+
+        Number iMax = LongEncoding.decodeNumber("61~~~~~", Integer.class);
+        Assert.assertEquals(Integer.MAX_VALUE, iMax);
+
+        Number iMin = LongEncoding.decodeNumber("0B7~~~~z00000", Integer.class);
+        Assert.assertEquals(Integer.MIN_VALUE, iMin);
+
+        Number lMax = LongEncoding.decodeNumber("B7~~~~~~~~~~", Long.class);
+        Assert.assertEquals(Long.MAX_VALUE, lMax);
+
+        Number lMin = LongEncoding.decodeNumber("010", Long.class);
+        Assert.assertEquals(Long.MIN_VALUE, lMin);
+
+        Number fMax = LongEncoding.decodeNumber("61~V~~~", Float.class);
+        Assert.assertEquals(Float.MAX_VALUE, fMax);
+
+        Number fMin = LongEncoding.decodeNumber("11", Float.class);
+        Assert.assertEquals(Float.MIN_VALUE, fMin);
+
+        Number dMax = LongEncoding.decodeNumber("B7~k~~~~~~~~", Double.class);
+        Assert.assertEquals(Double.MAX_VALUE, dMax);
+
+        Number dMin = LongEncoding.decodeNumber("11", Double.class);
+        Assert.assertEquals(Double.MIN_VALUE, dMin);
+    }
+
+    @Test
+    public void testEncodeSortableThenCompare() {
+        int count = 100000;
+        Random random1 = new Random();
+        Random random2 = new Random();
+        for (int i = 0; i < count; i++) {
+            long num1 = random1.nextLong();
+            long num2 = random2.nextLong();
+
+            String encoded1 = LongEncoding.encodeSortable(num1);
+            String encoded2 = LongEncoding.encodeSortable(num2);
+            int cmp = Bytes.compare(encoded1.getBytes(), encoded2.getBytes());
+
+            if (num1 == num2) {
+                Assert.assertEquals(0, cmp);
+            } else if (num1 > num2) {
+                Assert.assertTrue(cmp > 0);
+            } else {
+                assert num1 < num2;
+                Assert.assertTrue(cmp < 0);
+            }
+        }
+    }
+
+    @Test
+    public void testEncodeNumberThenCompare() {
+        int count = 100000;
+        Random random1 = new Random();
+        Random random2 = new Random();
+
+        for (int i = 0; i < count; i++) {
+            compareEncodedNumber(random1.nextInt(), random2.nextInt());
+        }
+        for (int i = 0; i < count; i++) {
+            compareEncodedNumber(random1.nextLong(), random2.nextLong());
+        }
+
+        for (int i = 0; i < count; i++) {
+            compareEncodedNumber(random1.nextInt(), random2.nextLong());
+        }
+        for (int i = 0; i < count; i++) {
+            compareEncodedNumber(random1.nextLong(), random2.nextInt());
+        }
+
+        for (int i = 0; i < count; i++) {
+            compareEncodedNumber(random1.nextFloat(), random2.nextFloat());
+        }
+        for (int i = 0; i < count; i++) {
+            compareEncodedNumber(random1.nextDouble(), random2.nextDouble());
+        }
+    }
+
+    private static void compareEncodedNumber(Number num1, Number num2) {
+        int cmpExpected = NumericUtil.compareNumber(num1, num2);
+
+        String encoded1 = LongEncoding.encodeNumber(num1);
+        String encoded2 = LongEncoding.encodeNumber(num2);
+        int cmp = Bytes.compare(encoded1.getBytes(), encoded2.getBytes());
+
+        if (cmpExpected == 0) {
+            Assert.assertEquals(0, cmp);
+        } else if (cmpExpected > 0) {
+            Assert.assertTrue(cmp > 0);
+        } else {
+            assert cmpExpected < 0;
+            Assert.assertTrue(cmp < 0);
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/NumericUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/NumericUtilTest.java
new file mode 100644
index 0000000000..fc1f0d6149
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/NumericUtilTest.java
@@ -0,0 +1,475 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.util.Bytes;
+import org.apache.hugegraph.util.NumericUtil;
+import org.apache.hugegraph.testutil.Assert;
+
+public class NumericUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testNumberToSortableBytes() {
+        // byte
+        byte[] bytes = NumericUtil.numberToSortableBytes((byte) 0x33);
+        assertEquals(new byte[]{(byte) 0xb3}, bytes);
+
+        bytes = NumericUtil.numberToSortableBytes(Byte.MIN_VALUE);
+        assertEquals(new byte[]{0x00}, bytes);
+
+        bytes = NumericUtil.numberToSortableBytes(Byte.MAX_VALUE);
+        assertEquals(new byte[]{(byte) 0xff}, bytes);
+
+        bytes = NumericUtil.numberToSortableBytes((byte) -1);
+        assertEquals(new byte[]{(byte) 0x7f}, bytes);
+
+        bytes = NumericUtil.numberToSortableBytes((byte) 0);
+        assertEquals(new byte[]{(byte) 0x80}, bytes);
+
+        // short
+        bytes = NumericUtil.numberToSortableBytes((short) 0x11223344);
+        assertEquals(new byte[]{(byte) 0x80, 0x00, 0x33, 0x44}, bytes);
+
+        // int
+        bytes = NumericUtil.numberToSortableBytes(0x11223344);
+        assertEquals(new byte[]{(byte) 0x91, 0x22, 0x33, 0x44}, bytes);
+
+        // long
+        bytes = NumericUtil.numberToSortableBytes(0x1122334455L);
+        assertEquals(new byte[]{(byte) 0x80, 0, 0, 0x11,
+                                0x22, 0x33, 0x44, 0x55}, bytes);
+
+        // float
+        bytes = NumericUtil.numberToSortableBytes(3.14f);
+        assertEquals(new byte[]{(byte) 0xc0, 0x48, (byte) 0xf5, (byte) 0xc3},
+                     bytes);
+
+        // double
+        bytes = NumericUtil.numberToSortableBytes(3.1415926d);
+        assertEquals(new byte[]{(byte) 0xc0, 0x09, 0x21, (byte) 0xfb,
+                                0x4d, 0x12, (byte) 0xd8, 0x4a}, bytes);
+
+        // BigDecimal
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.numberToSortableBytes(new BigDecimal(123));
+        });
+    }
+
+    @Test
+    public void testSortableBytesToNumber() {
+        // byte
+        Number value = NumericUtil.sortableBytesToNumber(new byte[]{0x33},
+                                                         Byte.class);
+        Assert.assertEquals(value, (byte) 0xb3);
+
+        value = NumericUtil.sortableBytesToNumber(new byte[]{(byte) 0x00},
+                                                  Byte.class);
+        Assert.assertEquals(value, Byte.MIN_VALUE);
+
+        value = NumericUtil.sortableBytesToNumber(new byte[]{(byte) 0xff},
+                                                  Byte.class);
+        Assert.assertEquals(value, Byte.MAX_VALUE);
+
+        value = NumericUtil.sortableBytesToNumber(new byte[]{(byte) 0x7f},
+                                                  Byte.class);
+        Assert.assertEquals(value, (byte) -1);
+
+        value = NumericUtil.sortableBytesToNumber(new byte[]{(byte) 0x80},
+                                                  Byte.class);
+        Assert.assertEquals(value, (byte) 0);
+
+        // short
+        value = NumericUtil.sortableBytesToNumber(new byte[]{0, 0, 0x33, 0x44},
+                                                  Short.class);
+        Assert.assertEquals((short) 0x3344, value);
+
+        // int
+        value = NumericUtil.sortableBytesToNumber(
+                new byte[]{(byte) 0x91, 0x22, 0x33, 0x44}, Integer.class);
+        Assert.assertEquals(0x11223344, value);
+
+        // long
+        value = NumericUtil.sortableBytesToNumber(
+                new byte[]{(byte) 0x80, 0, 0, 0x11, 0x22, 0x33, 0x44, 0x55},
+                Long.class);
+        Assert.assertEquals(0x1122334455L, value);
+
+        // float
+        value = NumericUtil.sortableBytesToNumber(
+                new byte[]{(byte) 0xc0, 0x48, (byte) 0xf5, (byte) 0xc3},
+                Float.class);
+        Assert.assertEquals(3.14f, value);
+
+        // double
+        value = NumericUtil.sortableBytesToNumber(
+                new byte[]{(byte) 0xc0, 0x09, 0x21, (byte) 0xfb,
+                           0x4d, 0x12, (byte) 0xd8, 0x4a},
+                Double.class);
+        Assert.assertEquals(3.1415926d, value);
+
+        // BigDecimal
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.sortableBytesToNumber(new byte[123], BigDecimal.class);
+        });
+    }
+
+    @Test
+    public void testIntToSortableBytesAndCompare() {
+        byte[] bytes1 = NumericUtil.numberToSortableBytes(123456);
+        byte[] bytes2 = NumericUtil.numberToSortableBytes(123456);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(1);
+        bytes2 = NumericUtil.numberToSortableBytes(2);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(666);
+        bytes2 = NumericUtil.numberToSortableBytes(88);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Integer.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(0);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-123456);
+        bytes2 = NumericUtil.numberToSortableBytes(-123456);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(-1);
+        bytes2 = NumericUtil.numberToSortableBytes(-2);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-666);
+        bytes2 = NumericUtil.numberToSortableBytes(-88);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Integer.MIN_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0);
+        bytes2 = NumericUtil.numberToSortableBytes(-1);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0);
+        bytes2 = NumericUtil.numberToSortableBytes(Integer.MIN_VALUE);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(1);
+        bytes2 = NumericUtil.numberToSortableBytes(-1);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Integer.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+    }
+
+    @Test
+    public void testLongToSortableBytesAndCompare() {
+        byte[] bytes1 = NumericUtil.numberToSortableBytes(123456L);
+        byte[] bytes2 = NumericUtil.numberToSortableBytes(123456L);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(1L);
+        bytes2 = NumericUtil.numberToSortableBytes(2L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(666L);
+        bytes2 = NumericUtil.numberToSortableBytes(88L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Long.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(0L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-123456L);
+        bytes2 = NumericUtil.numberToSortableBytes(-123456L);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(-1L);
+        bytes2 = NumericUtil.numberToSortableBytes(-2L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-666L);
+        bytes2 = NumericUtil.numberToSortableBytes(-88L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Long.MIN_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0L);
+        bytes2 = NumericUtil.numberToSortableBytes(-1L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0L);
+        bytes2 = NumericUtil.numberToSortableBytes(Long.MIN_VALUE);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(1L);
+        bytes2 = NumericUtil.numberToSortableBytes(-1L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Long.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1L);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+    }
+
+    @Test
+    public void testFloatToSortableBytesAndCompare() {
+        byte[] bytes1 = NumericUtil.numberToSortableBytes(123456F);
+        byte[] bytes2 = NumericUtil.numberToSortableBytes(123456F);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(1F);
+        bytes2 = NumericUtil.numberToSortableBytes(2F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(666F);
+        bytes2 = NumericUtil.numberToSortableBytes(88F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Float.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(0F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-123456F);
+        bytes2 = NumericUtil.numberToSortableBytes(-123456F);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(-1F);
+        bytes2 = NumericUtil.numberToSortableBytes(-2F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-666F);
+        bytes2 = NumericUtil.numberToSortableBytes(-88F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-Float.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0F);
+        bytes2 = NumericUtil.numberToSortableBytes(-1F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0F);
+        bytes2 = NumericUtil.numberToSortableBytes(-Float.MAX_VALUE);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(1F);
+        bytes2 = NumericUtil.numberToSortableBytes(-1F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Float.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+    }
+
+    @Test
+    public void testDoubleToSortableBytesAndCompare() {
+        byte[] bytes1 = NumericUtil.numberToSortableBytes(123456D);
+        byte[] bytes2 = NumericUtil.numberToSortableBytes(123456D);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(1D);
+        bytes2 = NumericUtil.numberToSortableBytes(2D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(666D);
+        bytes2 = NumericUtil.numberToSortableBytes(88D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Double.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(0D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-123456D);
+        bytes2 = NumericUtil.numberToSortableBytes(-123456D);
+        Assert.assertEquals(0, Bytes.compare(bytes1, bytes2));
+
+        bytes1 = NumericUtil.numberToSortableBytes(-1D);
+        bytes2 = NumericUtil.numberToSortableBytes(-2D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-666D);
+        bytes2 = NumericUtil.numberToSortableBytes(-88D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(-Double.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) < 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0D);
+        bytes2 = NumericUtil.numberToSortableBytes(-1D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(0D);
+        bytes2 = NumericUtil.numberToSortableBytes(-Double.MAX_VALUE);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(1D);
+        bytes2 = NumericUtil.numberToSortableBytes(-1D);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+
+        bytes1 = NumericUtil.numberToSortableBytes(Double.MAX_VALUE);
+        bytes2 = NumericUtil.numberToSortableBytes(-1F);
+        Assert.assertTrue(Bytes.compare(bytes1, bytes2) > 0);
+    }
+
+    @Test
+    public void testMinValueOf() {
+        Assert.assertEquals(Byte.MIN_VALUE,
+                            NumericUtil.minValueOf(Byte.class));
+
+        Assert.assertEquals(Integer.MIN_VALUE,
+                            NumericUtil.minValueOf(Short.class));
+        Assert.assertEquals(Integer.MIN_VALUE,
+                            NumericUtil.minValueOf(Integer.class));
+        Assert.assertEquals(Integer.MIN_VALUE,
+                            NumericUtil.minValueOf(Float.class));
+
+        Assert.assertEquals(Long.MIN_VALUE,
+                            NumericUtil.minValueOf(Long.class));
+        Assert.assertEquals(Long.MIN_VALUE,
+                            NumericUtil.minValueOf(Double.class));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.minValueOf(null);
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.minValueOf(Character.class);
+        });
+    }
+
+    @Test
+    public void testMaxValueOf() {
+        Assert.assertEquals(Byte.MAX_VALUE,
+                            NumericUtil.maxValueOf(Byte.class));
+
+        Assert.assertEquals(Integer.MAX_VALUE,
+                            NumericUtil.maxValueOf(Short.class));
+        Assert.assertEquals(Integer.MAX_VALUE,
+                            NumericUtil.maxValueOf(Integer.class));
+        Assert.assertEquals(Integer.MAX_VALUE,
+                            NumericUtil.maxValueOf(Float.class));
+
+        Assert.assertEquals(Long.MAX_VALUE,
+                            NumericUtil.maxValueOf(Long.class));
+        Assert.assertEquals(Long.MAX_VALUE,
+                            NumericUtil.maxValueOf(Double.class));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.maxValueOf(null);
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.maxValueOf(Character.class);
+        });
+    }
+
+    @Test
+    public void testIsNumber() {
+        Assert.assertTrue(NumericUtil.isNumber(byte.class));
+        Assert.assertTrue(NumericUtil.isNumber(Byte.class));
+        Assert.assertTrue(NumericUtil.isNumber(short.class));
+        Assert.assertTrue(NumericUtil.isNumber(Short.class));
+        Assert.assertTrue(NumericUtil.isNumber(int.class));
+        Assert.assertTrue(NumericUtil.isNumber(Integer.class));
+        Assert.assertTrue(NumericUtil.isNumber(long.class));
+        Assert.assertTrue(NumericUtil.isNumber(Long.class));
+        Assert.assertTrue(NumericUtil.isNumber(float.class));
+        Assert.assertTrue(NumericUtil.isNumber(Float.class));
+        Assert.assertTrue(NumericUtil.isNumber(double.class));
+        Assert.assertTrue(NumericUtil.isNumber(Double.class));
+
+        Assert.assertFalse(NumericUtil.isNumber(char.class));
+        Assert.assertFalse(NumericUtil.isNumber(Character.class));
+
+        Assert.assertTrue(NumericUtil.isNumber(1));
+        Assert.assertTrue(NumericUtil.isNumber(1L));
+        Assert.assertTrue(NumericUtil.isNumber(1.0f));
+        Assert.assertTrue(NumericUtil.isNumber(1.0d));
+        Assert.assertFalse(NumericUtil.isNumber('1'));
+        Assert.assertFalse(NumericUtil.isNumber((Object) null));
+    }
+
+    @Test
+    public void testConvertToNumber() {
+        Assert.assertEquals(1, NumericUtil.convertToNumber(1));
+        Assert.assertEquals(1.2, NumericUtil.convertToNumber(1.2));
+
+        Assert.assertEquals(new BigDecimal("1.25"),
+                            NumericUtil.convertToNumber("1.25"));
+
+        Date date = new Date();
+        Assert.assertEquals(date.getTime(), NumericUtil.convertToNumber(date));
+
+        Assert.assertNull(NumericUtil.convertToNumber(null));
+    }
+
+    @Test
+    public void testCompareNumber() {
+        Assert.assertEquals(0, NumericUtil.compareNumber(2, 2));
+        Assert.assertEquals(1, NumericUtil.compareNumber(10, 2));
+        Assert.assertEquals(-1, NumericUtil.compareNumber(1, 2));
+
+        Assert.assertEquals(-1, NumericUtil.compareNumber("1", 2));
+        Assert.assertEquals(0, NumericUtil.compareNumber("2.0", 2));
+        Assert.assertEquals(1, NumericUtil.compareNumber("2.00001", 2));
+        Assert.assertEquals(1, NumericUtil.compareNumber("3.8", 2));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.compareNumber(null, 1);
+        }, e -> {
+            Assert.assertContains("The first parameter can't be null",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.compareNumber(2, null);
+        }, e -> {
+            Assert.assertContains("The second parameter can't be null",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.compareNumber("2", null);
+        }, e -> {
+            Assert.assertContains("The second parameter can't be null",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            NumericUtil.compareNumber("f", 2);
+        }, e -> {
+            Assert.assertContains("Can't compare between 'f' and '2'",
+                                  e.getMessage());
+        });
+    }
+
+    private static void assertEquals(byte[] bytes1, byte[] bytes2) {
+        Assert.assertTrue(Bytes.toHex(bytes1) + " != " + Bytes.toHex(bytes2),
+                          Bytes.equals(bytes1, bytes2));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/OrderLimitMapTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/OrderLimitMapTest.java
new file mode 100644
index 0000000000..de8375c102
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/OrderLimitMapTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.util.OrderLimitMap;
+import org.apache.hugegraph.testutil.Assert;
+import com.google.common.collect.ImmutableList;
+
+public class OrderLimitMapTest {
+
+    @Test
+    public void testInvalidCapacity() {
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            new OrderLimitMap<>(-1);
+        }, e -> {
+            Assert.assertEquals("The capacity must be > 0", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testMap() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(4, 0.4);
+        map.put(2, 0.2);
+        map.put(5, 0.5);
+        map.put(1, 0.2);
+        map.put(3, 0.3);
+
+        Assert.assertEquals(5, map.size());
+
+        Assert.assertEquals(0.2, map.get(2), 1E-9);
+        Assert.assertEquals(0.4, map.get(4), 1E-9);
+
+        Assert.assertTrue(map.containsKey(1));
+        Assert.assertTrue(map.containsKey(3));
+        Assert.assertFalse(map.containsKey(6));
+
+        Assert.assertNull(map.get(6));
+
+        Assert.assertEquals(0.5, map.getOrDefault(5, 0.0), 1E-9);
+        Assert.assertEquals(0.0, map.getOrDefault(7, 0.0), 1E-9);
+    }
+
+    @Test
+    public void testOrder() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(1, 0.1);
+        map.put(2, 0.2);
+        map.put(3, 0.3);
+        map.put(4, 0.4);
+        map.put(5, 0.5);
+
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 2, 1),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testOrderWithIncrOrder() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5, true);
+        map.put(1, 0.5);
+        map.put(2, 0.4);
+        map.put(3, 0.3);
+        map.put(4, 0.2);
+        map.put(5, 0.1);
+
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 2, 1),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testOrderWithDupValue() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(1, 0.1);
+        map.put(2, 0.2);
+        map.put(3, 0.3);
+        map.put(4, 0.2);
+        map.put(5, 0.3);
+
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(3, 5, 2, 4, 1),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testOrderWithDupValueAndKeyIncrOrder() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(4, 0.2);
+        map.put(2, 0.2);
+        map.put(1, 0.1);
+        map.put(5, 0.3);
+        map.put(3, 0.3);
+
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(3, 5, 2, 4, 1),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testOrderWithDupKey() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(1, 0.1);
+        map.put(2, 0.2);
+        map.put(3, 0.3);
+        map.put(2, 0.4);
+        map.put(3, 0.2);
+
+        Assert.assertEquals(3, map.size());
+        Assert.assertEquals(ImmutableList.of(2, 3, 1),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testLimit() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(1, 0.1);
+        map.put(2, 0.2);
+        map.put(3, 0.3);
+        map.put(4, 0.4);
+        map.put(5, 0.5);
+
+        map.put(6, 0.6);
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(6, 5, 4, 3, 2),
+                            ImmutableList.copyOf(map.keySet()));
+
+        map.put(7, 0.7);
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(7, 6, 5, 4, 3),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testLimitWithDupValue() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(1, 0.1);
+        map.put(2, 0.2);
+        map.put(3, 0.3);
+        map.put(4, 0.4);
+        map.put(5, 0.5);
+
+        map.put(6, 0.1);
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 2, 6),
+                            ImmutableList.copyOf(map.keySet()));
+
+        map.put(7, 0.3);
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 7, 2),
+                            ImmutableList.copyOf(map.keySet()));
+
+        map.put(8, 0.5);
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(5, 8, 4, 3, 7),
+                            ImmutableList.copyOf(map.keySet()));
+
+        map.put(0, 0.5);
+        Assert.assertEquals(5, map.size());
+        Assert.assertEquals(ImmutableList.of(0, 5, 8, 4, 3),
+                            ImmutableList.copyOf(map.keySet()));
+    }
+
+    @Test
+    public void testTopN() {
+        OrderLimitMap<Integer, Double> map = new OrderLimitMap<>(5);
+        map.put(1, 0.1);
+        map.put(2, 0.2);
+        map.put(3, 0.3);
+        map.put(4, 0.4);
+        map.put(5, 0.5);
+
+        Map<Integer, Double> top = map.topN(1);
+        Assert.assertEquals(ImmutableList.of(5),
+                            ImmutableList.copyOf(top.keySet()));
+
+        top = map.topN(3);
+        Assert.assertEquals(ImmutableList.of(5, 4, 3),
+                            ImmutableList.copyOf(top.keySet()));
+
+        top = map.topN(5);
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 2, 1),
+                            ImmutableList.copyOf(top.keySet()));
+
+        top = map.topN(6);
+        Assert.assertEquals(ImmutableList.of(5, 4, 3, 2, 1),
+                            ImmutableList.copyOf(top.keySet()));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/ReflectionUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/ReflectionUtilTest.java
new file mode 100644
index 0000000000..f511ddfc7d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/ReflectionUtilTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.hugegraph.perf.PerfUtil;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.apache.hugegraph.unit.perf.testclass.TestClass;
+import org.apache.hugegraph.unit.perf.testclass.TestClass.Bar;
+import org.apache.hugegraph.unit.perf.testclass.TestClass.Base;
+import org.apache.hugegraph.unit.perf.testclass.TestClass.Foo;
+import org.apache.hugegraph.unit.perf.testclass.TestClass.ManuallyProfile;
+import org.apache.hugegraph.unit.perf.testclass.TestClass.Sub;
+import org.apache.hugegraph.util.ReflectionUtil;
+import org.junit.Test;
+
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+import javassist.NotFoundException;
+
+public class ReflectionUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testIsSimpleType() {
+        Assert.assertTrue(ReflectionUtil.isSimpleType(byte.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(char.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(short.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(int.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(long.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(float.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(double.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(boolean.class));
+
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Byte.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Character.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Short.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Integer.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Long.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Float.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Double.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(Boolean.class));
+        Assert.assertTrue(ReflectionUtil.isSimpleType(String.class));
+
+        Assert.assertFalse(ReflectionUtil.isSimpleType(Object.class));
+        Assert.assertFalse(ReflectionUtil.isSimpleType(BaseUnitTest.class));
+    }
+
+    @Test
+    public void testGetMethodsAnnotatedWith() {
+        List<Method> methods;
+
+        methods = ReflectionUtil.getMethodsAnnotatedWith(Sub.class,
+                                                         PerfUtil.Watched.class,
+                                                         false);
+        methods.sort((m1, m2) -> m1.getName().compareTo(m2.getName()));
+        Assert.assertEquals(2, methods.size());
+        Assert.assertEquals("func1", methods.get(0).getName());
+        Assert.assertEquals("func3", methods.get(1).getName());
+
+
+        methods = ReflectionUtil.getMethodsAnnotatedWith(Sub.class,
+                                                         PerfUtil.Watched.class,
+                                                         true);
+        methods.sort((m1, m2) -> m1.getName().compareTo(m2.getName()));
+        Assert.assertEquals(3, methods.size());
+        Assert.assertEquals("func", methods.get(0).getName());
+        Assert.assertEquals("func1", methods.get(1).getName());
+        Assert.assertEquals("func3", methods.get(2).getName());
+    }
+
+    @Test
+    public void testClasses() throws IOException {
+        @SuppressWarnings("unchecked")
+        List<ClassInfo> classes = IteratorUtils.toList(ReflectionUtil.classes(
+                                  "org.apache.hugegraph.util"));
+        Assert.assertEquals(19, classes.size());
+        classes.sort(Comparator.comparing(ClassInfo::getName));
+        Assert.assertEquals("org.apache.hugegraph.util.Bytes",
+                            classes.get(0).getName());
+        Assert.assertEquals("org.apache.hugegraph.util.CheckSocket",
+                            classes.get(1).getName());
+        Assert.assertEquals("org.apache.hugegraph.util.CollectionUtil",
+                            classes.get(2).getName());
+        Assert.assertEquals("org.apache.hugegraph.util.DateUtil",
+                            classes.get(3).getName());
+    }
+
+    @Test
+    public void testSuperClasses() throws NotFoundException {
+        List<String> classes = ReflectionUtil.superClasses(Sub.class.getName());
+        Assert.assertEquals(2, classes.size());
+        classes.sort(String::compareTo);
+        Assert.assertEquals(Object.class.getName(), classes.get(0));
+        Assert.assertEquals(Base.class.getName(), classes.get(1));
+    }
+
+    @Test
+    public void testNestedClasses() throws NotFoundException {
+        List<String> classes = ReflectionUtil.nestedClasses(
+                               TestClass.class.getName());
+        Assert.assertEquals(5, classes.size());
+        classes.sort(String::compareTo);
+        Assert.assertEquals(Bar.class.getName(), classes.get(0));
+        Assert.assertEquals(Base.class.getName(), classes.get(1));
+        Assert.assertEquals(Foo.class.getName(), classes.get(2));
+        Assert.assertEquals(ManuallyProfile.class.getName(), classes.get(3));
+        Assert.assertEquals(Sub.class.getName(), classes.get(4));
+    }
+
+    @Test
+    public void testPackageName() {
+        String clazz = "org.apache.hugegraph.unit.perf.testclass2.Test";
+        Assert.assertEquals("org.apache.hugegraph.unit.perf.testclass2",
+                            ReflectionUtil.packageName(clazz));
+
+        clazz = "org.apache.hugegraph.unit.perf.testclass2.Test$Bar";
+        Assert.assertEquals("org.apache.hugegraph.unit.perf.testclass2",
+                            ReflectionUtil.packageName(clazz));
+
+        clazz = "org.apache.hugegraph.unit.perf.testclass.Test$Bar";
+        Assert.assertEquals("org.apache.hugegraph.unit.perf.testclass",
+                            ReflectionUtil.packageName(clazz));
+
+        clazz = "org.apache.hugegraph.unit.perf.testclass..Test$Bar";
+        Assert.assertEquals("org.apache.hugegraph.unit.perf.testclass.",
+                            ReflectionUtil.packageName(clazz));
+
+        clazz = "com";
+        Assert.assertEquals("", ReflectionUtil.packageName(clazz));
+
+        clazz = "com.";
+        Assert.assertEquals("com", ReflectionUtil.packageName(clazz));
+
+        clazz = "Test";
+        Assert.assertEquals("", ReflectionUtil.packageName(clazz));
+
+        clazz = ".Test";
+        Assert.assertEquals("", ReflectionUtil.packageName(clazz));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/StringUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/StringUtilTest.java
new file mode 100644
index 0000000000..c7aab1532c
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/StringUtilTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.util.StringUtil;
+import org.apache.hugegraph.util.StringUtil.Chars;
+import org.junit.Test;
+
+import com.google.common.base.Splitter;
+
+public class StringUtilTest {
+
+    @Test
+    public void testSplit() {
+        Assert.assertArrayEquals(new String[]{"1", "2", "3"},
+                                 StringUtil.split("1, 2, 3", ", "));
+        Assert.assertArrayEquals(new String[]{"1", "1", "1"},
+                                 StringUtil.split("1 1 1", " "));
+        Assert.assertArrayEquals(new String[]{"", "", ""},
+                                 StringUtil.split("111", "1"));
+
+        Assert.assertEquals(guavaSplit("123", " "),
+                            toStringList(StringUtil.split("123", " ")));
+        Assert.assertEquals(guavaSplit("1 2 3", " "),
+                            toStringList(StringUtil.split("1 2 3", " ")));
+        Assert.assertEquals(guavaSplit("1:2:3", ":"),
+                            toStringList(StringUtil.split("1:2:3", ":")));
+        Assert.assertEquals(guavaSplit("1::2:3", ":"),
+                            toStringList(StringUtil.split("1::2:3", ":")));
+        Assert.assertEquals(guavaSplit("1::2::3", ":"),
+                            toStringList(StringUtil.split("1::2::3", ":")));
+        Assert.assertEquals(guavaSplit("1::2::3", "::"),
+                            toStringList(StringUtil.split("1::2::3", "::")));
+        Assert.assertEquals(guavaSplit("1:|2|:3", "|"),
+                            toStringList(StringUtil.split("1:|2|:3", "|")));
+        Assert.assertEquals(guavaSplit("1\t2\t3", "\t"),
+                            toStringList(StringUtil.split("1\t2\t3", "\t")));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            StringUtil.split("123", "");
+        });
+    }
+
+    @Test
+    public void testSplitToCharsArray() {
+        Assert.assertArrayEquals(Chars.of("1", "2", "3"),
+                                 StringUtil.splitToCharsArray("1, 2, 3", ", "));
+        Assert.assertArrayEquals(Chars.of("1", "1", "1"),
+                                 StringUtil.splitToCharsArray("1 1 1", " "));
+        Assert.assertArrayEquals(Chars.of("", "", ""),
+                                 StringUtil.splitToCharsArray("111", "1"));
+
+        Assert.assertArrayEquals(new Chars[]{Chars.of("123")},
+                                 StringUtil.splitToCharsArray("123", " "));
+        Assert.assertArrayEquals(Chars.of("1", "", "2", "3"),
+                                 StringUtil.splitToCharsArray("1::2:3", ":"));
+        Assert.assertArrayEquals(Chars.of("1", "", "2", "", "3"),
+                                 StringUtil.splitToCharsArray("1::2::3", ":"));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            StringUtil.splitToCharsArray("123", "");
+        });
+    }
+
+    @Test
+    public void testCharsCharAt() {
+        Chars chars = Chars.of("123");
+        Assert.assertEquals('1', chars.charAt(0));
+        Assert.assertEquals('2', chars.charAt(1));
+        Assert.assertEquals('3', chars.charAt(2));
+
+        Assert.assertThrows(ArrayIndexOutOfBoundsException.class, () -> {
+            chars.charAt(3);
+        });
+        Assert.assertThrows(ArrayIndexOutOfBoundsException.class, () -> {
+            chars.charAt(-1);
+        });
+    }
+
+    @Test
+    public void testCharsSubSequence() {
+        Chars chars = Chars.of("123");
+        Assert.assertEquals(Chars.of("1"), chars.subSequence(0, 1));
+        Assert.assertEquals(Chars.of("12"), chars.subSequence(0, 2));
+        Assert.assertEquals(Chars.of("2"), chars.subSequence(1, 2));
+        Assert.assertEquals(Chars.of("23"), chars.subSequence(1, 3));
+        Assert.assertEquals(Chars.of("123"), chars.subSequence(0, 3));
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            chars.subSequence(2, 1);
+        }, e -> {
+            Assert.assertContains("Invalid end parameter 1", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            chars.subSequence(-1, 2);
+        }, e -> {
+            Assert.assertContains("Invalid start parameter -1", e.getMessage());
+        });
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            chars.subSequence(1, -1);
+        }, e -> {
+            Assert.assertContains("Invalid end parameter -1", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testCharsEquals() {
+        Chars chars1 = Chars.of("123");
+        Chars chars2 = Chars.of("123");
+        Chars chars3 = Chars.of("12");
+
+        Assert.assertEquals(chars1, chars2);
+        Assert.assertNotEquals(chars1, chars3);
+        Assert.assertNotEquals(chars1, "123");
+        Assert.assertNotEquals(chars1, null);
+    }
+
+    @Test
+    public void testCharsHashCode() {
+        Chars chars1 = Chars.of("123");
+        Chars chars2 = Chars.of("123");
+        Chars chars3 = Chars.of("12");
+
+        Assert.assertEquals(chars1.hashCode(), chars2.hashCode());
+        Assert.assertEquals(chars1.hashCode(), "123".hashCode());
+        Assert.assertNotEquals(chars1.hashCode(), chars3.hashCode());
+    }
+
+    private static List<String> guavaSplit(String line, String delimiter) {
+        return Splitter.on(delimiter).splitToList(line);
+    }
+
+    private static List<String> toStringList(String[] stringArray) {
+        List<String> results = new ArrayList<>(stringArray.length);
+        Collections.addAll(results, stringArray);
+        return results;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/TimeUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/TimeUtilTest.java
new file mode 100644
index 0000000000..2fc34f0bb5
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/TimeUtilTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.util.Date;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.util.TimeUtil;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class TimeUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testTimeGen() {
+        long time = TimeUtil.timeGen();
+        long base = TimeUtil.BASE_TIME;
+        long difference = time - base - System.currentTimeMillis();
+        Assert.assertTrue(difference < 1000);
+    }
+
+    @Test
+    public void testTimeGenWithDate() {
+        @SuppressWarnings("deprecation")
+        Date date = new Date(2019 - 1900, 2, 28);
+        long time = TimeUtil.timeGen(date);
+        Assert.assertEquals(41904000000L, time);
+    }
+
+    @Test
+    public void testTimeGenWithLong() {
+        long date = TimeUtil.BASE_TIME + 123L;
+        long time = TimeUtil.timeGen(date);
+        Assert.assertEquals(123L, time);
+    }
+
+    @Test
+    public void testTillNextMillis() {
+        for (int i = 0; i < 100; i++) {
+            long lastTimestamp = TimeUtil.timeGen();
+            long time = TimeUtil.tillNextMillis(lastTimestamp);
+            Assert.assertNotEquals(lastTimestamp, time);
+        }
+    }
+
+    @Test
+    public void testReadableTime() {
+        Assert.assertEquals("0.001s", TimeUtil.readableTime(1));
+        Assert.assertEquals("0.999s", TimeUtil.readableTime(999));
+        Assert.assertEquals("1s", TimeUtil.readableTime(1000));
+        Assert.assertEquals("1.5s", TimeUtil.readableTime(1500));
+        Assert.assertEquals("15s", TimeUtil.readableTime(15 * 1000));
+        Assert.assertEquals("59.99s", TimeUtil.readableTime(59990));
+        Assert.assertEquals("1m", TimeUtil.readableTime(60000));
+        // Ignore milliseconds part
+        Assert.assertEquals("1m", TimeUtil.readableTime(60000 + 100));
+        Assert.assertEquals("1m 1s", TimeUtil.readableTime(60000 + 1000));
+        Assert.assertEquals("1m 1s", TimeUtil.readableTime(60000 + 1200));
+        Assert.assertEquals("59m", TimeUtil.readableTime(59 * 60 * 1000));
+        Assert.assertEquals("1h", TimeUtil.readableTime(60 * 60 * 1000));
+        Assert.assertEquals("1h 1m", TimeUtil.readableTime(60 * 60 * 1000 +
+                                                           60 * 1000));
+        Assert.assertEquals("23h 59m 59s", TimeUtil.readableTime(
+                                                    23 * 60 * 60 * 1000 +
+                                                    59 * 60 * 1000 +
+                                                    59 * 1000));
+        Assert.assertEquals("24h", TimeUtil.readableTime(24 * 60 * 60 * 1000));
+        Assert.assertEquals("25h 1m 1s", TimeUtil.readableTime(
+                                                    25 * 60 * 60 * 1000 +
+                                                    1 * 60 * 1000 +
+                                                    1 * 1200));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/UnitUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/UnitUtilTest.java
new file mode 100644
index 0000000000..56eb73f4d4
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/UnitUtilTest.java
@@ -0,0 +1,665 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.util.Bytes;
+import org.apache.hugegraph.util.UnitUtil;
+import org.apache.hugegraph.testutil.Assert;
+
+public class UnitUtilTest {
+
+    @Test
+    public void testBytesToMB() {
+        double value = UnitUtil.bytesToMB(0L);
+        Assert.assertEquals(0d, value, 0d);
+
+        // KB
+        value = UnitUtil.bytesToMB(1 * Bytes.KB);
+        Assert.assertEquals(0d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * 10);
+        Assert.assertEquals(0.01d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * 100);
+        Assert.assertEquals(0.1d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * (long) (134 * 1.024));
+        Assert.assertEquals(0.13d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * (long) (135 * 1.024));
+        Assert.assertEquals(0.13d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * (long) (136 * 1.024));
+        Assert.assertEquals(0.14d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * (long) (144 * 1.024));
+        Assert.assertEquals(0.14d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * (long) (754 * 1.024));
+        Assert.assertEquals(0.75d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * (long) (755 * 1.024));
+        Assert.assertEquals(0.75d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.KB * (long) (756 * 1.024));
+        Assert.assertEquals(0.76d, value, 0d);
+
+        // MB
+        value = UnitUtil.bytesToMB(Bytes.MB * 1);
+        Assert.assertEquals(1d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.MB * 13);
+        Assert.assertEquals(13d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.MB * 1357);
+        Assert.assertEquals(1357d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.MB * 1357924680);
+        Assert.assertEquals(1357924680d, value, 0d);
+
+        value = UnitUtil.bytesToMB(Bytes.MB * 1357924680246L);
+        Assert.assertEquals(1357924680246d, value, 0d);
+    }
+
+    @Test
+    public void testBytesToGB() {
+        double value = UnitUtil.bytesToGB(0L);
+        Assert.assertEquals(0d, value, 0d);
+
+        // MB
+        value = UnitUtil.bytesToGB(1 * Bytes.MB);
+        Assert.assertEquals(0d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * 10);
+        Assert.assertEquals(0.01d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * 100);
+        Assert.assertEquals(0.10d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * (long) (134 * 1.024));
+        Assert.assertEquals(0.13d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * (long) (135 * 1.024));
+        Assert.assertEquals(0.13d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * (long) (136 * 1.024));
+        Assert.assertEquals(0.14d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * (long) (144 * 1.024));
+        Assert.assertEquals(0.14d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * (long) (754 * 1.024));
+        Assert.assertEquals(0.75d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * (long) (755 * 1.024));
+        Assert.assertEquals(0.75d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.MB * (long) (756 * 1.024));
+        Assert.assertEquals(0.76d, value, 0d);
+
+        // GB
+        value = UnitUtil.bytesToGB(Bytes.GB * 1);
+        Assert.assertEquals(1d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.GB * 13);
+        Assert.assertEquals(13d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.GB * 1357);
+        Assert.assertEquals(1357d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.GB * 1357924680);
+        Assert.assertEquals(1357924680d, value, 0d);
+
+        value = UnitUtil.bytesToGB(Bytes.GB * 7357924680L);
+        Assert.assertEquals(7357924680d, value, 0d);
+
+        // Bytes overflow long value
+        value = UnitUtil.bytesToGB(Bytes.GB * 9357924680L);
+        Assert.assertEquals(-7.821944504E9, value, 0d);
+    }
+
+    @Test
+    public void testBytesToReadableString() {
+        String value = UnitUtil.bytesToReadableString(0L);
+        Assert.assertEquals("0 B", value);
+
+        // B
+        value = UnitUtil.bytesToReadableString(1);
+        Assert.assertEquals("1 B", value);
+
+        value = UnitUtil.bytesToReadableString(3);
+        Assert.assertEquals("3 B", value);
+
+        value = UnitUtil.bytesToReadableString(10);
+        Assert.assertEquals("10 B", value);
+
+        value = UnitUtil.bytesToReadableString(100);
+        Assert.assertEquals("100 B", value);
+
+        value = UnitUtil.bytesToReadableString(1000);
+        Assert.assertEquals("1000 B", value);
+
+        value = UnitUtil.bytesToReadableString(1023);
+        Assert.assertEquals("1023 B", value);
+
+        // KB
+        value = UnitUtil.bytesToReadableString(1024);
+        Assert.assertEquals("1 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB + 1);
+        Assert.assertEquals("1.0 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB + 10);
+        Assert.assertEquals("1.01 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB + 20);
+        Assert.assertEquals("1.02 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB + 100);
+        Assert.assertEquals("1.1 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB + 123);
+        Assert.assertEquals("1.12 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB + 129);
+        Assert.assertEquals("1.13 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB * 8 +
+                                               (long) (755 * 1.024));
+        Assert.assertEquals("8.75 KB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.KB * 168 +
+                                               (long) (756 * 1.024));
+        Assert.assertEquals("168.76 KB", value);
+
+        // MB
+        value = UnitUtil.bytesToReadableString(Bytes.KB * 1024);
+        Assert.assertEquals("1 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB + 1 * Bytes.KB);
+        Assert.assertEquals("1.0 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB + 10 * Bytes.KB);
+        Assert.assertEquals("1.01 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB + 20 * Bytes.KB);
+        Assert.assertEquals("1.02 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB + 100 * Bytes.KB);
+        Assert.assertEquals("1.1 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB + 123 * Bytes.KB);
+        Assert.assertEquals("1.12 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB + 129 * Bytes.KB);
+        Assert.assertEquals("1.13 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB * 8 +
+                                               (long) (755 * 1.024) * Bytes.KB);
+        Assert.assertEquals("8.75 MB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.MB * 168 +
+                                               (long) (756 * 1.024) * Bytes.KB);
+        Assert.assertEquals("168.76 MB", value);
+
+        // GB
+        value = UnitUtil.bytesToReadableString(Bytes.MB * 1024);
+        Assert.assertEquals("1 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB + 1 * Bytes.MB);
+        Assert.assertEquals("1.0 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB + 10 * Bytes.MB);
+        Assert.assertEquals("1.01 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB + 20 * Bytes.MB);
+        Assert.assertEquals("1.02 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB + 100 * Bytes.MB);
+        Assert.assertEquals("1.1 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB + 123 * Bytes.MB);
+        Assert.assertEquals("1.12 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB + 129 * Bytes.MB);
+        Assert.assertEquals("1.13 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB * 8 +
+                                               (long) (755 * 1.024) * Bytes.MB);
+        Assert.assertEquals("8.75 GB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.GB * 168 +
+                                               (long) (756 * 1.024) * Bytes.MB);
+        Assert.assertEquals("168.76 GB", value);
+
+        // TB
+        value = UnitUtil.bytesToReadableString(Bytes.GB * 1024);
+        Assert.assertEquals("1 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB + 1 * Bytes.GB);
+        Assert.assertEquals("1.0 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB + 10 * Bytes.GB);
+        Assert.assertEquals("1.01 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB + 20 * Bytes.GB);
+        Assert.assertEquals("1.02 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB + 100 * Bytes.GB);
+        Assert.assertEquals("1.1 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB + 123 * Bytes.GB);
+        Assert.assertEquals("1.12 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB + 129 * Bytes.GB);
+        Assert.assertEquals("1.13 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB * 8 +
+                                               (long) (755 * 1.024) * Bytes.GB);
+        Assert.assertEquals("8.75 TB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.TB * 168 +
+                                               (long) (756 * 1.024) * Bytes.GB);
+        Assert.assertEquals("168.76 TB", value);
+
+        // PB
+        value = UnitUtil.bytesToReadableString(Bytes.TB * 1024);
+        Assert.assertEquals("1 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB + 1 * Bytes.TB);
+        Assert.assertEquals("1.0 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB + 10 * Bytes.TB);
+        Assert.assertEquals("1.01 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB + 20 * Bytes.TB);
+        Assert.assertEquals("1.02 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB + 100 * Bytes.TB);
+        Assert.assertEquals("1.1 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB + 123 * Bytes.TB);
+        Assert.assertEquals("1.12 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB + 129 * Bytes.TB);
+        Assert.assertEquals("1.13 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB * 8 +
+                                               (long) (755 * 1.024) * Bytes.TB);
+        Assert.assertEquals("8.75 PB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.PB * 168 +
+                                               (long) (756 * 1.024) * Bytes.TB);
+        Assert.assertEquals("168.76 PB", value);
+
+        // EB
+        value = UnitUtil.bytesToReadableString(Bytes.PB * 1024);
+        Assert.assertEquals("1 EB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.EB + 1 * Bytes.PB);
+        Assert.assertEquals("1.0 EB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.EB + 10 * Bytes.PB);
+        Assert.assertEquals("1.01 EB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.EB + 20 * Bytes.PB);
+        Assert.assertEquals("1.02 EB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.EB + 100 * Bytes.PB);
+        Assert.assertEquals("1.1 EB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.EB + 123 * Bytes.PB);
+        Assert.assertEquals("1.12 EB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.EB + 129 * Bytes.PB);
+        Assert.assertEquals("1.13 EB", value);
+
+        value = UnitUtil.bytesToReadableString(Bytes.EB * 7 +
+                                               (long) (755 * 1.024) * Bytes.PB);
+        Assert.assertEquals("7.75 EB", value);
+
+        // Bytes overflow long value
+        value = UnitUtil.bytesToReadableString(Bytes.EB * 8);
+        Assert.assertEquals("0 B", value);
+    }
+
+    @Test
+    public void testBytesFromReadableString() {
+        // B
+        Assert.assertEquals(0L, UnitUtil.bytesFromReadableString("0 B"));
+        Assert.assertEquals(1L, UnitUtil.bytesFromReadableString("1 Bytes"));
+        Assert.assertEquals(3L, UnitUtil.bytesFromReadableString("3 bytes"));
+        Assert.assertEquals(10L, UnitUtil.bytesFromReadableString("10 Byte"));
+        Assert.assertEquals(100L, UnitUtil.bytesFromReadableString("100 byte"));
+        Assert.assertEquals(1000L, UnitUtil.bytesFromReadableString("1000 b"));
+        Assert.assertEquals(1023L, UnitUtil.bytesFromReadableString("1023 B"));
+
+        Assert.assertEquals(1024L, UnitUtil.bytesFromReadableString("1024 B"));
+        Assert.assertEquals(10245678L,
+                            UnitUtil.bytesFromReadableString("10245678 B"));
+        Assert.assertEquals(102456789012L,
+                            UnitUtil.bytesFromReadableString("102456789012 B"));
+
+        Assert.assertEquals(1L, UnitUtil.bytesFromReadableString("1  B"));
+        Assert.assertEquals(1L, UnitUtil.bytesFromReadableString("1  B "));
+        Assert.assertEquals(-2L, UnitUtil.bytesFromReadableString("-2 B"));
+
+        // KB
+        Assert.assertEquals(0L, UnitUtil.bytesFromReadableString("0 KB"));
+        Assert.assertEquals(Bytes.KB * 1L,
+                            UnitUtil.bytesFromReadableString("1 KB"));
+        Assert.assertEquals((long) (Bytes.KB * 3.14),
+                            UnitUtil.bytesFromReadableString("3.14 KB"));
+        Assert.assertEquals(Bytes.KB * 10L,
+                            UnitUtil.bytesFromReadableString("10 kB"));
+        Assert.assertEquals(Bytes.KB * 100L,
+                            UnitUtil.bytesFromReadableString("100 KiB"));
+        Assert.assertEquals(Bytes.KB * 1000L,
+                            UnitUtil.bytesFromReadableString("1000 kb"));
+        Assert.assertEquals(Bytes.KB * 1023L,
+                            UnitUtil.bytesFromReadableString("1023 kib"));
+        Assert.assertEquals(Bytes.KB * 1234567890L,
+                            UnitUtil.bytesFromReadableString("1234567890 Kib"));
+        // MB
+        Assert.assertEquals(0L, UnitUtil.bytesFromReadableString("0 MB"));
+        Assert.assertEquals(Bytes.MB * 1L,
+                            UnitUtil.bytesFromReadableString("1 MB"));
+        Assert.assertEquals((long) (Bytes.MB * 3.14),
+                            UnitUtil.bytesFromReadableString("3.14 MB"));
+        Assert.assertEquals(Bytes.MB * 10L,
+                            UnitUtil.bytesFromReadableString("10 mB"));
+        Assert.assertEquals(Bytes.MB * 100L,
+                            UnitUtil.bytesFromReadableString("100 MiB"));
+        Assert.assertEquals(Bytes.MB * 1000L,
+                            UnitUtil.bytesFromReadableString("1000 mib"));
+        Assert.assertEquals(Bytes.MB * 1023L,
+                            UnitUtil.bytesFromReadableString("1023 MIB"));
+        Assert.assertEquals(Bytes.MB * 1234567890L,
+                            UnitUtil.bytesFromReadableString("1234567890 Mb"));
+
+        // GB
+        Assert.assertEquals(0L, UnitUtil.bytesFromReadableString("0 GB"));
+        Assert.assertEquals(Bytes.GB * 1L,
+                            UnitUtil.bytesFromReadableString("1 GB"));
+        Assert.assertEquals((long) (Bytes.GB * 3.14),
+                            UnitUtil.bytesFromReadableString("3.14 GB"));
+        Assert.assertEquals(Bytes.GB * 10L,
+                            UnitUtil.bytesFromReadableString("10 gB"));
+        Assert.assertEquals(Bytes.GB * 100L,
+                            UnitUtil.bytesFromReadableString("100 GiB"));
+        Assert.assertEquals(Bytes.GB * 1000L,
+                            UnitUtil.bytesFromReadableString("1000 gib"));
+        Assert.assertEquals(Bytes.GB * 1023L,
+                            UnitUtil.bytesFromReadableString("1023 GIB"));
+        Assert.assertEquals(Bytes.GB * 1234567890L,
+                            UnitUtil.bytesFromReadableString("1234567890 Gb"));
+
+        // TB
+        Assert.assertEquals(0L, UnitUtil.bytesFromReadableString("0 TB"));
+        Assert.assertEquals(Bytes.TB * 1L,
+                            UnitUtil.bytesFromReadableString("1 TB"));
+        Assert.assertEquals((long) (Bytes.TB * 3.14),
+                            UnitUtil.bytesFromReadableString("3.14 TB"));
+        Assert.assertEquals(Bytes.TB * 10L,
+                            UnitUtil.bytesFromReadableString("10 tB"));
+        Assert.assertEquals(Bytes.TB * 100L,
+                            UnitUtil.bytesFromReadableString("100 TiB"));
+        Assert.assertEquals(Bytes.TB * 1000L,
+                            UnitUtil.bytesFromReadableString("1000 tib"));
+        Assert.assertEquals(Bytes.TB * 1023L,
+                            UnitUtil.bytesFromReadableString("1023 TIB"));
+        Assert.assertEquals(Bytes.TB * 123456L,
+                            UnitUtil.bytesFromReadableString("123456 Tb"));
+
+        // PB
+        Assert.assertEquals(0L, UnitUtil.bytesFromReadableString("0 PB"));
+        Assert.assertEquals(Bytes.PB * 1L,
+                            UnitUtil.bytesFromReadableString("1 PB"));
+        Assert.assertEquals((long) (Bytes.PB * 3.14),
+                            UnitUtil.bytesFromReadableString("3.14 PB"));
+        Assert.assertEquals(Bytes.PB * 10L,
+                            UnitUtil.bytesFromReadableString("10 pB"));
+        Assert.assertEquals(Bytes.PB * 100L,
+                            UnitUtil.bytesFromReadableString("100 PiB"));
+        Assert.assertEquals(Bytes.PB * 1000L,
+                            UnitUtil.bytesFromReadableString("1000 pib"));
+        Assert.assertEquals(Bytes.PB * 1023L,
+                            UnitUtil.bytesFromReadableString("1023 PIB"));
+        Assert.assertEquals(Bytes.PB * 8024L,
+                            UnitUtil.bytesFromReadableString("8024 PIB"));
+
+        // EB
+        Assert.assertEquals(0L, UnitUtil.bytesFromReadableString("0 EB"));
+        Assert.assertEquals(Bytes.EB * 1L,
+                            UnitUtil.bytesFromReadableString("1 EB"));
+        Assert.assertEquals((long) (Bytes.EB * 3.14),
+                            UnitUtil.bytesFromReadableString("3.14 EB"));
+        Assert.assertEquals((long) (Bytes.EB * 5.01),
+                            UnitUtil.bytesFromReadableString("5.01 eB"));
+        Assert.assertEquals((long) (Bytes.EB * 6.28),
+                            UnitUtil.bytesFromReadableString("6.28 EiB"));
+        Assert.assertEquals((long) (Bytes.EB * 7.9876),
+                            UnitUtil.bytesFromReadableString("7.9876 eib"));
+        Assert.assertEquals((long) (Bytes.EB * 8.0),
+                            UnitUtil.bytesFromReadableString("8.0 EIB")); // max
+    }
+
+    @Test
+    public void testBytesFromReadableStringWithInvalidFormat() {
+        // No space
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("1kb");
+        }, e -> {
+            Assert.assertContains("Invalid readable bytes '1kb'",
+                                  e.getMessage());
+        });
+
+        // Invalid unit
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("1 aBc");
+        }, e -> {
+            Assert.assertContains("Unrecognized unit aBc", e.getMessage());
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("1 k");
+        }, e -> {
+            Assert.assertContains("Unrecognized unit k", e.getMessage());
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("1 m");
+        }, e -> {
+            Assert.assertContains("Unrecognized unit m", e.getMessage());
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("1 2 MB");
+        }, e -> {
+            Assert.assertContains("Unrecognized unit 2 MB", e.getMessage());
+        });
+
+        // Invalid number
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("2b kb");
+        }, e -> {
+            Assert.assertContains("Invalid parameter(not number): '2b kb'",
+                                  e.getMessage());
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("2.3.4 kb");
+        }, e -> {
+            Assert.assertContains("Invalid parameter(not number): '2.3.4 kb'",
+                                  e.getMessage());
+        });
+
+        // Bytes overflow long value
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("8.1 EIB");
+        }, e -> {
+            Assert.assertContains("The value 9.33866418731546E18 from " +
+                                  "parameter '8.1 EIB' is out of range",
+                                  e.getMessage());
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("9024 Pb");
+        }, e -> {
+            Assert.assertContains("is out of range", e.getMessage());
+        });
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            UnitUtil.bytesFromReadableString("12345678 Tb");
+        }, e -> {
+            Assert.assertContains("is out of range", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testTimestampToReadableString() {
+        Assert.assertEquals("0ms",
+                            UnitUtil.timestampToReadableString(0L));
+        Assert.assertEquals("1ms",
+                            UnitUtil.timestampToReadableString(1L));
+        Assert.assertEquals("100ms",
+                            UnitUtil.timestampToReadableString(100L));
+        Assert.assertEquals("999ms",
+                            UnitUtil.timestampToReadableString(999L));
+
+        Assert.assertEquals("1s",
+                            UnitUtil.timestampToReadableString(1000L));
+        Assert.assertEquals("10s",
+                            UnitUtil.timestampToReadableString(10000L));
+        Assert.assertEquals("1s1ms",
+                            UnitUtil.timestampToReadableString(1001L));
+        Assert.assertEquals("1s200ms",
+                            UnitUtil.timestampToReadableString(1200L));
+        Assert.assertEquals("6s789ms",
+                            UnitUtil.timestampToReadableString(6789L));
+        Assert.assertEquals("59s789ms",
+                            UnitUtil.timestampToReadableString(59789L));
+
+        Assert.assertEquals("1m0s",
+                            UnitUtil.timestampToReadableString(60789L));
+        Assert.assertEquals("1m1s",
+                            UnitUtil.timestampToReadableString(61789L));
+        Assert.assertEquals("1m2s",
+                            UnitUtil.timestampToReadableString(62000L));
+        Assert.assertEquals("2m2s",
+                            UnitUtil.timestampToReadableString(122000L));
+        Assert.assertEquals("2m12s",
+                            UnitUtil.timestampToReadableString(132000L));
+        Assert.assertEquals("59m59s",
+                            UnitUtil.timestampToReadableString(3599000L));
+
+        Assert.assertEquals("1h0m0s",
+                            UnitUtil.timestampToReadableString(3600000L));
+        Assert.assertEquals("1h0m23s",
+                            UnitUtil.timestampToReadableString(3623000L));
+        Assert.assertEquals("1h1m23s",
+                            UnitUtil.timestampToReadableString(3683000L));
+        Assert.assertEquals("1h24m43s",
+                            UnitUtil.timestampToReadableString(5083000L));
+        Assert.assertEquals("23h59m59s",
+                            UnitUtil.timestampToReadableString(86399000L));
+
+        Assert.assertEquals("1d0h0m0s",
+                            UnitUtil.timestampToReadableString(86400000L));
+        Assert.assertEquals("1d1h24m43s",
+                            UnitUtil.timestampToReadableString(91483000L));
+        Assert.assertEquals("1d1h24m43s",
+                            UnitUtil.timestampToReadableString(91483000L));
+
+        Assert.assertEquals("30d0h0m0s",
+                            UnitUtil.timestampToReadableString(2592000000L));
+        Assert.assertEquals("30d23h59m59s",
+                            UnitUtil.timestampToReadableString(2678399000L));
+        Assert.assertEquals("130d23h59m59s",
+                            UnitUtil.timestampToReadableString(11318399000L));
+        Assert.assertEquals("1130d23h59m59s",
+                            UnitUtil.timestampToReadableString(97718399000L));
+    }
+
+    @Test
+    public void testTimestampFromReadableString() {
+        Assert.assertEquals(0L,
+                            UnitUtil.timestampFromReadableString("0ms"));
+        Assert.assertEquals(1L,
+                            UnitUtil.timestampFromReadableString("1ms"));
+        Assert.assertEquals(100L,
+                            UnitUtil.timestampFromReadableString("100ms"));
+        Assert.assertEquals(999L,
+                            UnitUtil.timestampFromReadableString("999ms"));
+        Assert.assertEquals(1001L,
+                            UnitUtil.timestampFromReadableString("1001ms"));
+
+        Assert.assertEquals(0L,
+                            UnitUtil.timestampFromReadableString("0s"));
+        Assert.assertEquals(1000L,
+                            UnitUtil.timestampFromReadableString("1s"));
+        Assert.assertEquals(10000L,
+                            UnitUtil.timestampFromReadableString("10s"));
+        Assert.assertEquals(1001L,
+                            UnitUtil.timestampFromReadableString("1s1ms"));
+        Assert.assertEquals(1200L,
+                            UnitUtil.timestampFromReadableString("1s200ms"));
+        Assert.assertEquals(6789L,
+                            UnitUtil.timestampFromReadableString("6s789ms"));
+        Assert.assertEquals(59789L,
+                            UnitUtil.timestampFromReadableString("59s789ms"));
+        Assert.assertEquals(59789L,
+                            UnitUtil.timestampFromReadableString("59s2789ms"));
+
+        Assert.assertEquals(60000L,
+                            UnitUtil.timestampFromReadableString("1m0s"));
+        Assert.assertEquals(61000L,
+                            UnitUtil.timestampFromReadableString("1m1s"));
+        Assert.assertEquals(62000L,
+                            UnitUtil.timestampFromReadableString("1m2s"));
+        Assert.assertEquals(122000L,
+                            UnitUtil.timestampFromReadableString("2m2s"));
+        Assert.assertEquals(132000L,
+                            UnitUtil.timestampFromReadableString("2m12s"));
+        Assert.assertEquals(3599000L,
+                            UnitUtil.timestampFromReadableString("59m59s"));
+
+        Assert.assertEquals(3600000L,
+                            UnitUtil.timestampFromReadableString("1h0m0s"));
+        Assert.assertEquals(3623000L,
+                            UnitUtil.timestampFromReadableString("1h0m23s"));
+        Assert.assertEquals(3683000L,
+                            UnitUtil.timestampFromReadableString("1h1m23s"));
+        Assert.assertEquals(5083000L,
+                            UnitUtil.timestampFromReadableString("1h24m43s"));
+        Assert.assertEquals(86399000L,
+                            UnitUtil.timestampFromReadableString("23h59m59s"));
+
+        Assert.assertEquals(86400000L,
+                            UnitUtil.timestampFromReadableString("1d0h0m0s"));
+        Assert.assertEquals(91483000L,
+                            UnitUtil.timestampFromReadableString("1d1h24m43s"));
+        Assert.assertEquals(91483000L,
+                            UnitUtil.timestampFromReadableString("1d1h24m43s"));
+
+        Assert.assertEquals(2592000000L, UnitUtil.timestampFromReadableString(
+                                         "30d0h0m0s"));
+        Assert.assertEquals(2678399000L, UnitUtil.timestampFromReadableString(
+                                         "30d23h59m59s"));
+        Assert.assertEquals(11318399000L, UnitUtil.timestampFromReadableString(
+                                          "130d23h59m59s"));
+        Assert.assertEquals(97718399000L, UnitUtil.timestampFromReadableString(
+                                          "1130d23h59m59s"));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/VersionUtilTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/VersionUtilTest.java
new file mode 100644
index 0000000000..25f6ef129a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/VersionUtilTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.hugegraph.unit.util;
+
+import java.net.MalformedURLException;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.util.VersionUtil;
+import org.apache.hugegraph.util.VersionUtil.Version;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.unit.BaseUnitTest;
+
+public class VersionUtilTest extends BaseUnitTest {
+
+    @Test
+    public void testVersionWithTwoPart() {
+        Version version = Version.of("0.2");
+
+        Assert.assertTrue(VersionUtil.match(version, "0", "1"));
+        Assert.assertTrue(VersionUtil.match(version, "0.0", "1.0"));
+        Assert.assertTrue(VersionUtil.match(version, "0.1", "0.3"));
+        Assert.assertTrue(VersionUtil.match(version, "0.2", "0.3"));
+        Assert.assertTrue(VersionUtil.match(version, "0.2", "0.2.1"));
+        Assert.assertTrue(VersionUtil.match(version, "0.2", "0.2.01"));
+        Assert.assertTrue(VersionUtil.match(version, "0.2", "0.10"));
+        Assert.assertTrue(VersionUtil.match(version, "0.2", "1.0"));
+
+        Assert.assertFalse(VersionUtil.match(version, "1", "0.3"));
+        Assert.assertFalse(VersionUtil.match(version, "0.3", "0.4"));
+        Assert.assertFalse(VersionUtil.match(version, "0.2", "0.1"));
+        Assert.assertFalse(VersionUtil.match(version, "0.2", "0.2"));
+        Assert.assertFalse(VersionUtil.match(version, "0.2", "0.2.0"));
+        Assert.assertFalse(VersionUtil.match(version, "0.3", "0.1"));
+    }
+
+    @Test
+    public void testVersionWithThreePart() {
+        Version version = Version.of("3.2.5");
+
+        Assert.assertTrue(VersionUtil.match(version, "2", "4"));
+        Assert.assertTrue(VersionUtil.match(version, "3", "4"));
+        Assert.assertTrue(VersionUtil.match(version, "3.1", "3.3"));
+        Assert.assertTrue(VersionUtil.match(version, "3.2", "3.3"));
+        Assert.assertTrue(VersionUtil.match(version, "3.2.4", "3.3"));
+        Assert.assertTrue(VersionUtil.match(version, "3.2.5", "3.3"));
+        Assert.assertTrue(VersionUtil.match(version, "3.2.5", "3.2.6"));
+        Assert.assertTrue(VersionUtil.match(version, "3.2.5", "3.2.10"));
+        Assert.assertTrue(VersionUtil.match(version, "3.2.5", "3.20.0"));
+
+        Assert.assertFalse(VersionUtil.match(version, "2", "3"));
+        Assert.assertFalse(VersionUtil.match(version, "3.3", "3.1"));
+        Assert.assertFalse(VersionUtil.match(version, "3.3", "3.2"));
+        Assert.assertFalse(VersionUtil.match(version, "3.3", "3.2"));
+        Assert.assertFalse(VersionUtil.match(version, "3.2.5", "3.2.5"));
+        Assert.assertFalse(VersionUtil.match(version, "3.2.6", "3.2.5"));
+        Assert.assertFalse(VersionUtil.match(version, "3.2.6", "3.2.4"));
+        Assert.assertFalse(VersionUtil.match(version, "3.2.50", "3.2.6"));
+        Assert.assertFalse(VersionUtil.match(version, "3.20.0", "3.3"));
+    }
+
+    @Test
+    public void testVersionGte() {
+        String version = "0.2";
+
+        Assert.assertTrue(VersionUtil.gte(version, "0.2"));
+        Assert.assertTrue(VersionUtil.gte(version, "0.2.0"));
+        Assert.assertTrue(VersionUtil.gte(version, "0.1"));
+        Assert.assertTrue(VersionUtil.gte(version, "0.1.9"));
+        Assert.assertTrue(VersionUtil.gte(version, "0.0.3"));
+
+        Assert.assertFalse(VersionUtil.gte(version, "0.2.0.1"));
+        Assert.assertFalse(VersionUtil.gte(version, "0.2.1"));
+        Assert.assertFalse(VersionUtil.gte(version, "0.3"));
+        Assert.assertFalse(VersionUtil.gte(version, "0.10"));
+    }
+
+    @Test
+    public void testVersionCheck() {
+        Version version = Version.of("0.6.5");
+
+        VersionUtil.check(version, "0.6", "0.7", "test-component");
+        VersionUtil.check(version, "0.6.5", "0.7", "test-component");
+        VersionUtil.check(version, "0.6.5", "0.6.6", "test-component");
+
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            VersionUtil.check(version, "0.6.5", "0.6.5", "test-component");
+        });
+
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            VersionUtil.check(version, "0.6.5", "0.6", "test-component");
+        });
+
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            VersionUtil.check(version, "0.7", "0.6", "test-component");
+        });
+
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            VersionUtil.check(version, "0.5", "0.6", "test-component");
+        });
+
+        Assert.assertThrows(IllegalStateException.class, () -> {
+            VersionUtil.check(version, "0.7", "1.0", "test-component");
+        });
+    }
+
+    @Test
+    public void testGetImplementationVersion() throws MalformedURLException {
+        // Can't mock Class: https://github.com/mockito/mockito/issues/1734
+        //Class<?> clazz = Mockito.mock(Class.class);
+        //Mockito.when(clazz.getSimpleName()).thenReturn("fake");
+        //Mockito.when(clazz.getResource("fake.class")).thenReturn(manifest);
+
+        String manifestPath = "file:./src/test/resources";
+        Assert.assertEquals("1.8.8.0",
+                            VersionUtil.getImplementationVersion(manifestPath));
+
+        manifestPath = "file:./src/test/resources2";
+        Assert.assertNull(VersionUtil.getImplementationVersion(manifestPath));
+    }
+
+    @Test
+    public void testVersion() {
+        // Test equals
+        Version v1 = Version.of("0.2.1");
+        Version v2 = Version.of("0.2.1");
+        Assert.assertEquals(v1, v1);
+        Assert.assertEquals(v1, v2);
+
+        Version v3 = Version.of("0.2.0");
+        Version v4 = Version.of("0.2");
+        Assert.assertEquals(v3, v4);
+
+        Version v5 = Version.of("0.2.3");
+        Version v6 = Version.of("0.3.2");
+        Assert.assertNotEquals(v5, v6);
+        Assert.assertNotEquals(v5, null);
+        Assert.assertNotEquals(v5, "0.2.3");
+
+        // Test hashCode
+        Assert.assertEquals(1023, v1.hashCode());
+        Assert.assertEquals(1023, v2.hashCode());
+        Assert.assertEquals(62, v3.hashCode());
+        Assert.assertEquals(62, v4.hashCode());
+        Assert.assertEquals(2945, v5.hashCode());
+        Assert.assertEquals(2015, v6.hashCode());
+
+        // Test compareTo
+        Assert.assertEquals(0, v1.compareTo(v2));
+        Assert.assertEquals(1, v1.compareTo(v3));
+        Assert.assertEquals(-1, v1.compareTo(v5));
+        Assert.assertEquals(1, v1.compareTo(null));
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/version/VersionTest.java b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/version/VersionTest.java
new file mode 100644
index 0000000000..432d66ee31
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/java/org/apache/hugegraph/unit/version/VersionTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.unit.version;
+
+import org.apache.hugegraph.util.VersionUtil;
+import org.junit.Test;
+
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.version.CommonVersion;
+
+public class VersionTest {
+
+    @Test
+    public void testGetCommonVersion() {
+        String pomVersion = VersionUtil.getPomVersion();
+        Assert.assertNotNull(pomVersion);
+        String version = CommonVersion.VERSION.get();
+        Assert.assertNotNull(version);
+        Assert.assertEquals(pomVersion, version);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/resources/META-INF/MANIFEST.MF b/hugegraph-commons/hugegraph-common/src/test/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..7abb11a917
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+Implementation-Version: 1.8.8.0
+Archiver-Version: Plexus Archiver
+Built-By: jermy
+Specification-Title: hugegraph-common
+Created-By: Apache Maven 3.3.9
+Build-Jdk: 1.8.0_111
+Specification-Version: 1.8.8
diff --git a/hugegraph-commons/hugegraph-common/src/test/resources/create-license.json b/hugegraph-commons/hugegraph-common/src/test/resources/create-license.json
new file mode 100644
index 0000000000..c1131312c9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/resources/create-license.json
@@ -0,0 +1,19 @@
+{
+  "subject": "hugegraph-evaluation",
+  "private_alias": "privatekey",
+  "key_ticket": "a123456",
+  "store_ticket": "a123456",
+  "privatekey_path": "src/test/resources/privateKeys.store",
+  "license_path": "src/test/resources/hugegraph-evaluation.license",
+  "issued_time": "2019-08-01 00:00:00",
+  "not_before": "2019-08-01 00:00:00",
+  "not_after": "2029-08-01 00:00:00",
+  "consumer_type": "user",
+  "consumer_amount": 1,
+  "extra_params": [
+    {
+      "id": "server-1",
+      "graphs": 3
+    }
+  ]
+}
diff --git a/hugegraph-commons/hugegraph-common/src/test/resources/log4j2.xml b/hugegraph-commons/hugegraph-common/src/test/resources/log4j2.xml
new file mode 100644
index 0000000000..5ada1de623
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/resources/log4j2.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<configuration status="error">
+    <appenders>
+        <Console name="console" target="SYSTEM_OUT">
+            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
+            <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %-5r [%t] [%-5p] %c %x - %m%n"/>
+        </Console>
+
+        <RollingFile name="file" fileName="logs/hugegraph-common.log"
+                     filePattern="logs/$${date:yyyy-MM}/hugegraph-common-%d{yyyy-MM-dd}-%i.log">
+            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
+            <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %-5r [%t] [%-5p] %c %x - %m%n"/>
+            <SizeBasedTriggeringPolicy size="100MB"/>
+        </RollingFile>
+    </appenders>
+    <loggers>
+        <root level="INFO">
+            <appender-ref ref="console"/>
+            <appender-ref ref="file"/>
+        </root>
+        <logger name="org.apache.hugegraph" level="INFO" additivity="false">
+            <appender-ref ref="console"/>
+            <appender-ref ref="file"/>
+        </logger>
+    </loggers>
+</configuration>
diff --git a/hugegraph-commons/hugegraph-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/hugegraph-commons/hugegraph-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..a76010b24c
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+mock-maker-inline
diff --git a/hugegraph-commons/hugegraph-common/src/test/resources/verify-license.json b/hugegraph-commons/hugegraph-common/src/test/resources/verify-license.json
new file mode 100644
index 0000000000..779c5d6883
--- /dev/null
+++ b/hugegraph-commons/hugegraph-common/src/test/resources/verify-license.json
@@ -0,0 +1,7 @@
+{
+  "subject": "hugegraph-evaluation",
+  "public_alias": "publiccert",
+  "store_ticket": "a123456",
+  "publickey_path": "src/test/resources/publicCerts.store",
+  "license_path": "src/test/resources/hugegraph-evaluation.license"
+}
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/LICENSE b/hugegraph-commons/hugegraph-dist/release-docs/LICENSE
new file mode 100644
index 0000000000..ab02e44829
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/LICENSE
@@ -0,0 +1,338 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+
+
+============================================================================
+   APACHE HUGEGRAPH (Incubating) SUBCOMPONENTS:
+
+   The Apache HugeGraph(Incubating) project contains subcomponents with separate copyright
+   notices and license terms. Your use of the source code for the these
+   subcomponents is subject to the terms and conditions of the following
+   licenses.
+
+
+========================================================================
+Third party Apache 2.0 licenses
+========================================================================
+
+The following components are provided under the Apache 2.0 License.
+See licenses/ for text of these licenses.
+
+    (Apache License, 2.0) Javassist (org.javassist:javassist:3.28.0-GA - http://www.javassist.org/)
+    (Apache License, Version 2.0) * Apache Commons BeanUtils:- commons-beanutils:commons-beanutils:1.9.4 (https://commons.apache.org/proper/commons-beanutils/)
+    (Apache License, Version 2.0) * Apache Commons Codec:- commons-codec:commons-codec:1.13 (https://commons.apache.org/proper/commons-codec/)
+    (Apache License, Version 2.0) * Apache Commons Collections:- commons-collections:commons-collections:3.2.2 (http://commons.apache.org/collections/)
+    (Apache License, Version 2.0) * Apache Commons Configuration:- commons-configuration:commons-configuration:1.10 (http://commons.apache.org/configuration/)- org.apache.commons:commons-configuration2:2.8.0 (https://commons.apache.org/proper/commons-configuration/)
+    (Apache License, Version 2.0) * Apache Commons IO:- commons-io:commons-io:2.7 (https://commons.apache.org/proper/commons-io/)
+    (Apache License, Version 2.0) * Apache Commons Lang:- org.apache.commons:commons-lang3:3.12.0 (https://commons.apache.org/proper/commons-lang/)
+    (Apache License, Version 2.0) * Apache Commons Text:- org.apache.commons:commons-text:1.9 (https://commons.apache.org/proper/commons-text)
+    (Apache License, Version 2.0) * Apache HttpClient:- org.apache.httpcomponents:httpclient:4.5.13 (http://hc.apache.org/httpcomponents-client)
+    (Apache License, Version 2.0) * Apache HttpCore:- org.apache.httpcomponents:httpcore:4.4.13 (http://hc.apache.org/httpcomponents-core-ga)
+    (Apache License, Version 2.0) * Apache Log4j API:- org.apache.logging.log4j:log4j-api:2.18.0 (https://logging.apache.org/log4j/2.x/log4j-api/)
+    (Apache License, Version 2.0) * Apache Log4j Core:- org.apache.logging.log4j:log4j-core:2.18.0 (https://logging.apache.org/log4j/2.x/log4j-core/)
+    (Apache License, Version 2.0) * Apache Log4j SLF4J Binding:- org.apache.logging.log4j:log4j-slf4j-impl:2.18.0 (https://logging.apache.org/log4j/2.x/log4j-slf4j-impl/)
+    (Apache License, Version 2.0) * Bean Validation API:- javax.validation:validation-api:1.1.0.Final (http://beanvalidation.org)
+    (Apache License, Version 2.0) * Byte Buddy (without dependencies):- net.bytebuddy:byte-buddy:1.12.1 (https://bytebuddy.net/byte-buddy)
+    (Apache License, Version 2.0) * Byte Buddy agent:- net.bytebuddy:byte-buddy-agent:1.12.1 (https://bytebuddy.net/byte-buddy-agent)
+    (Apache License, Version 2.0) * Commons Lang:- commons-lang:commons-lang:2.6 (http://commons.apache.org/lang/)
+    (Apache License, Version 2.0) * Commons Logging:- commons-logging:commons-logging:1.1.1 (http://commons.apache.org/logging)
+    (Apache License, Version 2.0) * Disruptor Framework:- com.lmax:disruptor:3.3.7 (http://lmax-exchange.github.com/disruptor)
+    (Apache License, Version 2.0) * FindBugs-jsr305:- com.google.code.findbugs:jsr305:3.0.1 (http://findbugs.sourceforge.net/)
+    (Apache License, Version 2.0) * Google Android Annotations Library:- com.google.android:annotations:4.1.1.4 (http://source.android.com/)
+    (Apache License, Version 2.0) * Gson:- com.google.code.gson:gson:2.8.6 (https://github.com/google/gson/gson)
+    (Apache License, Version 2.0) * Guava InternalFutureFailureAccess and InternalFutures:- com.google.guava:failureaccess:1.0.1 (https://github.com/google/guava/failureaccess)
+    (Apache License, Version 2.0) * Guava ListenableFuture only:- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava (https://github.com/google/guava/listenablefuture)
+    (Apache License, Version 2.0) * Guava: Google Core Libraries for Java:- com.google.guava:guava:30.0-jre (https://github.com/google/guava/guava)
+    (Apache License, Version 2.0) * J2ObjC Annotations:- com.google.j2objc:j2objc-annotations:1.3 (https://github.com/google/j2objc/)
+    (Apache License, Version 2.0) * Jackson module: Old JAXB Annotations (javax.xml.bind):- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.14.0-rc1 (https://github.com/FasterXML/jackson-modules-base)
+    (Apache License, Version 2.0) * Jackson-JAXRS: JSON:- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.14.0-rc1 (https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-json-provider)
+    (Apache License, Version 2.0) * Jackson-JAXRS: base:- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.14.0-rc1 (https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-base)
+    (Apache License, Version 2.0) * Jackson-annotations:- com.fasterxml.jackson.core:jackson-annotations:2.14.0-rc1 (https://github.com/FasterXML/jackson)
+    (Apache License, Version 2.0) * Jackson-core:- com.fasterxml.jackson.core:jackson-core:2.14.0-rc1 (https://github.com/FasterXML/jackson-core)
+    (Apache License, Version 2.0) * Jackson-dataformat-YAML:- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.3 (https://github.com/FasterXML/jackson-dataformats-text)
+    (Apache License, Version 2.0) * Joda-Time:- joda-time:joda-time:2.10.8 (https://www.joda.org/joda-time/)
+    (Apache License, Version 2.0) * Netty/All-in-One:- io.netty:netty-all:4.1.42.Final (https://netty.io/netty-all/)
+    (Apache License, Version 2.0) * Objenesis:- org.objenesis:objenesis:3.2 (http://objenesis.org/objenesis)
+    (Apache License, Version 2.0) * OpenTracing API:- io.opentracing:opentracing-api:0.22.0 (https://github.com/opentracing/opentracing-java/opentracing-api)
+    (Apache License, Version 2.0) * OpenTracing-mock:- io.opentracing:opentracing-mock:0.22.0 (https://github.com/opentracing/opentracing-java/opentracing-mock)
+    (Apache License, Version 2.0) * OpenTracing-noop:- io.opentracing:opentracing-noop:0.22.0 (https://github.com/opentracing/opentracing-java/opentracing-noop)
+    (Apache License, Version 2.0) * OpenTracing-util:- io.opentracing:opentracing-util:0.22.0 (https://github.com/opentracing/opentracing-java/opentracing-util)
+    (Apache License, Version 2.0) * SnakeYAML:- org.yaml:snakeyaml:1.18 (http://www.snakeyaml.org)
+    (Apache License, Version 2.0) * com.alipay.sofa.common:sofa-common-tools:- com.alipay.sofa.common:sofa-common-tools:1.0.12 (https://github.com/sofastack/sofa-common-tools)
+    (Apache License, Version 2.0) * com.alipay.sofa:bolt:- com.alipay.sofa:bolt:1.6.2 (https://github.com/alipay/sofa-bolt)
+    (Apache License, Version 2.0) * com.alipay.sofa:hessian:- com.alipay.sofa:hessian:3.3.7 (http://github.com/alipay/sofa-hessian)
+    (Apache License, Version 2.0) * com.alipay.sofa:sofa-rpc-all:- com.alipay.sofa:sofa-rpc-all:5.7.6 (http://github.com/sofastack/sofa-rpc)
+    (Apache License, Version 2.0) * error-prone annotations:- com.google.errorprone:error_prone_annotations:2.3.4 (http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/error_prone_annotations)
+    (Apache License, Version 2.0) * io.grpc:grpc-api:- io.grpc:grpc-api:1.28.0 (https://github.com/grpc/grpc-java)
+    (Apache License, Version 2.0) * io.grpc:grpc-context:- io.grpc:grpc-context:1.28.0 (https://github.com/grpc/grpc-java)
+    (Apache License, Version 2.0) * io.grpc:grpc-core:- io.grpc:grpc-core:1.28.0 (https://github.com/grpc/grpc-java)
+    (Apache License, Version 2.0) * io.grpc:grpc-netty-shaded:- io.grpc:grpc-netty-shaded:1.28.0 (https://github.com/grpc/grpc-java)
+    (Apache License, Version 2.0) * io.grpc:grpc-protobuf:- io.grpc:grpc-protobuf:1.28.0 (https://github.com/grpc/grpc-java)
+    (Apache License, Version 2.0) * io.grpc:grpc-protobuf-lite:- io.grpc:grpc-protobuf-lite:1.28.0 (https://github.com/grpc/grpc-java)
+    (Apache License, Version 2.0) * io.grpc:grpc-stub:- io.grpc:grpc-stub:1.28.0 (https://github.com/grpc/grpc-java)
+    (Apache License, Version 2.0) * jackson-databind:- com.fasterxml.jackson.core:jackson-databind:2.14.0-rc1 (https://github.com/FasterXML/jackson)
+    (Apache License, Version 2.0) * lookout-api:- com.alipay.sofa.lookout:lookout-api:1.4.1 (https://github.com/sofastack/sofa-lookout/lookout-api)
+    (Apache License, Version 2.0) * perfmark:perfmark-api:- io.perfmark:perfmark-api:0.19.0 (https://github.com/perfmark/perfmark)
+    (Apache License, Version 2.0) * proto-google-common-protos:- com.google.api.grpc:proto-google-common-protos:1.17.0 (https://github.com/googleapis/api-client-staging)
+    (Apache License, Version 2.0) * swagger-annotations:- io.swagger:swagger-annotations:1.5.18 (https://github.com/swagger-api/swagger-core/modules/swagger-annotations)
+    (Apache License, Version 2.0) * swagger-core:- io.swagger:swagger-core:1.5.18 (https://github.com/swagger-api/swagger-core/modules/swagger-core)
+    (Apache License, Version 2.0) * swagger-models:- io.swagger:swagger-models:1.5.18 (https://github.com/swagger-api/swagger-core/modules/swagger-models)
+    (Apache License, Version 2.0) * tracer-core:- com.alipay.sofa:tracer-core:3.0.8 (https://projects.spring.io/spring-boot/#/spring-boot-starter-parent/sofaboot-dependencies/tracer-all-parent/tracer-core)
+    (Apache License, Version 2.0) * OkHttp (com.squareup.okhttp3:okhttp:4.10.0 - https://github.com/square/okhttp)
+    (Apache License, Version 2.0) * OkHttp (com.squareup.okhttp3:logging-interceptor:4.10.0 - https://github.com/square/okhttp)
+
+========================================================================
+Third party CDDL licenses
+========================================================================
+
+The following components are provided under the CDDL License.
+See licenses/ for text of these licenses.
+   (CDDL) * JavaBeans Activation Framework API jar:- javax.activation:javax.activation-api:1.2.0 (http://java.net/all/javax.activation-api/)
+   (CDDL 1.1)  * jaxb-api:- javax.xml.bind:jaxb-api:2.3.1 (https://github.com/javaee/jaxb-spec/jaxb-api)
+   (Dual license consisting of the CDDL v1.1)  * Default Provider:- org.glassfish:javax.json:1.0 (http://jsonp.java.net)
+
+
+========================================================================
+Third party EPL licenses
+========================================================================
+
+The following components are provided under the EPL License.
+See licenses/ for text of these licenses.
+    (Eclipse Public License - v2.0) * HK2 API module:- org.glassfish.hk2:hk2-api:3.0.1 (https://github.com/eclipse-ee4j/glassfish-hk2/hk2-api)
+    (Eclipse Public License - v2.0) * HK2 Implementation Utilities:- org.glassfish.hk2:hk2-utils:3.0.1 (https://github.com/eclipse-ee4j/glassfish-hk2/hk2-utils)
+    (Eclipse Public License - v2.0) * OSGi resource locator:- org.glassfish.hk2:osgi-resource-locator:1.0.3 (https://projects.eclipse.org/projects/ee4j/osgi-resource-locator)
+    (Eclipse Public License - v2.0) * ServiceLocator Default Implementation:- org.glassfish.hk2:hk2-locator:3.0.1 (https://github.com/eclipse-ee4j/glassfish-hk2/hk2-locator)
+    (Eclipse Public License - v2.0) * aopalliance version 1.0 repackaged as a module:- org.glassfish.hk2.external:aopalliance-repackaged:3.0.1 (https://github.com/eclipse-ee4j/glassfish-hk2/external/aopalliance-repackaged)
+    (Eclipse Public License - v2.0) * JUnit:- junit:junit:4.13.1 (http://junit.org)
+
+========================================================================
+Third party EDL licenses
+========================================================================
+
+The following components are provided under the EDL License.
+See licenses/ for text of these licenses.
+    (Eclipse Distribution License - v1.0) * Jakarta Activation:- com.sun.activation:jakarta.activation:2.0.1 (https://github.com/eclipse-ee4j/jaf/jakarta.activation)
+    (Eclipse Distribution License - v1.0) * Jakarta Activation API jar:- jakarta.activation:jakarta.activation-api:1.2.2 (https://github.com/eclipse-ee4j/jaf/jakarta.activation-api)
+    (Eclipse Distribution License - v1.0) * Old JAXB Core:- com.sun.xml.bind:jaxb-core:3.0.2 (https://eclipse-ee4j.github.io/jaxb-ri/)
+    (Eclipse Distribution License - v1.0) * Old JAXB Runtime:- com.sun.xml.bind:jaxb-impl:3.0.2 (https://eclipse-ee4j.github.io/jaxb-ri/)
+
+
+========================================================================
+Third party BSD licenses
+========================================================================
+
+The following components are provided under the BSD License.
+See licenses/ for text of these licenses.
+    (The 3-Clause BSD License) * Hamcrest Core:- org.hamcrest:hamcrest-core:1.3 (https://github.com/hamcrest/JavaHamcrest/hamcrest-core)
+    (The 3-Clause BSD License) * Protocol Buffers [Core]:- com.google.protobuf:protobuf-java:3.11.0 (https://developers.google.com/protocol-buffers/protobuf-java/)
+
+========================================================================
+Third party MIT licenses
+========================================================================
+
+The following components are provided under the MIT License.
+See licenses/ for text of these licenses.
+    (The MIT License)* Animal Sniffer Annotations:- org.codehaus.mojo:animal-sniffer-annotations:1.18 (http://www.mojohaus.org/animal-sniffer/animal-sniffer-annotations)
+    (The MIT License)* Checker Qual:- org.checkerframework:checker-qual:3.5.0 (https://checkerframework.org)
+    (The MIT License)* SLF4J API Module:- org.slf4j:slf4j-api:1.7.25 (http://www.slf4j.org)
+    (The MIT License)* mockito-core:- org.mockito:mockito-core:4.1.0 (https://github.com/mockito/mockito)
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/NOTICE b/hugegraph-commons/hugegraph-dist/release-docs/NOTICE
new file mode 100644
index 0000000000..7d13a7d48f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/NOTICE
@@ -0,0 +1,935 @@
+Apache HugeGraph(incubating)
+Copyright 2022-2023 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+The initial codebase was donated to the ASF by HugeGraph Authors, copyright 2017-2021.
+
+========================================================================
+
+commons-logging NOTICE
+
+========================================================================
+// ------------------------------------------------------------------
+// NOTICE file corresponding to the section 4d of The Apache License,
+// Version 2.0, in this case for Commons Logging
+// ------------------------------------------------------------------
+
+Commons Logging
+Copyright 2001-2007 The Apache Software Foundation
+
+This product includes/uses software(s) developed by 'an unknown organization'
+  - Unnamed - avalon-framework:avalon-framework:jar:4.1.3
+  - Unnamed - log4j:log4j:jar:1.2.12
+  - Unnamed - logkit:logkit:jar:1.0.1
+
+
+========================================================================
+
+httpclient NOTICE
+
+========================================================================
+
+Apache HttpClient
+Copyright 1999-2020 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
+========================================================================
+
+httpcore NOTICE
+
+========================================================================
+
+Apache HttpCore
+Copyright 2005-2020 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
+========================================================================
+
+jackson-core-2.14.0 NOTICE
+
+========================================================================
+# Jackson JSON processor
+
+Jackson is a high-performance, Free/Open Source JSON processing library.
+It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
+been in development since 2007.
+It is currently developed by a community of developers.
+
+## Licensing
+
+Jackson 2.x core and extension components are licensed under Apache License 2.0
+To find the details that apply to this artifact see the accompanying LICENSE file.
+
+## Credits
+
+A list of contributors may be found from CREDITS(-2.x) file, which is included
+in some artifacts (usually source distributions); but is always available
+from the source code management (SCM) system project uses.
+========================================================================
+
+jackson-databind-2.14.0 NOTICE
+
+========================================================================
+# Jackson JSON processor
+
+Jackson is a high-performance, Free/Open Source JSON processing library.
+It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
+been in development since 2007.
+It is currently developed by a community of developers.
+
+## Licensing
+
+Jackson 2.x core and extension components are licensed under Apache License 2.0
+To find the details that apply to this artifact see the accompanying LICENSE file.
+
+## Credits
+
+A list of contributors may be found from CREDITS(-2.x) file, which is included
+in some artifacts (usually source distributions); but is always available
+from the source code management (SCM) system project uses.
+========================================================================
+
+jackson-dataformat-yaml NOTICE
+
+========================================================================
+# Jackson JSON processor
+
+Jackson is a high-performance, Free/Open Source JSON processing library.
+It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
+been in development since 2007.
+It is currently developed by a community of developers, as well as supported
+commercially by FasterXML.com.
+
+## Licensing
+
+Jackson core and extension components may be licensed under different licenses.
+To find the details that apply to this artifact see the accompanying LICENSE file.
+For more information, including possible other licensing options, contact
+FasterXML.com (http://fasterxml.com).
+
+## Credits
+
+A list of contributors may be found from CREDITS file, which is included
+in some artifacts (usually source distributions); but is always available
+from the source code management (SCM) system project uses.
+========================================================================
+
+jackson-jaxrs-json-provider-2.14.0 NOTICE
+
+========================================================================
+# Jackson JSON processor
+
+Jackson is a high-performance, Free/Open Source JSON processing library.
+It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
+been in development since 2007.
+It is currently developed by a community of developers, as well as supported
+commercially by FasterXML.com.
+
+## Licensing
+
+Jackson core and extension components may be licensed under different licenses.
+To find the details that apply to this artifact see the accompanying LICENSE file.
+For more information, including possible other licensing options, contact
+FasterXML.com (http://fasterxml.com).
+
+## Credits
+
+A list of contributors may be found from CREDITS file, which is included
+in some artifacts (usually source distributions); but is always available
+from the source code management (SCM) system project uses.
+========================================================================
+
+jackson-module-jaxb-annotations-2.14.0 NOTICE
+
+========================================================================
+# Jackson JSON processor
+
+Jackson is a high-performance, Free/Open Source JSON processing library.
+It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
+been in development since 2007.
+It is currently developed by a community of developers, as well as supported
+commercially by FasterXML.com.
+
+## Licensing
+
+Jackson core and extension components may licensed under different licenses.
+To find the details that apply to this artifact see the accompanying LICENSE file.
+For more information, including possible other licensing options, contact
+FasterXML.com (http://fasterxml.com).
+
+## Credits
+
+A list of contributors may be found from CREDITS file, which is included
+in some artifacts (usually source distributions); but is always available
+from the source code management (SCM) system project uses.
+========================================================================
+
+log4j-api NOTICE
+
+========================================================================
+
+Apache Log4j API
+Copyright 1999-2022 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
+========================================================================
+
+log4j-core NOTICE
+
+========================================================================
+Apache Log4j Core
+Copyright 1999-2012 Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+ResolverUtil.java
+Copyright 2005-2006 Tim Fennell
+
+========================================================================
+
+log4j-slf4j-impl NOTICE
+
+========================================================================
+
+Apache Log4j SLF4J Binding
+Copyright 1999-2022 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
+========================================================================
+
+gRPC NOTICE
+
+========================================================================
+
+
+Copyright 2014 The gRPC Authors
+
+Licensed 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.
+
+-----------------------------------------------------------------------
+
+This product contains a modified portion of 'OkHttp', an open source
+HTTP & SPDY client for Android and Java applications, which can be obtained
+at:
+
+  * LICENSE:
+    * okhttp/third_party/okhttp/LICENSE (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/square/okhttp
+  * LOCATION_IN_GRPC:
+    * okhttp/third_party/okhttp
+
+This product contains a modified portion of 'Envoy', an open source
+cloud-native high-performance edge/middle/service proxy, which can be
+obtained at:
+
+  * LICENSE:
+    * xds/third_party/envoy/LICENSE (Apache License 2.0)
+  * NOTICE:
+    * xds/third_party/envoy/NOTICE
+  * HOMEPAGE:
+    * https://www.envoyproxy.io
+  * LOCATION_IN_GRPC:
+    * xds/third_party/envoy
+
+This product contains a modified portion of 'protoc-gen-validate (PGV)',
+an open source protoc plugin to generate polyglot message validators,
+which can be obtained at:
+
+  * LICENSE:
+    * xds/third_party/protoc-gen-validate/LICENSE (Apache License 2.0)
+  * NOTICE:
+      * xds/third_party/protoc-gen-validate/NOTICE
+  * HOMEPAGE:
+    * https://github.com/envoyproxy/protoc-gen-validate
+  * LOCATION_IN_GRPC:
+    * xds/third_party/protoc-gen-validate
+
+This product contains a modified portion of 'udpa',
+an open source universal data plane API, which can be obtained at:
+
+  * LICENSE:
+    * xds/third_party/udpa/LICENSE (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/cncf/udpa
+  * LOCATION_IN_GRPC:
+    * xds/third_party/udpa
+
+========================================================================
+
+jaxb-ri NOTICE
+
+========================================================================
+# Notices for Eclipse Implementation of JAXB
+
+This content is produced and maintained by the Eclipse Implementation of JAXB
+project.
+
+* Project home: https://projects.eclipse.org/projects/ee4j.jaxb-impl
+
+## Trademarks
+
+Eclipse Implementation of JAXB is a trademark of the Eclipse Foundation.
+
+## Copyright
+
+All content is the property of the respective authors or their employers. For
+more information regarding authorship of content, please consult the listed
+source code repository logs.
+
+## Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Distribution License v. 1.0 which is available at
+http://www.eclipse.org/org/documents/edl-v10.php.
+
+SPDX-License-Identifier: BSD-3-Clause
+
+## Source Code
+
+The project maintains the following source code repositories:
+
+* https://github.com/eclipse-ee4j/jaxb-ri
+* https://github.com/eclipse-ee4j/jaxb-istack-commons
+* https://github.com/eclipse-ee4j/jaxb-dtd-parser
+* https://github.com/eclipse-ee4j/jaxb-fi
+* https://github.com/eclipse-ee4j/jaxb-stax-ex
+* https://github.com/eclipse-ee4j/jax-rpc-ri
+
+## Third-party Content
+
+This project leverages the following third party content.
+
+Apache Ant (1.10.2)
+
+* License: Apache-2.0 AND W3C AND LicenseRef-Public-Domain
+
+Apache Ant (1.10.2)
+
+* License: Apache-2.0 AND W3C AND LicenseRef-Public-Domain
+
+Apache Felix (1.2.0)
+
+* License: Apache License, 2.0
+
+args4j (2.33)
+
+* License: MIT License
+
+dom4j (1.6.1)
+
+* License: Custom license based on Apache 1.1
+
+file-management (3.0.0)
+
+* License: Apache-2.0
+* Project: https://maven.apache.org/shared/file-management/
+* Source:
+   https://svn.apache.org/viewvc/maven/shared/tags/file-management-3.0.0/
+
+JUnit (4.12)
+
+* License: Eclipse Public License
+
+JUnit (4.12)
+
+* License: Eclipse Public License
+
+maven-compat (3.5.2)
+
+* License: Apache-2.0
+* Project: https://maven.apache.org/ref/3.5.2/maven-compat/
+* Source:
+   https://mvnrepository.com/artifact/org.apache.maven/maven-compat/3.5.2
+
+maven-core (3.5.2)
+
+* License: Apache-2.0
+* Project: https://maven.apache.org/ref/3.5.2/maven-core/index.html
+* Source: https://mvnrepository.com/artifact/org.apache.maven/maven-core/3.5.2
+
+maven-plugin-annotations (3.5)
+
+* License: Apache-2.0
+* Project: https://maven.apache.org/plugin-tools/maven-plugin-annotations/
+* Source:
+   https://github.com/apache/maven-plugin-tools/tree/master/maven-plugin-annotations
+
+maven-plugin-api (3.5.2)
+
+* License: Apache-2.0
+
+maven-resolver-api (1.1.1)
+
+* License: Apache-2.0
+
+maven-resolver-api (1.1.1)
+
+* License: Apache-2.0
+
+maven-resolver-connector-basic (1.1.1)
+
+* License: Apache-2.0
+
+maven-resolver-impl (1.1.1)
+
+* License: Apache-2.0
+
+maven-resolver-spi (1.1.1)
+
+* License: Apache-2.0
+
+maven-resolver-transport-file (1.1.1)
+
+* License: Apache-2.0
+* Project: https://maven.apache.org/resolver/maven-resolver-transport-file/
+* Source:
+   https://github.com/apache/maven-resolver/tree/master/maven-resolver-transport-file
+
+maven-resolver-util (1.1.1)
+
+* License: Apache-2.0
+
+maven-settings (3.5.2)
+
+* License: Apache-2.0
+* Source:
+   https://mvnrepository.com/artifact/org.apache.maven/maven-settings/3.5.2
+
+OSGi Service Platform Core Companion Code (6.0)
+
+* License: Apache License, 2.0
+
+plexus-archiver (3.5)
+
+* License: Apache-2.0
+* Project: https://codehaus-plexus.github.io/plexus-archiver/
+* Source: https://github.com/codehaus-plexus/plexus-archiver
+
+plexus-io (3.0.0)
+
+* License: Apache-2.0
+
+plexus-utils (3.1.0)
+
+* License: Apache- 2.0 or Apache- 1.1 or BSD or Public Domain or Indiana
+   University Extreme! Lab Software License V1.1.1 (Apache 1.1 style)
+
+relaxng-datatype (1.0)
+
+* License: New BSD license
+
+Sax (0.2)
+
+* License: SAX-PD
+* Project: http://www.megginson.com/downloads/SAX/
+* Source: http://sourceforge.net/project/showfiles.php?group_id=29449
+
+testng (6.14.2)
+
+* License: Apache-2.0 AND (MIT )
+* Project: https://testng.org/doc/index.html
+* Source: https://github.com/cbeust/testng
+
+wagon-http-lightweight (3.0.0)
+
+* License: Pending
+* Project: https://maven.apache.org/wagon/
+* Source:
+   https://mvnrepository.com/artifact/org.apache.maven.wagon/wagon-http-lightweight/3.0.0
+
+xz for java (1.8)
+
+* License: LicenseRef-Public-Domain
+
+## Cryptography
+
+Content may contain encryption software. The country in which you are currently
+may have restrictions on the import, possession, and use, and/or re-export to
+another country, of encryption software. BEFORE using any encryption software,
+please check the country's laws, regulations and policies concerning the import,
+possession, or use, and re-export of encryption software, to see if this is
+permitted.
+
+
+========================================================================
+
+Swagger Core NOTICE
+
+========================================================================
+Swagger Core - ${pom.name}
+Copyright (c) 2015. SmartBear Software Inc.
+Swagger Core - ${pom.name}  is licensed under Apache 2.0 license.
+Copy of the Apache 2.0 license can be found in `LICENSE` file.
+
+
+========================================================================
+
+Joda time NOTICE
+
+========================================================================
+
+=============================================================================
+= NOTICE file corresponding to section 4d of the Apache License Version 2.0 =
+=============================================================================
+This product includes software developed by
+Joda.org (https://www.joda.org/).
+
+========================================================================
+
+Eclipse GlassFish NOTICE
+
+========================================================================
+
+# Notices for Eclipse GlassFish
+
+This content is produced and maintained by the Eclipse GlassFish project.
+
+* Project home: https://projects.eclipse.org/projects/ee4j.glassfish
+
+## Trademarks
+
+Eclipse GlassFish, and GlassFish are trademarks of the Eclipse Foundation.
+
+## Copyright
+
+All content is the property of the respective authors or their employers. For
+more information regarding authorship of content, please consult the listed
+source code repository logs.
+
+## Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License v. 2.0 which is available at
+http://www.eclipse.org/legal/epl-2.0. This Source Code may also be made
+available under the following Secondary Licenses when the conditions for such
+availability set forth in the Eclipse Public License v. 2.0 are satisfied: GNU
+General Public License, version 2 with the GNU Classpath Exception which is
+available at https://www.gnu.org/software/classpath/license.html.
+
+SPDX-License-Identifier: EPL-2.0
+
+## Source Code
+
+The project maintains the following source code repositories:
+
+* https://github.com/eclipse-ee4j/glassfish-ha-api
+* https://github.com/eclipse-ee4j/glassfish-logging-annotation-processor
+* https://github.com/eclipse-ee4j/glassfish-shoal
+* https://github.com/eclipse-ee4j/glassfish-cdi-porting-tck
+* https://github.com/eclipse-ee4j/glassfish-jsftemplating
+* https://github.com/eclipse-ee4j/glassfish-hk2-extra
+* https://github.com/eclipse-ee4j/glassfish-hk2
+* https://github.com/eclipse-ee4j/glassfish-fighterfish
+
+## Third-party Content
+
+This project leverages the following third party content.
+
+None
+
+## Cryptography
+
+Content may contain encryption software. The country in which you are currently
+may have restrictions on the import, possession, and use, and/or re-export to
+another country, of encryption software. BEFORE using any encryption software,
+please check the country's laws, regulations and policies concerning the import,
+possession, or use, and re-export of encryption software, to see if this is
+permitted.
+
+
+========================================================================
+
+netty NOTICE
+
+========================================================================
+
+                            The Netty Project
+                            =================
+
+Please visit the Netty web site for more information:
+
+  * https://netty.io/
+
+Copyright 2014 The Netty Project
+
+The Netty Project 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:
+
+  https://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.
+
+Also, please refer to each LICENSE.<component>.txt file, which is located in
+the 'license' directory of the distribution file, for the license terms of the
+components that this product depends on.
+
+-------------------------------------------------------------------------------
+This product contains the extensions to Java Collections Framework which has
+been derived from the works by JSR-166 EG, Doug Lea, and Jason T. Greene:
+
+  * LICENSE:
+    * license/LICENSE.jsr166y.txt (Public Domain)
+  * HOMEPAGE:
+    * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/
+    * http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbosscache/experimental/jsr166/
+
+This product contains a modified version of Robert Harder's Public Domain
+Base64 Encoder and Decoder, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.base64.txt (Public Domain)
+  * HOMEPAGE:
+    * http://iharder.sourceforge.net/current/java/base64/
+
+This product contains a modified portion of 'Webbit', an event based
+WebSocket and HTTP server, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.webbit.txt (BSD License)
+  * HOMEPAGE:
+    * https://github.com/joewalnes/webbit
+
+This product contains a modified portion of 'SLF4J', a simple logging
+facade for Java, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.slf4j.txt (MIT License)
+  * HOMEPAGE:
+    * https://www.slf4j.org/
+
+This product contains a modified portion of 'Apache Harmony', an open source
+Java SE, which can be obtained at:
+
+  * NOTICE:
+    * license/NOTICE.harmony.txt
+  * LICENSE:
+    * license/LICENSE.harmony.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://archive.apache.org/dist/harmony/
+
+This product contains a modified portion of 'jbzip2', a Java bzip2 compression
+and decompression library written by Matthew J. Francis. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.jbzip2.txt (MIT License)
+  * HOMEPAGE:
+    * https://code.google.com/p/jbzip2/
+
+This product contains a modified portion of 'libdivsufsort', a C API library to construct
+the suffix array and the Burrows-Wheeler transformed string for any input string of
+a constant-size alphabet written by Yuta Mori. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.libdivsufsort.txt (MIT License)
+  * HOMEPAGE:
+    * https://github.com/y-256/libdivsufsort
+
+This product contains a modified portion of Nitsan Wakart's 'JCTools', Java Concurrency Tools for the JVM,
+ which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.jctools.txt (ASL2 License)
+  * HOMEPAGE:
+    * https://github.com/JCTools/JCTools
+
+This product optionally depends on 'JZlib', a re-implementation of zlib in
+pure Java, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.jzlib.txt (BSD style License)
+  * HOMEPAGE:
+    * http://www.jcraft.com/jzlib/
+
+This product optionally depends on 'Compress-LZF', a Java library for encoding and
+decoding data in LZF format, written by Tatu Saloranta. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.compress-lzf.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/ning/compress
+
+This product optionally depends on 'lz4', a LZ4 Java compression
+and decompression library written by Adrien Grand. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.lz4.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/jpountz/lz4-java
+
+This product optionally depends on 'lzma-java', a LZMA Java compression
+and decompression library, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.lzma-java.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/jponge/lzma-java
+
+This product optionally depends on 'zstd-jni', a zstd-jni Java compression
+and decompression library, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.zstd-jni.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/luben/zstd-jni
+
+This product contains a modified portion of 'jfastlz', a Java port of FastLZ compression
+and decompression library written by William Kinney. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.jfastlz.txt (MIT License)
+  * HOMEPAGE:
+    * https://code.google.com/p/jfastlz/
+
+This product contains a modified portion of and optionally depends on 'Protocol Buffers', Google's data
+interchange format, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.protobuf.txt (New BSD License)
+  * HOMEPAGE:
+    * https://github.com/google/protobuf
+
+This product optionally depends on 'Bouncy Castle Crypto APIs' to generate
+a temporary self-signed X.509 certificate when the JVM does not provide the
+equivalent functionality.  It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.bouncycastle.txt (MIT License)
+  * HOMEPAGE:
+    * https://www.bouncycastle.org/
+
+This product optionally depends on 'Snappy', a compression library produced
+by Google Inc, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.snappy.txt (New BSD License)
+  * HOMEPAGE:
+    * https://github.com/google/snappy
+
+This product optionally depends on 'JBoss Marshalling', an alternative Java
+serialization API, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.jboss-marshalling.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/jboss-remoting/jboss-marshalling
+
+This product optionally depends on 'Caliper', Google's micro-
+benchmarking framework, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.caliper.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/google/caliper
+
+This product optionally depends on 'Apache Commons Logging', a logging
+framework, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.commons-logging.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://commons.apache.org/logging/
+
+This product optionally depends on 'Apache Log4J', a logging framework, which
+can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.log4j.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://logging.apache.org/log4j/
+
+This product optionally depends on 'Aalto XML', an ultra-high performance
+non-blocking XML processor, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.aalto-xml.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://wiki.fasterxml.com/AaltoHome
+
+This product contains a modified version of 'HPACK', a Java implementation of
+the HTTP/2 HPACK algorithm written by Twitter. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.hpack.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/twitter/hpack
+
+This product contains a modified version of 'HPACK', a Java implementation of
+the HTTP/2 HPACK algorithm written by Cory Benfield. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.hyper-hpack.txt (MIT License)
+  * HOMEPAGE:
+    * https://github.com/python-hyper/hpack/
+
+This product contains a modified version of 'HPACK', a Java implementation of
+the HTTP/2 HPACK algorithm written by Tatsuhiro Tsujikawa. It can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.nghttp2-hpack.txt (MIT License)
+  * HOMEPAGE:
+    * https://github.com/nghttp2/nghttp2/
+
+This product contains a modified portion of 'Apache Commons Lang', a Java library
+provides utilities for the java.lang API, which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.commons-lang.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://commons.apache.org/proper/commons-lang/
+
+
+This product contains the Maven wrapper scripts from 'Maven Wrapper', that provides an easy way to ensure a user has everything necessary to run the Maven build.
+
+  * LICENSE:
+    * license/LICENSE.mvn-wrapper.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/takari/maven-wrapper
+
+This product contains the dnsinfo.h header file, that provides a way to retrieve the system DNS configuration on MacOS.
+This private header is also used by Apple's open source
+ mDNSResponder (https://opensource.apple.com/tarballs/mDNSResponder/).
+
+ * LICENSE:
+    * license/LICENSE.dnsinfo.txt (Apple Public Source License 2.0)
+  * HOMEPAGE:
+    * https://www.opensource.apple.com/source/configd/configd-453.19/dnsinfo/dnsinfo.h
+
+This product optionally depends on 'Brotli4j', Brotli compression and
+decompression for Java., which can be obtained at:
+
+  * LICENSE:
+    * license/LICENSE.brotli4j.txt (Apache License 2.0)
+  * HOMEPAGE:
+    * https://github.com/hyperxpro/Brotli4j
+========================================================================
+
+perfmark NOTICE
+
+========================================================================
+
+Copyright 2019 Google LLC
+
+Licensed 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.
+
+-----------------------------------------------------------------------
+
+This product contains a modified portion of 'Catapult', an open source
+Trace Event viewer for Chome, Linux, and Android applications, which can
+be obtained at:
+
+  * LICENSE:
+    * traceviewer/src/main/resources/io/perfmark/traceviewer/third_party/catapult/LICENSE (New BSD License)
+  * HOMEPAGE:
+    * https://github.com/catapult-project/catapult
+
+This product contains a modified portion of 'Polymer', a library for Web
+Components, which can be obtained at:
+  * LICENSE:
+    * traceviewer/src/main/resources/io/perfmark/traceviewer/third_party/polymer/LICENSE (New BSD License)
+  * HOMEPAGE:
+    * https://github.com/Polymer/polymer
+
+
+This product contains a modified portion of 'ASM', an open source
+Java Bytecode library, which can be obtained at:
+
+  * LICENSE:
+    * agent/src/main/resources/io/perfmark/agent/third_party/asm/LICENSE (BSD style License)
+  * HOMEPAGE:
+    * https://asm.ow2.io/
+========================================================================
+
+junit5 NOTICE
+
+========================================================================
+Open Source Licenses
+====================
+
+This product may include a number of subcomponents with separate
+copyright notices and license terms. Your use of the source code for
+these subcomponents is subject to the terms and conditions of the
+subcomponent's license, as noted in the LICENSE-<subcomponent>.md
+files.
+========================================================================
+
+jaf-api NOTICE
+
+========================================================================
+
+# Notices for Jakarta Activation
+
+This content is produced and maintained by Jakarta Activation project.
+
+* Project home: https://projects.eclipse.org/projects/ee4j.jaf
+
+## Copyright
+
+All content is the property of the respective authors or their employers. For
+more information regarding authorship of content, please consult the listed
+source code repository logs.
+
+## Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Distribution License v. 1.0,
+which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+
+SPDX-License-Identifier: BSD-3-Clause
+
+## Source Code
+
+The project maintains the following source code repositories:
+
+* https://github.com/eclipse-ee4j/jaf
+========================================================================
+
+okhttp NOTICE
+
+========================================================================
+
+Note that publicsuffixes.gz is compiled from The Public Suffix List:
+https://publicsuffix.org/list/public_suffix_list.dat
+
+It is subject to the terms of the Mozilla Public License, v. 2.0:
+https://mozilla.org/MPL/2.0/
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-JavaHamcrest.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-JavaHamcrest.txt
new file mode 100644
index 0000000000..4933bda5ba
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-JavaHamcrest.txt
@@ -0,0 +1,27 @@
+BSD License
+
+Copyright (c) 2000-2015 www.hamcrest.org
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of
+conditions and the following disclaimer. Redistributions in binary form must reproduce
+the above copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the distribution.
+
+Neither the name of Hamcrest nor the names of its contributors may be used to endorse
+or promote products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-animal-sniffer.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-animal-sniffer.txt
new file mode 100644
index 0000000000..370fb559bb
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-animal-sniffer.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2009 codehaus.org.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-aopalliance-repackaged.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-aopalliance-repackaged.txt
new file mode 100644
index 0000000000..4a00ba9482
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-aopalliance-repackaged.txt
@@ -0,0 +1,362 @@
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.1
+
+1. Definitions.
+
+    1.1. "Contributor" means each individual or entity that creates or
+    contributes to the creation of Modifications.
+
+    1.2. "Contributor Version" means the combination of the Original
+    Software, prior Modifications used by a Contributor (if any), and
+    the Modifications made by that particular Contributor.
+
+    1.3. "Covered Software" means (a) the Original Software, or (b)
+    Modifications, or (c) the combination of files containing Original
+    Software with files containing Modifications, in each case including
+    portions thereof.
+
+    1.4. "Executable" means the Covered Software in any form other than
+    Source Code.
+
+    1.5. "Initial Developer" means the individual or entity that first
+    makes Original Software available under this License.
+
+    1.6. "Larger Work" means a work which combines Covered Software or
+    portions thereof with code not governed by the terms of this License.
+
+    1.7. "License" means this document.
+
+    1.8. "Licensable" means having the right to grant, to the maximum
+    extent possible, whether at the time of the initial grant or
+    subsequently acquired, any and all of the rights conveyed herein.
+
+    1.9. "Modifications" means the Source Code and Executable form of
+    any of the following:
+
+    A. Any file that results from an addition to, deletion from or
+    modification of the contents of a file containing Original Software
+    or previous Modifications;
+
+    B. Any new file that contains any part of the Original Software or
+    previous Modification; or
+
+    C. Any new file that is contributed or otherwise made available
+    under the terms of this License.
+
+    1.10. "Original Software" means the Source Code and Executable form
+    of computer software code that is originally released under this
+    License.
+
+    1.11. "Patent Claims" means any patent claim(s), now owned or
+    hereafter acquired, including without limitation, method, process,
+    and apparatus claims, in any patent Licensable by grantor.
+
+    1.12. "Source Code" means (a) the common form of computer software
+    code in which modifications are made and (b) associated
+    documentation included in or with such code.
+
+    1.13. "You" (or "Your") means an individual or a legal entity
+    exercising rights under, and complying with all of the terms of,
+    this License. For legal entities, "You" includes any entity which
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants.
+
+    2.1. The Initial Developer Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and subject
+    to third party intellectual property claims, the Initial Developer
+    hereby grants You a world-wide, royalty-free, non-exclusive license:
+
+    (a) under intellectual property rights (other than patent or
+    trademark) Licensable by Initial Developer, to use, reproduce,
+    modify, display, perform, sublicense and distribute the Original
+    Software (or portions thereof), with or without Modifications,
+    and/or as part of a Larger Work; and
+
+    (b) under Patent Claims infringed by the making, using or selling of
+    Original Software, to make, have made, use, practice, sell, and
+    offer for sale, and/or otherwise dispose of the Original Software
+    (or portions thereof).
+
+    (c) The licenses granted in Sections 2.1(a) and (b) are effective on
+    the date Initial Developer first distributes or otherwise makes the
+    Original Software available to a third party under the terms of this
+    License.
+
+    (d) Notwithstanding Section 2.1(b) above, no patent license is
+    granted: (1) for code that You delete from the Original Software, or
+    (2) for infringements caused by: (i) the modification of the
+    Original Software, or (ii) the combination of the Original Software
+    with other software or devices.
+
+    2.2. Contributor Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and subject
+    to third party intellectual property claims, each Contributor hereby
+    grants You a world-wide, royalty-free, non-exclusive license:
+
+    (a) under intellectual property rights (other than patent or
+    trademark) Licensable by Contributor to use, reproduce, modify,
+    display, perform, sublicense and distribute the Modifications
+    created by such Contributor (or portions thereof), either on an
+    unmodified basis, with other Modifications, as Covered Software
+    and/or as part of a Larger Work; and
+
+    (b) under Patent Claims infringed by the making, using, or selling
+    of Modifications made by that Contributor either alone and/or in
+    combination with its Contributor Version (or portions of such
+    combination), to make, use, sell, offer for sale, have made, and/or
+    otherwise dispose of: (1) Modifications made by that Contributor (or
+    portions thereof); and (2) the combination of Modifications made by
+    that Contributor with its Contributor Version (or portions of such
+    combination).
+
+    (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective
+    on the date Contributor first distributes or otherwise makes the
+    Modifications available to a third party.
+
+    (d) Notwithstanding Section 2.2(b) above, no patent license is
+    granted: (1) for any code that Contributor has deleted from the
+    Contributor Version; (2) for infringements caused by: (i) third
+    party modifications of Contributor Version, or (ii) the combination
+    of Modifications made by that Contributor with other software
+    (except as part of the Contributor Version) or other devices; or (3)
+    under Patent Claims infringed by Covered Software in the absence of
+    Modifications made by that Contributor.
+
+3. Distribution Obligations.
+
+    3.1. Availability of Source Code.
+
+    Any Covered Software that You distribute or otherwise make available
+    in Executable form must also be made available in Source Code form
+    and that Source Code form must be distributed only under the terms
+    of this License. You must include a copy of this License with every
+    copy of the Source Code form of the Covered Software You distribute
+    or otherwise make available. You must inform recipients of any such
+    Covered Software in Executable form as to how they can obtain such
+    Covered Software in Source Code form in a reasonable manner on or
+    through a medium customarily used for software exchange.
+
+    3.2. Modifications.
+
+    The Modifications that You create or to which You contribute are
+    governed by the terms of this License. You represent that You
+    believe Your Modifications are Your original creation(s) and/or You
+    have sufficient rights to grant the rights conveyed by this License.
+
+    3.3. Required Notices.
+
+    You must include a notice in each of Your Modifications that
+    identifies You as the Contributor of the Modification. You may not
+    remove or alter any copyright, patent or trademark notices contained
+    within the Covered Software, or any notices of licensing or any
+    descriptive text giving attribution to any Contributor or the
+    Initial Developer.
+
+    3.4. Application of Additional Terms.
+
+    You may not offer or impose any terms on any Covered Software in
+    Source Code form that alters or restricts the applicable version of
+    this License or the recipients' rights hereunder. You may choose to
+    offer, and to charge a fee for, warranty, support, indemnity or
+    liability obligations to one or more recipients of Covered Software.
+    However, you may do so only on Your own behalf, and not on behalf of
+    the Initial Developer or any Contributor. You must make it
+    absolutely clear that any such warranty, support, indemnity or
+    liability obligation is offered by You alone, and You hereby agree
+    to indemnify the Initial Developer and every Contributor for any
+    liability incurred by the Initial Developer or such Contributor as a
+    result of warranty, support, indemnity or liability terms You offer.
+
+    3.5. Distribution of Executable Versions.
+
+    You may distribute the Executable form of the Covered Software under
+    the terms of this License or under the terms of a license of Your
+    choice, which may contain terms different from this License,
+    provided that You are in compliance with the terms of this License
+    and that the license for the Executable form does not attempt to
+    limit or alter the recipient's rights in the Source Code form from
+    the rights set forth in this License. If You distribute the Covered
+    Software in Executable form under a different license, You must make
+    it absolutely clear that any terms which differ from this License
+    are offered by You alone, not by the Initial Developer or
+    Contributor. You hereby agree to indemnify the Initial Developer and
+    every Contributor for any liability incurred by the Initial
+    Developer or such Contributor as a result of any such terms You offer.
+
+    3.6. Larger Works.
+
+    You may create a Larger Work by combining Covered Software with
+    other code not governed by the terms of this License and distribute
+    the Larger Work as a single product. In such a case, You must make
+    sure the requirements of this License are fulfilled for the Covered
+    Software.
+
+4. Versions of the License.
+
+    4.1. New Versions.
+
+    Oracle is the initial license steward and may publish revised and/or
+    new versions of this License from time to time. Each version will be
+    given a distinguishing version number. Except as provided in Section
+    4.3, no one other than the license steward has the right to modify
+    this License.
+
+    4.2. Effect of New Versions.
+
+    You may always continue to use, distribute or otherwise make the
+    Covered Software available under the terms of the version of the
+    License under which You originally received the Covered Software. If
+    the Initial Developer includes a notice in the Original Software
+    prohibiting it from being distributed or otherwise made available
+    under any subsequent version of the License, You must distribute and
+    make the Covered Software available under the terms of the version
+    of the License under which You originally received the Covered
+    Software. Otherwise, You may also choose to use, distribute or
+    otherwise make the Covered Software available under the terms of any
+    subsequent version of the License published by the license steward.
+
+    4.3. Modified Versions.
+
+    When You are an Initial Developer and You want to create a new
+    license for Your Original Software, You may create and use a
+    modified version of this License if You: (a) rename the license and
+    remove any references to the name of the license steward (except to
+    note that the license differs from this License); and (b) otherwise
+    make it clear that the license contains terms which differ from this
+    License.
+
+5. DISCLAIMER OF WARRANTY.
+
+    COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+    WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+    INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE
+    IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+    NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF
+    THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE
+    DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY
+    OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING,
+    REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+    ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS
+    AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+6. TERMINATION.
+
+    6.1. This License and the rights granted hereunder will terminate
+    automatically if You fail to comply with terms herein and fail to
+    cure such breach within 30 days of becoming aware of the breach.
+    Provisions which, by their nature, must remain in effect beyond the
+    termination of this License shall survive.
+
+    6.2. If You assert a patent infringement claim (excluding
+    declaratory judgment actions) against Initial Developer or a
+    Contributor (the Initial Developer or Contributor against whom You
+    assert such claim is referred to as "Participant") alleging that the
+    Participant Software (meaning the Contributor Version where the
+    Participant is a Contributor or the Original Software where the
+    Participant is the Initial Developer) directly or indirectly
+    infringes any patent, then any and all rights granted directly or
+    indirectly to You by such Participant, the Initial Developer (if the
+    Initial Developer is not the Participant) and all Contributors under
+    Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice
+    from Participant terminate prospectively and automatically at the
+    expiration of such 60 day notice period, unless if within such 60
+    day period You withdraw Your claim with respect to the Participant
+    Software against such Participant either unilaterally or pursuant to
+    a written agreement with Participant.
+
+    6.3. If You assert a patent infringement claim against Participant
+    alleging that the Participant Software directly or indirectly
+    infringes any patent where such claim is resolved (such as by
+    license or settlement) prior to the initiation of patent
+    infringement litigation, then the reasonable value of the licenses
+    granted by such Participant under Sections 2.1 or 2.2 shall be taken
+    into account in determining the amount or value of any payment or
+    license.
+
+    6.4. In the event of termination under Sections 6.1 or 6.2 above,
+    all end user licenses that have been validly granted by You or any
+    distributor hereunder prior to termination (excluding licenses
+    granted to You by any distributor) shall survive termination.
+
+7. LIMITATION OF LIABILITY.
+
+    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+    (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
+    INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
+    COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE
+    TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
+    CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
+    LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER
+    FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
+    LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
+    POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT
+    APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+    PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+    LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR
+    LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION
+    AND LIMITATION MAY NOT APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS.
+
+    The Covered Software is a "commercial item," as that term is defined
+    in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+    software" (as that term is defined at 48 C.F.R. §
+    252.227-7014(a)(1)) and "commercial computer software documentation"
+    as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent
+    with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4
+    (June 1995), all U.S. Government End Users acquire Covered Software
+    with only those rights set forth herein. This U.S. Government Rights
+    clause is in lieu of, and supersedes, any other FAR, DFAR, or other
+    clause or provision that addresses Government rights in computer
+    software under this License.
+
+9. MISCELLANEOUS.
+
+    This License represents the complete agreement concerning subject
+    matter hereof. If any provision of this License is held to be
+    unenforceable, such provision shall be reformed only to the extent
+    necessary to make it enforceable. This License shall be governed by
+    the law of the jurisdiction specified in a notice contained within
+    the Original Software (except to the extent applicable law, if any,
+    provides otherwise), excluding such jurisdiction's conflict-of-law
+    provisions. Any litigation relating to this License shall be subject
+    to the jurisdiction of the courts located in the jurisdiction and
+    venue specified in a notice contained within the Original Software,
+    with the losing party responsible for costs, including, without
+    limitation, court costs and reasonable attorneys' fees and expenses.
+    The application of the United Nations Convention on Contracts for
+    the International Sale of Goods is expressly excluded. Any law or
+    regulation which provides that the language of a contract shall be
+    construed against the drafter shall not apply to this License. You
+    agree that You alone are responsible for compliance with the United
+    States export administration regulations (and the export control
+    laws and regulation of any other countries) when You use, distribute
+    or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS.
+
+    As between Initial Developer and the Contributors, each party is
+    responsible for claims and damages arising, directly or indirectly,
+    out of its utilization of rights under this License and You agree to
+    work with Initial Developer and Contributors to distribute such
+    responsibility on an equitable basis. Nothing herein is intended or
+    shall be deemed to constitute any admission of liability.
+
+------------------------------------------------------------------------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION
+LICENSE (CDDL)
+
+The code released under the CDDL shall be governed by the laws of the
+State of California (excluding conflict-of-law provisions). Any
+litigation relating to this License shall be subject to the jurisdiction
+of the Federal Courts of the Northern District of California and the
+state courts of the State of California, with venue lying in Santa Clara
+County, California.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-api-client-staging.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-api-client-staging.txt
new file mode 100644
index 0000000000..97ee06a0a4
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-api-client-staging.txt
@@ -0,0 +1,25 @@
+Copyright 2016, Google Inc.
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-checker-qual.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-checker-qual.txt
new file mode 100644
index 0000000000..9837c6b69f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-checker-qual.txt
@@ -0,0 +1,22 @@
+Checker Framework qualifiers
+Copyright 2004-present by the Checker Framework developers
+
+MIT License:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-beanutils.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-beanutils.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-beanutils.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-codec.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-codec.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-codec.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-collections.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-collections.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-collections.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-configuration.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-configuration.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-configuration.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-configuration2.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-configuration2.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-configuration2.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-io.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-io.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-io.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-lang.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-lang.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-lang.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-lang3.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-lang3.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-lang3.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-logging.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-logging.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-logging.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-text.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-text.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-commons-text.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-failureaccess.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-failureaccess.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-failureaccess.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-glassfish-hk2.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-glassfish-hk2.txt
new file mode 100644
index 0000000000..bda7db00c5
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-glassfish-hk2.txt
@@ -0,0 +1,277 @@
+# Eclipse Public License - v 2.0
+
+        THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+        PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+        OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+    1. DEFINITIONS
+
+    "Contribution" means:
+
+      a) in the case of the initial Contributor, the initial content
+         Distributed under this Agreement, and
+
+      b) in the case of each subsequent Contributor:
+         i) changes to the Program, and
+         ii) additions to the Program;
+      where such changes and/or additions to the Program originate from
+      and are Distributed by that particular Contributor. A Contribution
+      "originates" from a Contributor if it was added to the Program by
+      such Contributor itself or anyone acting on such Contributor's behalf.
+      Contributions do not include changes or additions to the Program that
+      are not Modified Works.
+
+    "Contributor" means any person or entity that Distributes the Program.
+
+    "Licensed Patents" mean patent claims licensable by a Contributor which
+    are necessarily infringed by the use or sale of its Contribution alone
+    or when combined with the Program.
+
+    "Program" means the Contributions Distributed in accordance with this
+    Agreement.
+
+    "Recipient" means anyone who receives the Program under this Agreement
+    or any Secondary License (as applicable), including Contributors.
+
+    "Derivative Works" shall mean any work, whether in Source Code or other
+    form, that is based on (or derived from) the Program and for which the
+    editorial revisions, annotations, elaborations, or other modifications
+    represent, as a whole, an original work of authorship.
+
+    "Modified Works" shall mean any work in Source Code or other form that
+    results from an addition to, deletion from, or modification of the
+    contents of the Program, including, for purposes of clarity any new file
+    in Source Code form that contains any contents of the Program. Modified
+    Works shall not include works that contain only declarations,
+    interfaces, types, classes, structures, or files of the Program solely
+    in each case in order to link to, bind by name, or subclass the Program
+    or Modified Works thereof.
+
+    "Distribute" means the acts of a) distributing or b) making available
+    in any manner that enables the transfer of a copy.
+
+    "Source Code" means the form of a Program preferred for making
+    modifications, including but not limited to software source code,
+    documentation source, and configuration files.
+
+    "Secondary License" means either the GNU General Public License,
+    Version 2.0, or any later versions of that license, including any
+    exceptions or additional permissions as identified by the initial
+    Contributor.
+
+    2. GRANT OF RIGHTS
+
+      a) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free copyright
+      license to reproduce, prepare Derivative Works of, publicly display,
+      publicly perform, Distribute and sublicense the Contribution of such
+      Contributor, if any, and such Derivative Works.
+
+      b) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free patent
+      license under Licensed Patents to make, use, sell, offer to sell,
+      import and otherwise transfer the Contribution of such Contributor,
+      if any, in Source Code or other form. This patent license shall
+      apply to the combination of the Contribution and the Program if, at
+      the time the Contribution is added by the Contributor, such addition
+      of the Contribution causes such combination to be covered by the
+      Licensed Patents. The patent license shall not apply to any other
+      combinations which include the Contribution. No hardware per se is
+      licensed hereunder.
+
+      c) Recipient understands that although each Contributor grants the
+      licenses to its Contributions set forth herein, no assurances are
+      provided by any Contributor that the Program does not infringe the
+      patent or other intellectual property rights of any other entity.
+      Each Contributor disclaims any liability to Recipient for claims
+      brought by any other entity based on infringement of intellectual
+      property rights or otherwise. As a condition to exercising the
+      rights and licenses granted hereunder, each Recipient hereby
+      assumes sole responsibility to secure any other intellectual
+      property rights needed, if any. For example, if a third party
+      patent license is required to allow Recipient to Distribute the
+      Program, it is Recipient's responsibility to acquire that license
+      before distributing the Program.
+
+      d) Each Contributor represents that to its knowledge it has
+      sufficient copyright rights in its Contribution, if any, to grant
+      the copyright license set forth in this Agreement.
+
+      e) Notwithstanding the terms of any Secondary License, no
+      Contributor makes additional grants to any Recipient (other than
+      those set forth in this Agreement) as a result of such Recipient's
+      receipt of the Program under the terms of a Secondary License
+      (if permitted under the terms of Section 3).
+
+    3. REQUIREMENTS
+
+    3.1 If a Contributor Distributes the Program in any form, then:
+
+      a) the Program must also be made available as Source Code, in
+      accordance with section 3.2, and the Contributor must accompany
+      the Program with a statement that the Source Code for the Program
+      is available under this Agreement, and informs Recipients how to
+      obtain it in a reasonable manner on or through a medium customarily
+      used for software exchange; and
+
+      b) the Contributor may Distribute the Program under a license
+      different than this Agreement, provided that such license:
+         i) effectively disclaims on behalf of all other Contributors all
+         warranties and conditions, express and implied, including
+         warranties or conditions of title and non-infringement, and
+         implied warranties or conditions of merchantability and fitness
+         for a particular purpose;
+
+         ii) effectively excludes on behalf of all other Contributors all
+         liability for damages, including direct, indirect, special,
+         incidental and consequential damages, such as lost profits;
+
+         iii) does not attempt to limit or alter the recipients' rights
+         in the Source Code under section 3.2; and
+
+         iv) requires any subsequent distribution of the Program by any
+         party to be under a license that satisfies the requirements
+         of this section 3.
+
+    3.2 When the Program is Distributed as Source Code:
+
+      a) it must be made available under this Agreement, or if the
+      Program (i) is combined with other material in a separate file or
+      files made available under a Secondary License, and (ii) the initial
+      Contributor attached to the Source Code the notice described in
+      Exhibit A of this Agreement, then the Program may be made available
+      under the terms of such Secondary Licenses, and
+
+      b) a copy of this Agreement must be included with each copy of
+      the Program.
+
+    3.3 Contributors may not remove or alter any copyright, patent,
+    trademark, attribution notices, disclaimers of warranty, or limitations
+    of liability ("notices") contained within the Program from any copy of
+    the Program which they Distribute, provided that Contributors may add
+    their own appropriate notices.
+
+    4. COMMERCIAL DISTRIBUTION
+
+    Commercial distributors of software may accept certain responsibilities
+    with respect to end users, business partners and the like. While this
+    license is intended to facilitate the commercial use of the Program,
+    the Contributor who includes the Program in a commercial product
+    offering should do so in a manner which does not create potential
+    liability for other Contributors. Therefore, if a Contributor includes
+    the Program in a commercial product offering, such Contributor
+    ("Commercial Contributor") hereby agrees to defend and indemnify every
+    other Contributor ("Indemnified Contributor") against any losses,
+    damages and costs (collectively "Losses") arising from claims, lawsuits
+    and other legal actions brought by a third party against the Indemnified
+    Contributor to the extent caused by the acts or omissions of such
+    Commercial Contributor in connection with its distribution of the Program
+    in a commercial product offering. The obligations in this section do not
+    apply to any claims or Losses relating to any actual or alleged
+    intellectual property infringement. In order to qualify, an Indemnified
+    Contributor must: a) promptly notify the Commercial Contributor in
+    writing of such claim, and b) allow the Commercial Contributor to control,
+    and cooperate with the Commercial Contributor in, the defense and any
+    related settlement negotiations. The Indemnified Contributor may
+    participate in any such claim at its own expense.
+
+    For example, a Contributor might include the Program in a commercial
+    product offering, Product X. That Contributor is then a Commercial
+    Contributor. If that Commercial Contributor then makes performance
+    claims, or offers warranties related to Product X, those performance
+    claims and warranties are such Commercial Contributor's responsibility
+    alone. Under this section, the Commercial Contributor would have to
+    defend claims against the other Contributors related to those performance
+    claims and warranties, and if a court requires any other Contributor to
+    pay any damages as a result, the Commercial Contributor must pay
+    those damages.
+
+    5. NO WARRANTY
+
+    EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+    PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+    BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+    IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+    TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+    PURPOSE. Each Recipient is solely responsible for determining the
+    appropriateness of using and distributing the Program and assumes all
+    risks associated with its exercise of rights under this Agreement,
+    including but not limited to the risks and costs of program errors,
+    compliance with applicable laws, damage to or loss of data, programs
+    or equipment, and unavailability or interruption of operations.
+
+    6. DISCLAIMER OF LIABILITY
+
+    EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+    PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+    SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+    PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+    EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGES.
+
+    7. GENERAL
+
+    If any provision of this Agreement is invalid or unenforceable under
+    applicable law, it shall not affect the validity or enforceability of
+    the remainder of the terms of this Agreement, and without further
+    action by the parties hereto, such provision shall be reformed to the
+    minimum extent necessary to make such provision valid and enforceable.
+
+    If Recipient institutes patent litigation against any entity
+    (including a cross-claim or counterclaim in a lawsuit) alleging that the
+    Program itself (excluding combinations of the Program with other software
+    or hardware) infringes such Recipient's patent(s), then such Recipient's
+    rights granted under Section 2(b) shall terminate as of the date such
+    litigation is filed.
+
+    All Recipient's rights under this Agreement shall terminate if it
+    fails to comply with any of the material terms or conditions of this
+    Agreement and does not cure such failure in a reasonable period of
+    time after becoming aware of such noncompliance. If all Recipient's
+    rights under this Agreement terminate, Recipient agrees to cease use
+    and distribution of the Program as soon as reasonably practicable.
+    However, Recipient's obligations under this Agreement and any licenses
+    granted by Recipient relating to the Program shall continue and survive.
+
+    Everyone is permitted to copy and distribute copies of this Agreement,
+    but in order to avoid inconsistency the Agreement is copyrighted and
+    may only be modified in the following manner. The Agreement Steward
+    reserves the right to publish new versions (including revisions) of
+    this Agreement from time to time. No one other than the Agreement
+    Steward has the right to modify this Agreement. The Eclipse Foundation
+    is the initial Agreement Steward. The Eclipse Foundation may assign the
+    responsibility to serve as the Agreement Steward to a suitable separate
+    entity. Each new version of the Agreement will be given a distinguishing
+    version number. The Program (including Contributions) may always be
+    Distributed subject to the version of the Agreement under which it was
+    received. In addition, after a new version of the Agreement is published,
+    Contributor may elect to Distribute the Program (including its
+    Contributions) under the new version.
+
+    Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+    receives no rights or licenses to the intellectual property of any
+    Contributor under this Agreement, whether expressly, by implication,
+    estoppel or otherwise. All rights in the Program not expressly granted
+    under this Agreement are reserved. Nothing in this Agreement is intended
+    to be enforceable by any entity that is not a Contributor or Recipient.
+    No third-party beneficiary rights are created under this Agreement.
+
+    Exhibit A - Form of Secondary Licenses Notice
+
+    "This Source Code may also be made available under the following
+    Secondary Licenses when the conditions for such availability set forth
+    in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+    version(s), and exceptions or additional permissions here}."
+
+      Simply including a copy of this Agreement, including this Exhibit A
+      is not sufficient to license the Source Code under Secondary Licenses.
+
+      If it is not possible or desirable to put the notice in a particular
+      file, then You may include the notice in a location (such as a LICENSE
+      file in a relevant directory) where a recipient would be likely to
+      look for such a notice.
+
+      You may add additional accurate notices of copyright ownership.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-grpc-java.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-grpc-java.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-grpc-java.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-gson.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-gson.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-gson.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-httpclient.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-httpclient.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-httpclient.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-httpcore.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-httpcore.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-httpcore.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-j2objc.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-j2objc.txt
new file mode 100644
index 0000000000..2b004c3eee
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-j2objc.txt
@@ -0,0 +1,232 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+--------------------------------------------------------------------------------
+The next section, BSD-3-Clause, applies to the files in:
+jre_emul/android/platform/libcore/ojluni/src/main/java/java/time
+--------------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of JSR-310 nor the names of its contributors
+  may be used to endorse or promote products derived from this software
+  without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-annotations-2.14.0.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-annotations-2.14.0.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-annotations-2.14.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-annotations.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-annotations.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-annotations.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-core-2.14.0.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-core-2.14.0.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-core-2.14.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-core.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-core.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-core.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-databind-2.14.0.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-databind-2.14.0.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-databind-2.14.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-databind.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-databind.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-databind.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-dataformat-yaml.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-dataformat-yaml.txt
new file mode 100644
index 0000000000..8d5775d40c
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-dataformat-yaml.txt
@@ -0,0 +1,8 @@
+This copy of Jackson JSON processor YAML module is licensed under the
+Apache (Software) License, version 2.0 ("the License").
+See the License for details about distribution rights, and the
+specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-base-2.14.0.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-base-2.14.0.txt
new file mode 100644
index 0000000000..6acf75483f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-base-2.14.0.txt
@@ -0,0 +1,8 @@
+This copy of Jackson JSON processor databind module is licensed under the
+Apache (Software) License, version 2.0 ("the License").
+See the License for details about distribution rights, and the
+specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-base.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-base.txt
new file mode 100644
index 0000000000..6acf75483f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-base.txt
@@ -0,0 +1,8 @@
+This copy of Jackson JSON processor databind module is licensed under the
+Apache (Software) License, version 2.0 ("the License").
+See the License for details about distribution rights, and the
+specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-json-provider-2.14.0.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-json-provider-2.14.0.txt
new file mode 100644
index 0000000000..6acf75483f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-json-provider-2.14.0.txt
@@ -0,0 +1,8 @@
+This copy of Jackson JSON processor databind module is licensed under the
+Apache (Software) License, version 2.0 ("the License").
+See the License for details about distribution rights, and the
+specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-json-provider.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-json-provider.txt
new file mode 100644
index 0000000000..6acf75483f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-jaxrs-json-provider.txt
@@ -0,0 +1,8 @@
+This copy of Jackson JSON processor databind module is licensed under the
+Apache (Software) License, version 2.0 ("the License").
+See the License for details about distribution rights, and the
+specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-module-jaxb-annotations-2.14.0.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-module-jaxb-annotations-2.14.0.txt
new file mode 100644
index 0000000000..283587f1b1
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-module-jaxb-annotations-2.14.0.txt
@@ -0,0 +1,8 @@
+This copy of Jackson JSON processor `jackson-module-jaxb-annotations` module is licensed under the
+Apache (Software) License, version 2.0 ("the License").
+See the License for details about distribution rights, and the
+specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-module-jaxb-annotations.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-module-jaxb-annotations.txt
new file mode 100644
index 0000000000..283587f1b1
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jackson-module-jaxb-annotations.txt
@@ -0,0 +1,8 @@
+This copy of Jackson JSON processor `jackson-module-jaxb-annotations` module is licensed under the
+Apache (Software) License, version 2.0 ("the License").
+See the License for details about distribution rights, and the
+specific rights regarding derivate works.
+
+You may obtain a copy of the License at:
+
+http://www.apache.org/licenses/LICENSE-2.0
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jaf-api.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jaf-api.txt
new file mode 100644
index 0000000000..05220de312
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jaf-api.txt
@@ -0,0 +1,29 @@
+
+    Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+   
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+   
+      - Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+   
+      - Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+   
+      - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+        contributors may be used to endorse or promote products derived
+        from this software without specific prior written permission.
+   
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jakarta.activation-api.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jakarta.activation-api.txt
new file mode 100644
index 0000000000..e0358f9721
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jakarta.activation-api.txt
@@ -0,0 +1,29 @@
+
+    Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+   
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+   
+      - Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+   
+      - Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+   
+      - Neither the name of the Eclipse Foundation, Inc. nor the names of its
+        contributors may be used to endorse or promote products derived
+        from this software without specific prior written permission.
+   
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jakarta.activation.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jakarta.activation.txt
new file mode 100644
index 0000000000..a8ba56ef14
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jakarta.activation.txt
@@ -0,0 +1,277 @@
+# Eclipse Public License - v 2.0
+
+        THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+        PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+        OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+    1. DEFINITIONS
+
+    "Contribution" means:
+
+      a) in the case of the initial Contributor, the initial content
+         Distributed under this Agreement, and
+
+      b) in the case of each subsequent Contributor: 
+         i) changes to the Program, and 
+         ii) additions to the Program;
+      where such changes and/or additions to the Program originate from
+      and are Distributed by that particular Contributor. A Contribution
+      "originates" from a Contributor if it was added to the Program by
+      such Contributor itself or anyone acting on such Contributor's behalf.
+      Contributions do not include changes or additions to the Program that
+      are not Modified Works.
+
+    "Contributor" means any person or entity that Distributes the Program.
+
+    "Licensed Patents" mean patent claims licensable by a Contributor which
+    are necessarily infringed by the use or sale of its Contribution alone
+    or when combined with the Program.
+
+    "Program" means the Contributions Distributed in accordance with this
+    Agreement.
+
+    "Recipient" means anyone who receives the Program under this Agreement
+    or any Secondary License (as applicable), including Contributors.
+
+    "Derivative Works" shall mean any work, whether in Source Code or other
+    form, that is based on (or derived from) the Program and for which the
+    editorial revisions, annotations, elaborations, or other modifications
+    represent, as a whole, an original work of authorship.
+
+    "Modified Works" shall mean any work in Source Code or other form that
+    results from an addition to, deletion from, or modification of the
+    contents of the Program, including, for purposes of clarity any new file
+    in Source Code form that contains any contents of the Program. Modified
+    Works shall not include works that contain only declarations,
+    interfaces, types, classes, structures, or files of the Program solely
+    in each case in order to link to, bind by name, or subclass the Program
+    or Modified Works thereof.
+
+    "Distribute" means the acts of a) distributing or b) making available
+    in any manner that enables the transfer of a copy.
+
+    "Source Code" means the form of a Program preferred for making
+    modifications, including but not limited to software source code,
+    documentation source, and configuration files.
+
+    "Secondary License" means either the GNU General Public License,
+    Version 2.0, or any later versions of that license, including any
+    exceptions or additional permissions as identified by the initial
+    Contributor.
+
+    2. GRANT OF RIGHTS
+
+      a) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free copyright
+      license to reproduce, prepare Derivative Works of, publicly display,
+      publicly perform, Distribute and sublicense the Contribution of such
+      Contributor, if any, and such Derivative Works.
+
+      b) Subject to the terms of this Agreement, each Contributor hereby
+      grants Recipient a non-exclusive, worldwide, royalty-free patent
+      license under Licensed Patents to make, use, sell, offer to sell,
+      import and otherwise transfer the Contribution of such Contributor,
+      if any, in Source Code or other form. This patent license shall
+      apply to the combination of the Contribution and the Program if, at
+      the time the Contribution is added by the Contributor, such addition
+      of the Contribution causes such combination to be covered by the
+      Licensed Patents. The patent license shall not apply to any other
+      combinations which include the Contribution. No hardware per se is
+      licensed hereunder.
+
+      c) Recipient understands that although each Contributor grants the
+      licenses to its Contributions set forth herein, no assurances are
+      provided by any Contributor that the Program does not infringe the
+      patent or other intellectual property rights of any other entity.
+      Each Contributor disclaims any liability to Recipient for claims
+      brought by any other entity based on infringement of intellectual
+      property rights or otherwise. As a condition to exercising the
+      rights and licenses granted hereunder, each Recipient hereby
+      assumes sole responsibility to secure any other intellectual
+      property rights needed, if any. For example, if a third party
+      patent license is required to allow Recipient to Distribute the
+      Program, it is Recipient's responsibility to acquire that license
+      before distributing the Program.
+
+      d) Each Contributor represents that to its knowledge it has
+      sufficient copyright rights in its Contribution, if any, to grant
+      the copyright license set forth in this Agreement.
+
+      e) Notwithstanding the terms of any Secondary License, no
+      Contributor makes additional grants to any Recipient (other than
+      those set forth in this Agreement) as a result of such Recipient's
+      receipt of the Program under the terms of a Secondary License
+      (if permitted under the terms of Section 3).
+
+    3. REQUIREMENTS
+
+    3.1 If a Contributor Distributes the Program in any form, then:
+
+      a) the Program must also be made available as Source Code, in
+      accordance with section 3.2, and the Contributor must accompany
+      the Program with a statement that the Source Code for the Program
+      is available under this Agreement, and informs Recipients how to
+      obtain it in a reasonable manner on or through a medium customarily
+      used for software exchange; and
+
+      b) the Contributor may Distribute the Program under a license
+      different than this Agreement, provided that such license:
+         i) effectively disclaims on behalf of all other Contributors all
+         warranties and conditions, express and implied, including
+         warranties or conditions of title and non-infringement, and
+         implied warranties or conditions of merchantability and fitness
+         for a particular purpose;
+
+         ii) effectively excludes on behalf of all other Contributors all
+         liability for damages, including direct, indirect, special,
+         incidental and consequential damages, such as lost profits;
+
+         iii) does not attempt to limit or alter the recipients' rights
+         in the Source Code under section 3.2; and
+
+         iv) requires any subsequent distribution of the Program by any
+         party to be under a license that satisfies the requirements
+         of this section 3.
+
+    3.2 When the Program is Distributed as Source Code:
+
+      a) it must be made available under this Agreement, or if the
+      Program (i) is combined with other material in a separate file or
+      files made available under a Secondary License, and (ii) the initial
+      Contributor attached to the Source Code the notice described in
+      Exhibit A of this Agreement, then the Program may be made available
+      under the terms of such Secondary Licenses, and
+
+      b) a copy of this Agreement must be included with each copy of
+      the Program.
+
+    3.3 Contributors may not remove or alter any copyright, patent,
+    trademark, attribution notices, disclaimers of warranty, or limitations
+    of liability ("notices") contained within the Program from any copy of
+    the Program which they Distribute, provided that Contributors may add
+    their own appropriate notices.
+
+    4. COMMERCIAL DISTRIBUTION
+
+    Commercial distributors of software may accept certain responsibilities
+    with respect to end users, business partners and the like. While this
+    license is intended to facilitate the commercial use of the Program,
+    the Contributor who includes the Program in a commercial product
+    offering should do so in a manner which does not create potential
+    liability for other Contributors. Therefore, if a Contributor includes
+    the Program in a commercial product offering, such Contributor
+    ("Commercial Contributor") hereby agrees to defend and indemnify every
+    other Contributor ("Indemnified Contributor") against any losses,
+    damages and costs (collectively "Losses") arising from claims, lawsuits
+    and other legal actions brought by a third party against the Indemnified
+    Contributor to the extent caused by the acts or omissions of such
+    Commercial Contributor in connection with its distribution of the Program
+    in a commercial product offering. The obligations in this section do not
+    apply to any claims or Losses relating to any actual or alleged
+    intellectual property infringement. In order to qualify, an Indemnified
+    Contributor must: a) promptly notify the Commercial Contributor in
+    writing of such claim, and b) allow the Commercial Contributor to control,
+    and cooperate with the Commercial Contributor in, the defense and any
+    related settlement negotiations. The Indemnified Contributor may
+    participate in any such claim at its own expense.
+
+    For example, a Contributor might include the Program in a commercial
+    product offering, Product X. That Contributor is then a Commercial
+    Contributor. If that Commercial Contributor then makes performance
+    claims, or offers warranties related to Product X, those performance
+    claims and warranties are such Commercial Contributor's responsibility
+    alone. Under this section, the Commercial Contributor would have to
+    defend claims against the other Contributors related to those performance
+    claims and warranties, and if a court requires any other Contributor to
+    pay any damages as a result, the Commercial Contributor must pay
+    those damages.
+
+    5. NO WARRANTY
+
+    EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+    PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+    BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+    IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+    TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+    PURPOSE. Each Recipient is solely responsible for determining the
+    appropriateness of using and distributing the Program and assumes all
+    risks associated with its exercise of rights under this Agreement,
+    including but not limited to the risks and costs of program errors,
+    compliance with applicable laws, damage to or loss of data, programs
+    or equipment, and unavailability or interruption of operations.
+
+    6. DISCLAIMER OF LIABILITY
+
+    EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+    PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+    SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+    PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+    EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGES.
+
+    7. GENERAL
+
+    If any provision of this Agreement is invalid or unenforceable under
+    applicable law, it shall not affect the validity or enforceability of
+    the remainder of the terms of this Agreement, and without further
+    action by the parties hereto, such provision shall be reformed to the
+    minimum extent necessary to make such provision valid and enforceable.
+
+    If Recipient institutes patent litigation against any entity
+    (including a cross-claim or counterclaim in a lawsuit) alleging that the
+    Program itself (excluding combinations of the Program with other software
+    or hardware) infringes such Recipient's patent(s), then such Recipient's
+    rights granted under Section 2(b) shall terminate as of the date such
+    litigation is filed.
+
+    All Recipient's rights under this Agreement shall terminate if it
+    fails to comply with any of the material terms or conditions of this
+    Agreement and does not cure such failure in a reasonable period of
+    time after becoming aware of such noncompliance. If all Recipient's
+    rights under this Agreement terminate, Recipient agrees to cease use
+    and distribution of the Program as soon as reasonably practicable.
+    However, Recipient's obligations under this Agreement and any licenses
+    granted by Recipient relating to the Program shall continue and survive.
+
+    Everyone is permitted to copy and distribute copies of this Agreement,
+    but in order to avoid inconsistency the Agreement is copyrighted and
+    may only be modified in the following manner. The Agreement Steward
+    reserves the right to publish new versions (including revisions) of
+    this Agreement from time to time. No one other than the Agreement
+    Steward has the right to modify this Agreement. The Eclipse Foundation
+    is the initial Agreement Steward. The Eclipse Foundation may assign the
+    responsibility to serve as the Agreement Steward to a suitable separate
+    entity. Each new version of the Agreement will be given a distinguishing
+    version number. The Program (including Contributions) may always be
+    Distributed subject to the version of the Agreement under which it was
+    received. In addition, after a new version of the Agreement is published,
+    Contributor may elect to Distribute the Program (including its
+    Contributions) under the new version.
+
+    Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+    receives no rights or licenses to the intellectual property of any
+    Contributor under this Agreement, whether expressly, by implication,
+    estoppel or otherwise. All rights in the Program not expressly granted
+    under this Agreement are reserved. Nothing in this Agreement is intended
+    to be enforceable by any entity that is not a Contributor or Recipient.
+    No third-party beneficiary rights are created under this Agreement.
+
+    Exhibit A - Form of Secondary Licenses Notice
+
+    "This Source Code may also be made available under the following 
+    Secondary Licenses when the conditions for such availability set forth 
+    in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+    version(s), and exceptions or additional permissions here}."
+
+      Simply including a copy of this Agreement, including this Exhibit A
+      is not sufficient to license the Source Code under Secondary Licenses.
+
+      If it is not possible or desirable to put the notice in a particular
+      file, then You may include the notice in a location (such as a LICENSE
+      file in a relevant directory) where a recipient would be likely to
+      look for such a notice.
+
+      You may add additional accurate notices of copyright ownership.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-javassist.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-javassist.txt
new file mode 100644
index 0000000000..f45a423e3f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-javassist.txt
@@ -0,0 +1,357 @@
+<HTML>
+<HEAD>
+<TITLE>Javassist License</TITLE>
+<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<META content="MSHTML 5.50.4916.2300" name=GENERATOR></HEAD>
+
+<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000ee bgColor=#ffffff>
+<CENTER><B><FONT size=+2>MOZILLA PUBLIC LICENSE</FONT></B> <BR><B>Version 
+1.1</B> 
+<P>
+<HR width="20%">
+</CENTER>
+<P><B>1. Definitions.</B> 
+<UL><B>1.0.1. "Commercial Use" </B>means distribution or otherwise making the 
+  Covered Code available to a third party. 
+  <P><B>1.1. ''Contributor''</B> means each entity that creates or contributes 
+  to the creation of Modifications. 
+  <P><B>1.2. ''Contributor Version''</B> means the combination of the Original 
+  Code, prior Modifications used by a Contributor, and the Modifications made by 
+  that particular Contributor. 
+  <P><B>1.3. ''Covered Code''</B> means the Original Code or Modifications or 
+  the combination of the Original Code and Modifications, in each case including 
+  portions thereof<B>.</B> 
+  <P><B>1.4. ''Electronic Distribution Mechanism''</B> means a mechanism 
+  generally accepted in the software development community for the electronic 
+  transfer of data. 
+  <P><B>1.5. ''Executable''</B> means Covered Code in any form other than Source 
+  Code. 
+  <P><B>1.6. ''Initial Developer''</B> means the individual or entity identified 
+  as the Initial Developer in the Source Code notice required by <B>Exhibit 
+  A</B>. 
+  <P><B>1.7. ''Larger Work''</B> means a work which combines Covered Code or 
+  portions thereof with code not governed by the terms of this License. 
+  <P><B>1.8. ''License''</B> means this document. 
+  <P><B>1.8.1. "Licensable"</B> means having the right to grant, to the maximum 
+  extent possible, whether at the time of the initial grant or subsequently 
+  acquired, any and all of the rights conveyed herein. 
+  <P><B>1.9. ''Modifications''</B> means any addition to or deletion from the 
+  substance or structure of either the Original Code or any previous 
+  Modifications. When Covered Code is released as a series of files, a 
+  Modification is: 
+  <UL><B>A.</B> Any addition to or deletion from the contents of a file 
+    containing Original Code or previous Modifications. 
+    <P><B>B.</B> Any new file that contains any part of the Original Code or 
+    previous Modifications. <BR>&nbsp;</P></UL><B>1.10. ''Original Code''</B> 
+  means Source Code of computer software code which is described in the Source 
+  Code notice required by <B>Exhibit A</B> as Original Code, and which, at the 
+  time of its release under this License is not already Covered Code governed by 
+  this License. 
+  <P><B>1.10.1. "Patent Claims"</B> means any patent claim(s), now owned or 
+  hereafter acquired, including without limitation,&nbsp; method, process, and 
+  apparatus claims, in any patent Licensable by grantor. 
+  <P><B>1.11. ''Source Code''</B> means the preferred form of the Covered Code 
+  for making modifications to it, including all modules it contains, plus any 
+  associated interface definition files, scripts used to control compilation and 
+  installation of an Executable, or source code differential comparisons against 
+  either the Original Code or another well known, available Covered Code of the 
+  Contributor's choice. The Source Code can be in a compressed or archival form, 
+  provided the appropriate decompression or de-archiving software is widely 
+  available for no charge. 
+  <P><B>1.12. "You'' (or "Your")&nbsp;</B> means an individual or a legal entity 
+  exercising rights under, and complying with all of the terms of, this License 
+  or a future version of this License issued under Section 6.1. For legal 
+  entities, "You'' includes any entity which controls, is controlled by, or is 
+  under common control with You. For purposes of this definition, "control'' 
+  means (a) the power, direct or indirect, to cause the direction or management 
+  of such entity, whether by contract or otherwise, or (b) ownership of more 
+  than fifty percent (50%) of the outstanding shares or beneficial ownership of 
+  such entity.</P></UL><B>2. Source Code License.</B> 
+<UL><B>2.1. The Initial Developer Grant.</B> <BR>The Initial Developer hereby 
+  grants You a world-wide, royalty-free, non-exclusive license, subject to third 
+  party intellectual property claims: 
+  <UL><B>(a)</B>&nbsp;<B> </B>under intellectual property rights (other than 
+    patent or trademark) Licensable by Initial Developer to use, reproduce, 
+    modify, display, perform, sublicense and distribute the Original Code (or 
+    portions thereof) with or without Modifications, and/or as part of a Larger 
+    Work; and 
+    <P><B>(b)</B> under Patents Claims infringed by the making, using or selling 
+    of Original Code, to make, have made, use, practice, sell, and offer for 
+    sale, and/or otherwise dispose of the Original Code (or portions thereof). 
+    <UL>
+      <UL></UL></UL><B>(c) </B>the licenses granted in this Section 2.1(a) and (b) 
+    are effective on the date Initial Developer first distributes Original Code 
+    under the terms of this License. 
+    <P><B>(d) </B>Notwithstanding Section 2.1(b) above, no patent license is 
+    granted: 1) for code that You delete from the Original Code; 2) separate 
+    from the Original Code;&nbsp; or 3) for infringements caused by: i) the 
+    modification of the Original Code or ii) the combination of the Original 
+    Code with other software or devices. <BR>&nbsp;</P></UL><B>2.2. Contributor 
+  Grant.</B> <BR>Subject to third party intellectual property claims, each 
+  Contributor hereby grants You a world-wide, royalty-free, non-exclusive 
+  license 
+  <UL> <BR><B>(a)</B>&nbsp;<B> </B>under intellectual property rights (other 
+    than patent or trademark) Licensable by Contributor, to use, reproduce, 
+    modify, display, perform, sublicense and distribute the Modifications 
+    created by such Contributor (or portions thereof) either on an unmodified 
+    basis, with other Modifications, as Covered Code and/or as part of a Larger 
+    Work; and 
+    <P><B>(b)</B> under Patent Claims infringed by the making, using, or selling 
+    of&nbsp; Modifications made by that Contributor either alone and/or in<FONT 
+    color=#000000> combination with its Contributor Version (or portions of such 
+    combination), to make, use, sell, offer for sale, have made, and/or 
+    otherwise dispose of: 1) Modifications made by that Contributor (or portions 
+    thereof); and 2) the combination of&nbsp; Modifications made by that 
+    Contributor with its Contributor Version (or portions of such 
+    combination).</FONT> 
+    <P><B>(c) </B>the licenses granted in Sections 2.2(a) and 2.2(b) are 
+    effective on the date Contributor first makes Commercial Use of the Covered 
+    Code. 
+    <P><B>(d)&nbsp;</B>&nbsp;&nbsp; Notwithstanding Section 2.2(b) above, no 
+    patent license is granted: 1) for any code that Contributor has deleted from 
+    the Contributor Version; 2)&nbsp; separate from the Contributor 
+    Version;&nbsp; 3)&nbsp; for infringements caused by: i) third party 
+    modifications of Contributor Version or ii)&nbsp; the combination of 
+    Modifications made by that Contributor with other software&nbsp; (except as 
+    part of the Contributor Version) or other devices; or 4) under Patent Claims 
+    infringed by Covered Code in the absence of Modifications made by that 
+    Contributor.</P></UL></UL>
+<P><BR><B>3. Distribution Obligations.</B> 
+<UL><B>3.1. Application of License.</B> <BR>The Modifications which You create 
+  or to which You contribute are governed by the terms of this License, 
+  including without limitation Section <B>2.2</B>. The Source Code version of 
+  Covered Code may be distributed only under the terms of this License or a 
+  future version of this License released under Section <B>6.1</B>, and You must 
+  include a copy of this License with every copy of the Source Code You 
+  distribute. You may not offer or impose any terms on any Source Code version 
+  that alters or restricts the applicable version of this License or the 
+  recipients' rights hereunder. However, You may include an additional document 
+  offering the additional rights described in Section <B>3.5</B>. 
+  <P><B>3.2. Availability of Source Code.</B> <BR>Any Modification which You 
+  create or to which You contribute must be made available in Source Code form 
+  under the terms of this License either on the same media as an Executable 
+  version or via an accepted Electronic Distribution Mechanism to anyone to whom 
+  you made an Executable version available; and if made available via Electronic 
+  Distribution Mechanism, must remain available for at least twelve (12) months 
+  after the date it initially became available, or at least six (6) months after 
+  a subsequent version of that particular Modification has been made available 
+  to such recipients. You are responsible for ensuring that the Source Code 
+  version remains available even if the Electronic Distribution Mechanism is 
+  maintained by a third party. 
+  <P><B>3.3. Description of Modifications.</B> <BR>You must cause all Covered 
+  Code to which You contribute to contain a file documenting the changes You 
+  made to create that Covered Code and the date of any change. You must include 
+  a prominent statement that the Modification is derived, directly or 
+  indirectly, from Original Code provided by the Initial Developer and including 
+  the name of the Initial Developer in (a) the Source Code, and (b) in any 
+  notice in an Executable version or related documentation in which You describe 
+  the origin or ownership of the Covered Code. 
+  <P><B>3.4. Intellectual Property Matters</B> 
+  <UL><B>(a) Third Party Claims</B>. <BR>If Contributor has knowledge that a 
+    license under a third party's intellectual property rights is required to 
+    exercise the rights granted by such Contributor under Sections 2.1 or 2.2, 
+    Contributor must include a text file with the Source Code distribution 
+    titled "LEGAL'' which describes the claim and the party making the claim in 
+    sufficient detail that a recipient will know whom to contact. If Contributor 
+    obtains such knowledge after the Modification is made available as described 
+    in Section 3.2, Contributor shall promptly modify the LEGAL file in all 
+    copies Contributor makes available thereafter and shall take other steps 
+    (such as notifying appropriate mailing lists or newsgroups) reasonably 
+    calculated to inform those who received the Covered Code that new knowledge 
+    has been obtained. 
+    <P><B>(b) Contributor APIs</B>. <BR>If Contributor's Modifications include 
+    an application programming interface and Contributor has knowledge of patent 
+    licenses which are reasonably necessary to implement that API, Contributor 
+    must also include this information in the LEGAL file. 
+  <BR>&nbsp;</P></UL>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+  <B>(c)&nbsp;&nbsp;&nbsp; Representations.</B> 
+  <UL>Contributor represents that, except as disclosed pursuant to Section 
+    3.4(a) above, Contributor believes that Contributor's Modifications are 
+    Contributor's original creation(s) and/or Contributor has sufficient rights 
+    to grant the rights conveyed by this License.</UL>
+  <P><BR><B>3.5. Required Notices.</B> <BR>You must duplicate the notice in 
+  <B>Exhibit A</B> in each file of the Source Code.&nbsp; If it is not possible 
+  to put such notice in a particular Source Code file due to its structure, then 
+  You must include such notice in a location (such as a relevant directory) 
+  where a user would be likely to look for such a notice.&nbsp; If You created 
+  one or more Modification(s) You may add your name as a Contributor to the 
+  notice described in <B>Exhibit A</B>.&nbsp; You must also duplicate this 
+  License in any documentation for the Source Code where You describe 
+  recipients' rights or ownership rights relating to Covered Code.&nbsp; You may 
+  choose to offer, and to charge a fee for, warranty, support, indemnity or 
+  liability obligations to one or more recipients of Covered Code. However, You 
+  may do so only on Your own behalf, and not on behalf of the Initial Developer 
+  or any Contributor. You must make it absolutely clear than any such warranty, 
+  support, indemnity or liability obligation is offered by You alone, and You 
+  hereby agree to indemnify the Initial Developer and every Contributor for any 
+  liability incurred by the Initial Developer or such Contributor as a result of 
+  warranty, support, indemnity or liability terms You offer. 
+  <P><B>3.6. Distribution of Executable Versions.</B> <BR>You may distribute 
+  Covered Code in Executable form only if the requirements of Section 
+  <B>3.1-3.5</B> have been met for that Covered Code, and if You include a 
+  notice stating that the Source Code version of the Covered Code is available 
+  under the terms of this License, including a description of how and where You 
+  have fulfilled the obligations of Section <B>3.2</B>. The notice must be 
+  conspicuously included in any notice in an Executable version, related 
+  documentation or collateral in which You describe recipients' rights relating 
+  to the Covered Code. You may distribute the Executable version of Covered Code 
+  or ownership rights under a license of Your choice, which may contain terms 
+  different from this License, provided that You are in compliance with the 
+  terms of this License and that the license for the Executable version does not 
+  attempt to limit or alter the recipient's rights in the Source Code version 
+  from the rights set forth in this License. If You distribute the Executable 
+  version under a different license You must make it absolutely clear that any 
+  terms which differ from this License are offered by You alone, not by the 
+  Initial Developer or any Contributor. You hereby agree to indemnify the 
+  Initial Developer and every Contributor for any liability incurred by the 
+  Initial Developer or such Contributor as a result of any such terms You offer. 
+
+  <P><B>3.7. Larger Works.</B> <BR>You may create a Larger Work by combining 
+  Covered Code with other code not governed by the terms of this License and 
+  distribute the Larger Work as a single product. In such a case, You must make 
+  sure the requirements of this License are fulfilled for the Covered 
+Code.</P></UL><B>4. Inability to Comply Due to Statute or Regulation.</B> 
+<UL>If it is impossible for You to comply with any of the terms of this 
+  License with respect to some or all of the Covered Code due to statute, 
+  judicial order, or regulation then You must: (a) comply with the terms of this 
+  License to the maximum extent possible; and (b) describe the limitations and 
+  the code they affect. Such description must be included in the LEGAL file 
+  described in Section <B>3.4</B> and must be included with all distributions of 
+  the Source Code. Except to the extent prohibited by statute or regulation, 
+  such description must be sufficiently detailed for a recipient of ordinary 
+  skill to be able to understand it.</UL><B>5. Application of this License.</B> 
+<UL>This License applies to code to which the Initial Developer has attached 
+  the notice in <B>Exhibit A</B> and to related Covered Code.</UL><B>6. Versions 
+of the License.</B> 
+<UL><B>6.1. New Versions</B>. <BR>Netscape Communications Corporation 
+  (''Netscape'') may publish revised and/or new versions of the License from 
+  time to time. Each version will be given a distinguishing version number. 
+  <P><B>6.2. Effect of New Versions</B>. <BR>Once Covered Code has been 
+  published under a particular version of the License, You may always continue 
+  to use it under the terms of that version. You may also choose to use such 
+  Covered Code under the terms of any subsequent version of the License 
+  published by Netscape. No one other than Netscape has the right to modify the 
+  terms applicable to Covered Code created under this License. 
+  <P><B>6.3. Derivative Works</B>. <BR>If You create or use a modified version 
+  of this License (which you may only do in order to apply it to code which is 
+  not already Covered Code governed by this License), You must (a) rename Your 
+  license so that the phrases ''Mozilla'', ''MOZILLAPL'', ''MOZPL'', 
+  ''Netscape'', "MPL", ''NPL'' or any confusingly similar phrase do not appear 
+  in your license (except to note that your license differs from this License) 
+  and (b) otherwise make it clear that Your version of the license contains 
+  terms which differ from the Mozilla Public License and Netscape Public 
+  License. (Filling in the name of the Initial Developer, Original Code or 
+  Contributor in the notice described in <B>Exhibit A</B> shall not of 
+  themselves be deemed to be modifications of this License.)</P></UL><B>7. 
+DISCLAIMER OF WARRANTY.</B> 
+<UL>COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS'' BASIS, WITHOUT 
+  WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT 
+  LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, 
+  FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE 
+  QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED 
+  CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY 
+  OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR 
+  CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS 
+  LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS 
+  DISCLAIMER.</UL><B>8. TERMINATION.</B> 
+<UL><B>8.1.&nbsp; </B>This License and the rights granted hereunder will 
+  terminate automatically if You fail to comply with terms herein and fail to 
+  cure such breach within 30 days of becoming aware of the breach. All 
+  sublicenses to the Covered Code which are properly granted shall survive any 
+  termination of this License. Provisions which, by their nature, must remain in 
+  effect beyond the termination of this License shall survive. 
+  <P><B>8.2.&nbsp; </B>If You initiate litigation by asserting a patent 
+  infringement claim (excluding declatory judgment actions) against Initial 
+  Developer or a Contributor (the Initial Developer or Contributor against whom 
+  You file such action is referred to as "Participant")&nbsp; alleging that: 
+  <P><B>(a)&nbsp; </B>such Participant's Contributor Version directly or 
+  indirectly infringes any patent, then any and all rights granted by such 
+  Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 
+  60 days notice from Participant terminate prospectively, unless if within 60 
+  days after receipt of notice You either: (i)&nbsp; agree in writing to pay 
+  Participant a mutually agreeable reasonable royalty for Your past and future 
+  use of Modifications made by such Participant, or (ii) withdraw Your 
+  litigation claim with respect to the Contributor Version against such 
+  Participant.&nbsp; If within 60 days of notice, a reasonable royalty and 
+  payment arrangement are not mutually agreed upon in writing by the parties or 
+  the litigation claim is not withdrawn, the rights granted by Participant to 
+  You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of 
+  the 60 day notice period specified above. 
+  <P><B>(b)</B>&nbsp; any software, hardware, or device, other than such 
+  Participant's Contributor Version, directly or indirectly infringes any 
+  patent, then any rights granted to You by such Participant under Sections 
+  2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, 
+  sold, distributed, or had made, Modifications made by that Participant. 
+  <P><B>8.3.&nbsp; </B>If You assert a patent infringement claim against 
+  Participant alleging that such Participant's Contributor Version directly or 
+  indirectly infringes any patent where such claim is resolved (such as by 
+  license or settlement) prior to the initiation of patent infringement 
+  litigation, then the reasonable value of the licenses granted by such 
+  Participant under Sections 2.1 or 2.2 shall be taken into account in 
+  determining the amount or value of any payment or license. 
+  <P><B>8.4.</B>&nbsp; In the event of termination under Sections 8.1 or 8.2 
+  above,&nbsp; all end user license agreements (excluding distributors and 
+  resellers) which have been validly granted by You or any distributor hereunder 
+  prior to termination shall survive termination.</P></UL><B>9. LIMITATION OF 
+LIABILITY.</B> 
+<UL>UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING 
+  NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY 
+  OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY 
+  OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, 
+  INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT 
+  LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR 
+  MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH 
+  PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS 
+  LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL 
+  INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW 
+  PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR 
+  LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND 
+  LIMITATION MAY NOT APPLY TO YOU.</UL><B>10. U.S. GOVERNMENT END USERS.</B> 
+<UL>The Covered Code is a ''commercial item,'' as that term is defined in 48 
+  C.F.R. 2.101 (Oct. 1995), consisting of ''commercial computer software'' and 
+  ''commercial computer software documentation,'' as such terms are used in 48 
+  C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 
+  227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users 
+  acquire Covered Code with only those rights set forth herein.</UL><B>11. 
+MISCELLANEOUS.</B> 
+<UL>This License represents the complete agreement concerning subject matter 
+  hereof. If any provision of this License is held to be unenforceable, such 
+  provision shall be reformed only to the extent necessary to make it 
+  enforceable. This License shall be governed by California law provisions 
+  (except to the extent applicable law, if any, provides otherwise), excluding 
+  its conflict-of-law provisions. With respect to disputes in which at least one 
+  party is a citizen of, or an entity chartered or registered to do business in 
+  the United States of America, any litigation relating to this License shall be 
+  subject to the jurisdiction of the Federal Courts of the Northern District of 
+  California, with venue lying in Santa Clara County, California, with the 
+  losing party responsible for costs, including without limitation, court costs 
+  and reasonable attorneys' fees and expenses. The application of the United 
+  Nations Convention on Contracts for the International Sale of Goods is 
+  expressly excluded. Any law or regulation which provides that the language of 
+  a contract shall be construed against the drafter shall not apply to this 
+  License.</UL><B>12. RESPONSIBILITY FOR CLAIMS.</B> 
+<UL>As between Initial Developer and the Contributors, each party is 
+  responsible for claims and damages arising, directly or indirectly, out of its 
+  utilization of rights under this License and You agree to work with Initial 
+  Developer and Contributors to distribute such responsibility on an equitable 
+  basis. Nothing herein is intended or shall be deemed to constitute any 
+  admission of liability.</UL><B>13. MULTIPLE-LICENSED CODE.</B> 
+<UL>Initial Developer may designate portions of the Covered Code as 
+  "Multiple-Licensed".&nbsp; "Multiple-Licensed" means that the Initial 
+  Developer permits you to utilize portions of the Covered Code under Your 
+  choice of the MPL or the alternative licenses, if any, specified by the 
+  Initial Developer in the file described in Exhibit A.</UL>
+<P><BR><B>EXHIBIT A -Mozilla Public License.</B> 
+<UL>The contents of this file are subject to the Mozilla Public License 
+  Version 1.1 (the "License"); you may not use this file except in compliance 
+  with the License. You may obtain a copy of the License at 
+  <BR>http://www.mozilla.org/MPL/ 
+  <P>Software distributed under the License is distributed on an "AS IS" basis, 
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the
+  License.
+  <P>The Original Code is Javassist. 
+  <P>The Initial Developer of the Original Code is Shigeru Chiba. 
+  Portions created by the Initial Developer are<BR>&nbsp;
+  Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. 
+  <P>Contributor(s):  __Bill Burke, Jason T. Greene______________.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-javax.activation-api-1.2.0-sources.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-javax.activation-api-1.2.0-sources.txt
new file mode 100644
index 0000000000..596a510633
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-javax.activation-api-1.2.0-sources.txt
@@ -0,0 +1,362 @@
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.1
+
+1. Definitions.
+
+    1.1. "Contributor" means each individual or entity that creates or
+    contributes to the creation of Modifications.
+
+    1.2. "Contributor Version" means the combination of the Original
+    Software, prior Modifications used by a Contributor (if any), and
+    the Modifications made by that particular Contributor.
+
+    1.3. "Covered Software" means (a) the Original Software, or (b)
+    Modifications, or (c) the combination of files containing Original
+    Software with files containing Modifications, in each case including
+    portions thereof.
+
+    1.4. "Executable" means the Covered Software in any form other than
+    Source Code.
+
+    1.5. "Initial Developer" means the individual or entity that first
+    makes Original Software available under this License.
+
+    1.6. "Larger Work" means a work which combines Covered Software or
+    portions thereof with code not governed by the terms of this License.
+
+    1.7. "License" means this document.
+
+    1.8. "Licensable" means having the right to grant, to the maximum
+    extent possible, whether at the time of the initial grant or
+    subsequently acquired, any and all of the rights conveyed herein.
+
+    1.9. "Modifications" means the Source Code and Executable form of
+    any of the following:
+
+    A. Any file that results from an addition to, deletion from or
+    modification of the contents of a file containing Original Software
+    or previous Modifications;
+
+    B. Any new file that contains any part of the Original Software or
+    previous Modification; or
+
+    C. Any new file that is contributed or otherwise made available
+    under the terms of this License.
+
+    1.10. "Original Software" means the Source Code and Executable form
+    of computer software code that is originally released under this
+    License.
+
+    1.11. "Patent Claims" means any patent claim(s), now owned or
+    hereafter acquired, including without limitation, method, process,
+    and apparatus claims, in any patent Licensable by grantor.
+
+    1.12. "Source Code" means (a) the common form of computer software
+    code in which modifications are made and (b) associated
+    documentation included in or with such code.
+
+    1.13. "You" (or "Your") means an individual or a legal entity
+    exercising rights under, and complying with all of the terms of,
+    this License. For legal entities, "You" includes any entity which
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants.
+
+    2.1. The Initial Developer Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and subject
+    to third party intellectual property claims, the Initial Developer
+    hereby grants You a world-wide, royalty-free, non-exclusive license:
+
+    (a) under intellectual property rights (other than patent or
+    trademark) Licensable by Initial Developer, to use, reproduce,
+    modify, display, perform, sublicense and distribute the Original
+    Software (or portions thereof), with or without Modifications,
+    and/or as part of a Larger Work; and
+
+    (b) under Patent Claims infringed by the making, using or selling of
+    Original Software, to make, have made, use, practice, sell, and
+    offer for sale, and/or otherwise dispose of the Original Software
+    (or portions thereof).
+
+    (c) The licenses granted in Sections 2.1(a) and (b) are effective on
+    the date Initial Developer first distributes or otherwise makes the
+    Original Software available to a third party under the terms of this
+    License.
+
+    (d) Notwithstanding Section 2.1(b) above, no patent license is
+    granted: (1) for code that You delete from the Original Software, or
+    (2) for infringements caused by: (i) the modification of the
+    Original Software, or (ii) the combination of the Original Software
+    with other software or devices.
+
+    2.2. Contributor Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and subject
+    to third party intellectual property claims, each Contributor hereby
+    grants You a world-wide, royalty-free, non-exclusive license:
+
+    (a) under intellectual property rights (other than patent or
+    trademark) Licensable by Contributor to use, reproduce, modify,
+    display, perform, sublicense and distribute the Modifications
+    created by such Contributor (or portions thereof), either on an
+    unmodified basis, with other Modifications, as Covered Software
+    and/or as part of a Larger Work; and
+
+    (b) under Patent Claims infringed by the making, using, or selling
+    of Modifications made by that Contributor either alone and/or in
+    combination with its Contributor Version (or portions of such
+    combination), to make, use, sell, offer for sale, have made, and/or
+    otherwise dispose of: (1) Modifications made by that Contributor (or
+    portions thereof); and (2) the combination of Modifications made by
+    that Contributor with its Contributor Version (or portions of such
+    combination).
+
+    (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective
+    on the date Contributor first distributes or otherwise makes the
+    Modifications available to a third party.
+
+    (d) Notwithstanding Section 2.2(b) above, no patent license is
+    granted: (1) for any code that Contributor has deleted from the
+    Contributor Version; (2) for infringements caused by: (i) third
+    party modifications of Contributor Version, or (ii) the combination
+    of Modifications made by that Contributor with other software
+    (except as part of the Contributor Version) or other devices; or (3)
+    under Patent Claims infringed by Covered Software in the absence of
+    Modifications made by that Contributor.
+
+3. Distribution Obligations.
+
+    3.1. Availability of Source Code.
+
+    Any Covered Software that You distribute or otherwise make available
+    in Executable form must also be made available in Source Code form
+    and that Source Code form must be distributed only under the terms
+    of this License. You must include a copy of this License with every
+    copy of the Source Code form of the Covered Software You distribute
+    or otherwise make available. You must inform recipients of any such
+    Covered Software in Executable form as to how they can obtain such
+    Covered Software in Source Code form in a reasonable manner on or
+    through a medium customarily used for software exchange.
+
+    3.2. Modifications.
+
+    The Modifications that You create or to which You contribute are
+    governed by the terms of this License. You represent that You
+    believe Your Modifications are Your original creation(s) and/or You
+    have sufficient rights to grant the rights conveyed by this License.
+
+    3.3. Required Notices.
+
+    You must include a notice in each of Your Modifications that
+    identifies You as the Contributor of the Modification. You may not
+    remove or alter any copyright, patent or trademark notices contained
+    within the Covered Software, or any notices of licensing or any
+    descriptive text giving attribution to any Contributor or the
+    Initial Developer.
+
+    3.4. Application of Additional Terms.
+
+    You may not offer or impose any terms on any Covered Software in
+    Source Code form that alters or restricts the applicable version of
+    this License or the recipients' rights hereunder. You may choose to
+    offer, and to charge a fee for, warranty, support, indemnity or
+    liability obligations to one or more recipients of Covered Software.
+    However, you may do so only on Your own behalf, and not on behalf of
+    the Initial Developer or any Contributor. You must make it
+    absolutely clear that any such warranty, support, indemnity or
+    liability obligation is offered by You alone, and You hereby agree
+    to indemnify the Initial Developer and every Contributor for any
+    liability incurred by the Initial Developer or such Contributor as a
+    result of warranty, support, indemnity or liability terms You offer.
+
+    3.5. Distribution of Executable Versions.
+
+    You may distribute the Executable form of the Covered Software under
+    the terms of this License or under the terms of a license of Your
+    choice, which may contain terms different from this License,
+    provided that You are in compliance with the terms of this License
+    and that the license for the Executable form does not attempt to
+    limit or alter the recipient's rights in the Source Code form from
+    the rights set forth in this License. If You distribute the Covered
+    Software in Executable form under a different license, You must make
+    it absolutely clear that any terms which differ from this License
+    are offered by You alone, not by the Initial Developer or
+    Contributor. You hereby agree to indemnify the Initial Developer and
+    every Contributor for any liability incurred by the Initial
+    Developer or such Contributor as a result of any such terms You offer.
+
+    3.6. Larger Works.
+
+    You may create a Larger Work by combining Covered Software with
+    other code not governed by the terms of this License and distribute
+    the Larger Work as a single product. In such a case, You must make
+    sure the requirements of this License are fulfilled for the Covered
+    Software.
+
+4. Versions of the License.
+
+    4.1. New Versions.
+
+    Oracle is the initial license steward and may publish revised and/or
+    new versions of this License from time to time. Each version will be
+    given a distinguishing version number. Except as provided in Section
+    4.3, no one other than the license steward has the right to modify
+    this License.
+
+    4.2. Effect of New Versions.
+
+    You may always continue to use, distribute or otherwise make the
+    Covered Software available under the terms of the version of the
+    License under which You originally received the Covered Software. If
+    the Initial Developer includes a notice in the Original Software
+    prohibiting it from being distributed or otherwise made available
+    under any subsequent version of the License, You must distribute and
+    make the Covered Software available under the terms of the version
+    of the License under which You originally received the Covered
+    Software. Otherwise, You may also choose to use, distribute or
+    otherwise make the Covered Software available under the terms of any
+    subsequent version of the License published by the license steward.
+
+    4.3. Modified Versions.
+
+    When You are an Initial Developer and You want to create a new
+    license for Your Original Software, You may create and use a
+    modified version of this License if You: (a) rename the license and
+    remove any references to the name of the license steward (except to
+    note that the license differs from this License); and (b) otherwise
+    make it clear that the license contains terms which differ from this
+    License.
+
+5. DISCLAIMER OF WARRANTY.
+
+    COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+    WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+    INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE
+    IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+    NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF
+    THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE
+    DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY
+    OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING,
+    REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+    ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS
+    AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+6. TERMINATION.
+
+    6.1. This License and the rights granted hereunder will terminate
+    automatically if You fail to comply with terms herein and fail to
+    cure such breach within 30 days of becoming aware of the breach.
+    Provisions which, by their nature, must remain in effect beyond the
+    termination of this License shall survive.
+
+    6.2. If You assert a patent infringement claim (excluding
+    declaratory judgment actions) against Initial Developer or a
+    Contributor (the Initial Developer or Contributor against whom You
+    assert such claim is referred to as "Participant") alleging that the
+    Participant Software (meaning the Contributor Version where the
+    Participant is a Contributor or the Original Software where the
+    Participant is the Initial Developer) directly or indirectly
+    infringes any patent, then any and all rights granted directly or
+    indirectly to You by such Participant, the Initial Developer (if the
+    Initial Developer is not the Participant) and all Contributors under
+    Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice
+    from Participant terminate prospectively and automatically at the
+    expiration of such 60 day notice period, unless if within such 60
+    day period You withdraw Your claim with respect to the Participant
+    Software against such Participant either unilaterally or pursuant to
+    a written agreement with Participant.
+
+    6.3. If You assert a patent infringement claim against Participant
+    alleging that the Participant Software directly or indirectly
+    infringes any patent where such claim is resolved (such as by
+    license or settlement) prior to the initiation of patent
+    infringement litigation, then the reasonable value of the licenses
+    granted by such Participant under Sections 2.1 or 2.2 shall be taken
+    into account in determining the amount or value of any payment or
+    license.
+
+    6.4. In the event of termination under Sections 6.1 or 6.2 above,
+    all end user licenses that have been validly granted by You or any
+    distributor hereunder prior to termination (excluding licenses
+    granted to You by any distributor) shall survive termination.
+
+7. LIMITATION OF LIABILITY.
+
+    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+    (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
+    INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
+    COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE
+    TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
+    CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
+    LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER
+    FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
+    LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
+    POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT
+    APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+    PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+    LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR
+    LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION
+    AND LIMITATION MAY NOT APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS.
+
+    The Covered Software is a "commercial item," as that term is defined
+    in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+    software" (as that term is defined at 48 C.F.R. �
+    252.227-7014(a)(1)) and "commercial computer software documentation"
+    as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent
+    with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4
+    (June 1995), all U.S. Government End Users acquire Covered Software
+    with only those rights set forth herein. This U.S. Government Rights
+    clause is in lieu of, and supersedes, any other FAR, DFAR, or other
+    clause or provision that addresses Government rights in computer
+    software under this License.
+
+9. MISCELLANEOUS.
+
+    This License represents the complete agreement concerning subject
+    matter hereof. If any provision of this License is held to be
+    unenforceable, such provision shall be reformed only to the extent
+    necessary to make it enforceable. This License shall be governed by
+    the law of the jurisdiction specified in a notice contained within
+    the Original Software (except to the extent applicable law, if any,
+    provides otherwise), excluding such jurisdiction's conflict-of-law
+    provisions. Any litigation relating to this License shall be subject
+    to the jurisdiction of the courts located in the jurisdiction and
+    venue specified in a notice contained within the Original Software,
+    with the losing party responsible for costs, including, without
+    limitation, court costs and reasonable attorneys' fees and expenses.
+    The application of the United Nations Convention on Contracts for
+    the International Sale of Goods is expressly excluded. Any law or
+    regulation which provides that the language of a contract shall be
+    construed against the drafter shall not apply to this License. You
+    agree that You alone are responsible for compliance with the United
+    States export administration regulations (and the export control
+    laws and regulation of any other countries) when You use, distribute
+    or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS.
+
+    As between Initial Developer and the Contributors, each party is
+    responsible for claims and damages arising, directly or indirectly,
+    out of its utilization of rights under this License and You agree to
+    work with Initial Developer and Contributors to distribute such
+    responsibility on an equitable basis. Nothing herein is intended or
+    shall be deemed to constitute any admission of liability.
+
+------------------------------------------------------------------------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION
+LICENSE (CDDL)
+
+The code released under the CDDL shall be governed by the laws of the
+State of California (excluding conflict-of-law provisions). Any
+litigation relating to this License shall be subject to the jurisdiction
+of the Federal Courts of the Northern District of California and the
+state courts of the State of California, with venue lying in Santa Clara
+County, California.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jaxb-ri.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jaxb-ri.txt
new file mode 100644
index 0000000000..74b62b6219
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jaxb-ri.txt
@@ -0,0 +1,11 @@
+Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-joda-time.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-joda-time.txt
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-joda-time.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jsonp.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jsonp.txt
new file mode 100644
index 0000000000..4a00ba9482
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-jsonp.txt
@@ -0,0 +1,362 @@
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.1
+
+1. Definitions.
+
+    1.1. "Contributor" means each individual or entity that creates or
+    contributes to the creation of Modifications.
+
+    1.2. "Contributor Version" means the combination of the Original
+    Software, prior Modifications used by a Contributor (if any), and
+    the Modifications made by that particular Contributor.
+
+    1.3. "Covered Software" means (a) the Original Software, or (b)
+    Modifications, or (c) the combination of files containing Original
+    Software with files containing Modifications, in each case including
+    portions thereof.
+
+    1.4. "Executable" means the Covered Software in any form other than
+    Source Code.
+
+    1.5. "Initial Developer" means the individual or entity that first
+    makes Original Software available under this License.
+
+    1.6. "Larger Work" means a work which combines Covered Software or
+    portions thereof with code not governed by the terms of this License.
+
+    1.7. "License" means this document.
+
+    1.8. "Licensable" means having the right to grant, to the maximum
+    extent possible, whether at the time of the initial grant or
+    subsequently acquired, any and all of the rights conveyed herein.
+
+    1.9. "Modifications" means the Source Code and Executable form of
+    any of the following:
+
+    A. Any file that results from an addition to, deletion from or
+    modification of the contents of a file containing Original Software
+    or previous Modifications;
+
+    B. Any new file that contains any part of the Original Software or
+    previous Modification; or
+
+    C. Any new file that is contributed or otherwise made available
+    under the terms of this License.
+
+    1.10. "Original Software" means the Source Code and Executable form
+    of computer software code that is originally released under this
+    License.
+
+    1.11. "Patent Claims" means any patent claim(s), now owned or
+    hereafter acquired, including without limitation, method, process,
+    and apparatus claims, in any patent Licensable by grantor.
+
+    1.12. "Source Code" means (a) the common form of computer software
+    code in which modifications are made and (b) associated
+    documentation included in or with such code.
+
+    1.13. "You" (or "Your") means an individual or a legal entity
+    exercising rights under, and complying with all of the terms of,
+    this License. For legal entities, "You" includes any entity which
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants.
+
+    2.1. The Initial Developer Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and subject
+    to third party intellectual property claims, the Initial Developer
+    hereby grants You a world-wide, royalty-free, non-exclusive license:
+
+    (a) under intellectual property rights (other than patent or
+    trademark) Licensable by Initial Developer, to use, reproduce,
+    modify, display, perform, sublicense and distribute the Original
+    Software (or portions thereof), with or without Modifications,
+    and/or as part of a Larger Work; and
+
+    (b) under Patent Claims infringed by the making, using or selling of
+    Original Software, to make, have made, use, practice, sell, and
+    offer for sale, and/or otherwise dispose of the Original Software
+    (or portions thereof).
+
+    (c) The licenses granted in Sections 2.1(a) and (b) are effective on
+    the date Initial Developer first distributes or otherwise makes the
+    Original Software available to a third party under the terms of this
+    License.
+
+    (d) Notwithstanding Section 2.1(b) above, no patent license is
+    granted: (1) for code that You delete from the Original Software, or
+    (2) for infringements caused by: (i) the modification of the
+    Original Software, or (ii) the combination of the Original Software
+    with other software or devices.
+
+    2.2. Contributor Grant.
+
+    Conditioned upon Your compliance with Section 3.1 below and subject
+    to third party intellectual property claims, each Contributor hereby
+    grants You a world-wide, royalty-free, non-exclusive license:
+
+    (a) under intellectual property rights (other than patent or
+    trademark) Licensable by Contributor to use, reproduce, modify,
+    display, perform, sublicense and distribute the Modifications
+    created by such Contributor (or portions thereof), either on an
+    unmodified basis, with other Modifications, as Covered Software
+    and/or as part of a Larger Work; and
+
+    (b) under Patent Claims infringed by the making, using, or selling
+    of Modifications made by that Contributor either alone and/or in
+    combination with its Contributor Version (or portions of such
+    combination), to make, use, sell, offer for sale, have made, and/or
+    otherwise dispose of: (1) Modifications made by that Contributor (or
+    portions thereof); and (2) the combination of Modifications made by
+    that Contributor with its Contributor Version (or portions of such
+    combination).
+
+    (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective
+    on the date Contributor first distributes or otherwise makes the
+    Modifications available to a third party.
+
+    (d) Notwithstanding Section 2.2(b) above, no patent license is
+    granted: (1) for any code that Contributor has deleted from the
+    Contributor Version; (2) for infringements caused by: (i) third
+    party modifications of Contributor Version, or (ii) the combination
+    of Modifications made by that Contributor with other software
+    (except as part of the Contributor Version) or other devices; or (3)
+    under Patent Claims infringed by Covered Software in the absence of
+    Modifications made by that Contributor.
+
+3. Distribution Obligations.
+
+    3.1. Availability of Source Code.
+
+    Any Covered Software that You distribute or otherwise make available
+    in Executable form must also be made available in Source Code form
+    and that Source Code form must be distributed only under the terms
+    of this License. You must include a copy of this License with every
+    copy of the Source Code form of the Covered Software You distribute
+    or otherwise make available. You must inform recipients of any such
+    Covered Software in Executable form as to how they can obtain such
+    Covered Software in Source Code form in a reasonable manner on or
+    through a medium customarily used for software exchange.
+
+    3.2. Modifications.
+
+    The Modifications that You create or to which You contribute are
+    governed by the terms of this License. You represent that You
+    believe Your Modifications are Your original creation(s) and/or You
+    have sufficient rights to grant the rights conveyed by this License.
+
+    3.3. Required Notices.
+
+    You must include a notice in each of Your Modifications that
+    identifies You as the Contributor of the Modification. You may not
+    remove or alter any copyright, patent or trademark notices contained
+    within the Covered Software, or any notices of licensing or any
+    descriptive text giving attribution to any Contributor or the
+    Initial Developer.
+
+    3.4. Application of Additional Terms.
+
+    You may not offer or impose any terms on any Covered Software in
+    Source Code form that alters or restricts the applicable version of
+    this License or the recipients' rights hereunder. You may choose to
+    offer, and to charge a fee for, warranty, support, indemnity or
+    liability obligations to one or more recipients of Covered Software.
+    However, you may do so only on Your own behalf, and not on behalf of
+    the Initial Developer or any Contributor. You must make it
+    absolutely clear that any such warranty, support, indemnity or
+    liability obligation is offered by You alone, and You hereby agree
+    to indemnify the Initial Developer and every Contributor for any
+    liability incurred by the Initial Developer or such Contributor as a
+    result of warranty, support, indemnity or liability terms You offer.
+
+    3.5. Distribution of Executable Versions.
+
+    You may distribute the Executable form of the Covered Software under
+    the terms of this License or under the terms of a license of Your
+    choice, which may contain terms different from this License,
+    provided that You are in compliance with the terms of this License
+    and that the license for the Executable form does not attempt to
+    limit or alter the recipient's rights in the Source Code form from
+    the rights set forth in this License. If You distribute the Covered
+    Software in Executable form under a different license, You must make
+    it absolutely clear that any terms which differ from this License
+    are offered by You alone, not by the Initial Developer or
+    Contributor. You hereby agree to indemnify the Initial Developer and
+    every Contributor for any liability incurred by the Initial
+    Developer or such Contributor as a result of any such terms You offer.
+
+    3.6. Larger Works.
+
+    You may create a Larger Work by combining Covered Software with
+    other code not governed by the terms of this License and distribute
+    the Larger Work as a single product. In such a case, You must make
+    sure the requirements of this License are fulfilled for the Covered
+    Software.
+
+4. Versions of the License.
+
+    4.1. New Versions.
+
+    Oracle is the initial license steward and may publish revised and/or
+    new versions of this License from time to time. Each version will be
+    given a distinguishing version number. Except as provided in Section
+    4.3, no one other than the license steward has the right to modify
+    this License.
+
+    4.2. Effect of New Versions.
+
+    You may always continue to use, distribute or otherwise make the
+    Covered Software available under the terms of the version of the
+    License under which You originally received the Covered Software. If
+    the Initial Developer includes a notice in the Original Software
+    prohibiting it from being distributed or otherwise made available
+    under any subsequent version of the License, You must distribute and
+    make the Covered Software available under the terms of the version
+    of the License under which You originally received the Covered
+    Software. Otherwise, You may also choose to use, distribute or
+    otherwise make the Covered Software available under the terms of any
+    subsequent version of the License published by the license steward.
+
+    4.3. Modified Versions.
+
+    When You are an Initial Developer and You want to create a new
+    license for Your Original Software, You may create and use a
+    modified version of this License if You: (a) rename the license and
+    remove any references to the name of the license steward (except to
+    note that the license differs from this License); and (b) otherwise
+    make it clear that the license contains terms which differ from this
+    License.
+
+5. DISCLAIMER OF WARRANTY.
+
+    COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+    WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+    INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE
+    IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+    NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF
+    THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE
+    DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY
+    OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING,
+    REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+    ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS
+    AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+6. TERMINATION.
+
+    6.1. This License and the rights granted hereunder will terminate
+    automatically if You fail to comply with terms herein and fail to
+    cure such breach within 30 days of becoming aware of the breach.
+    Provisions which, by their nature, must remain in effect beyond the
+    termination of this License shall survive.
+
+    6.2. If You assert a patent infringement claim (excluding
+    declaratory judgment actions) against Initial Developer or a
+    Contributor (the Initial Developer or Contributor against whom You
+    assert such claim is referred to as "Participant") alleging that the
+    Participant Software (meaning the Contributor Version where the
+    Participant is a Contributor or the Original Software where the
+    Participant is the Initial Developer) directly or indirectly
+    infringes any patent, then any and all rights granted directly or
+    indirectly to You by such Participant, the Initial Developer (if the
+    Initial Developer is not the Participant) and all Contributors under
+    Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice
+    from Participant terminate prospectively and automatically at the
+    expiration of such 60 day notice period, unless if within such 60
+    day period You withdraw Your claim with respect to the Participant
+    Software against such Participant either unilaterally or pursuant to
+    a written agreement with Participant.
+
+    6.3. If You assert a patent infringement claim against Participant
+    alleging that the Participant Software directly or indirectly
+    infringes any patent where such claim is resolved (such as by
+    license or settlement) prior to the initiation of patent
+    infringement litigation, then the reasonable value of the licenses
+    granted by such Participant under Sections 2.1 or 2.2 shall be taken
+    into account in determining the amount or value of any payment or
+    license.
+
+    6.4. In the event of termination under Sections 6.1 or 6.2 above,
+    all end user licenses that have been validly granted by You or any
+    distributor hereunder prior to termination (excluding licenses
+    granted to You by any distributor) shall survive termination.
+
+7. LIMITATION OF LIABILITY.
+
+    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+    (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
+    INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
+    COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE
+    TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
+    CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
+    LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER
+    FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
+    LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
+    POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT
+    APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+    PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+    LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR
+    LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION
+    AND LIMITATION MAY NOT APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS.
+
+    The Covered Software is a "commercial item," as that term is defined
+    in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+    software" (as that term is defined at 48 C.F.R. §
+    252.227-7014(a)(1)) and "commercial computer software documentation"
+    as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent
+    with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4
+    (June 1995), all U.S. Government End Users acquire Covered Software
+    with only those rights set forth herein. This U.S. Government Rights
+    clause is in lieu of, and supersedes, any other FAR, DFAR, or other
+    clause or provision that addresses Government rights in computer
+    software under this License.
+
+9. MISCELLANEOUS.
+
+    This License represents the complete agreement concerning subject
+    matter hereof. If any provision of this License is held to be
+    unenforceable, such provision shall be reformed only to the extent
+    necessary to make it enforceable. This License shall be governed by
+    the law of the jurisdiction specified in a notice contained within
+    the Original Software (except to the extent applicable law, if any,
+    provides otherwise), excluding such jurisdiction's conflict-of-law
+    provisions. Any litigation relating to this License shall be subject
+    to the jurisdiction of the courts located in the jurisdiction and
+    venue specified in a notice contained within the Original Software,
+    with the losing party responsible for costs, including, without
+    limitation, court costs and reasonable attorneys' fees and expenses.
+    The application of the United Nations Convention on Contracts for
+    the International Sale of Goods is expressly excluded. Any law or
+    regulation which provides that the language of a contract shall be
+    construed against the drafter shall not apply to this License. You
+    agree that You alone are responsible for compliance with the United
+    States export administration regulations (and the export control
+    laws and regulation of any other countries) when You use, distribute
+    or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS.
+
+    As between Initial Developer and the Contributors, each party is
+    responsible for claims and damages arising, directly or indirectly,
+    out of its utilization of rights under this License and You agree to
+    work with Initial Developer and Contributors to distribute such
+    responsibility on an equitable basis. Nothing herein is intended or
+    shall be deemed to constitute any admission of liability.
+
+------------------------------------------------------------------------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION
+LICENSE (CDDL)
+
+The code released under the CDDL shall be governed by the laws of the
+State of California (excluding conflict-of-law provisions). Any
+litigation relating to this License shall be subject to the jurisdiction
+of the Federal Courts of the Northern District of California and the
+state courts of the State of California, with venue lying in Santa Clara
+County, California.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-junit5.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-junit5.txt
new file mode 100644
index 0000000000..8ebced110a
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-junit5.txt
@@ -0,0 +1,98 @@
+Eclipse Public License - v 2.0
+==============================
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE (“AGREEMENT”). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+### 1. Definitions
+
+“Contribution” means:
+* **a)** in the case of the initial Contributor, the initial content Distributed under this Agreement, and
+* **b)** in the case of each subsequent Contributor:
+	* **i)** changes to the Program, and
+	* **ii)** additions to the Program;
+where such changes and/or additions to the Program originate from and are Distributed by that particular Contributor. A Contribution “originates” from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include changes or additions to the Program that are not Modified Works.
+
+“Contributor” means any person or entity that Distributes the Program.
+
+“Licensed Patents” mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
+
+“Program” means the Contributions Distributed in accordance with this Agreement.
+
+“Recipient” means anyone who receives the Program under this Agreement or any Secondary License (as applicable), including Contributors.
+
+“Derivative Works” shall mean any work, whether in Source Code or other form, that is based on (or derived from) the Program and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship.
+
+“Modified Works” shall mean any work in Source Code or other form that results from an addition to, deletion from, or modification of the contents of the Program, including, for purposes of clarity any new file in Source Code form that contains any contents of the Program. Modified Works shall not include works that contain only declarations, interfaces, types, classes, structures, or files of the Program solely in each case in order to link to, bind by name, or subclass the Program or Modified Works thereof.
+
+“Distribute” means the acts of **a)** distributing or **b)** making available in any manner that enables the transfer of a copy.
+
+“Source Code” means the form of a Program preferred for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+“Secondary License” means either the GNU General Public License, Version 2.0, or any later versions of that license, including any exceptions or additional permissions as identified by the initial Contributor.
+
+### 2. Grant of Rights
+
+**a)** Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, Distribute and sublicense the Contribution of such Contributor, if any, and such Derivative Works.
+
+**b)** Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in Source Code or other form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+
+**c)** Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to Distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+
+**d)** Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
+
+**e)** Notwithstanding the terms of any Secondary License, no Contributor makes additional grants to any Recipient (other than those set forth in this Agreement) as a result of such Recipient's receipt of the Program under the terms of a Secondary License (if permitted under the terms of Section 3).
+
+### 3. Requirements
+
+**3.1** If a Contributor Distributes the Program in any form, then:
+
+* **a)** the Program must also be made available as Source Code, in accordance with section 3.2, and the Contributor must accompany the Program with a statement that the Source Code for the Program is available under this Agreement, and informs Recipients how to obtain it in a reasonable manner on or through a medium customarily used for software exchange; and
+
+* **b)** the Contributor may Distribute the Program under a license different than this Agreement, provided that such license:
+	* **i)** effectively disclaims on behalf of all other Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
+	* **ii)** effectively excludes on behalf of all other Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
+	* **iii)** does not attempt to limit or alter the recipients' rights in the Source Code under section 3.2; and
+	* **iv)** requires any subsequent distribution of the Program by any party to be under a license that satisfies the requirements of this section 3.
+
+**3.2** When the Program is Distributed as Source Code:
+
+* **a)** it must be made available under this Agreement, or if the Program **(i)** is combined with other material in a separate file or files made available under a Secondary License, and **(ii)** the initial Contributor attached to the Source Code the notice described in Exhibit A of this Agreement, then the Program may be made available under the terms of such Secondary Licenses, and
+* **b)** a copy of this Agreement must be included with each copy of the Program.
+
+**3.3** Contributors may not remove or alter any copyright, patent, trademark, attribution notices, disclaimers of warranty, or limitations of liability (“notices”) contained within the Program from any copy of the Program which they Distribute, provided that Contributors may add their own appropriate notices.
+
+### 4. Commercial Distribution
+
+Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor (“Commercial Contributor”) hereby agrees to defend and indemnify every other Contributor (“Indemnified Contributor”) against any losses, damages and costs (collectively “Losses”) arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: **a)** promptly notify the Commercial Contributor in writing of such claim, and **b)** allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
+
+### 5. No Warranty
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
+
+### 6. Disclaimer of Liability
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+### 7. General
+
+If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be Distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to Distribute the Program (including its Contributions) under the new version.
+
+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. Nothing in this Agreement is intended to be enforceable by any entity that is not a Contributor or Recipient. No third-party beneficiary rights are created under this Agreement.
+
+#### Exhibit A - Form of Secondary Licenses Notice
+
+> “This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), version(s), and exceptions or additional permissions here}.”
+
+Simply including a copy of this Agreement, including this Exhibit A is not sufficient to license the Source Code under Secondary Licenses.
+
+If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.
+
+You may add additional accurate notices of copyright ownership.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-api.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-api.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-api.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-core.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-core.txt
new file mode 100644
index 0000000000..6279e5206d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-core.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 1999-2005 The Apache Software Foundation
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-slf4j-impl.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-slf4j-impl.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-log4j-slf4j-impl.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-netty.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-netty.txt
new file mode 100644
index 0000000000..e25e752cf1
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-netty.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        https://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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
+
+       https://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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-okhttp.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-okhttp.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-okhttp.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-opentracing-java.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-opentracing-java.txt
new file mode 100644
index 0000000000..8dada3edaf
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-opentracing-java.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed 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.
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-perfmark.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-perfmark.txt
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-perfmark.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-protobuf.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-protobuf.txt
new file mode 100644
index 0000000000..97a6e3d199
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-protobuf.txt
@@ -0,0 +1,32 @@
+Copyright 2008 Google Inc.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Code generated by the Protocol Buffer compiler is owned by the owner
+of the input file used when generating it.  This code is not
+standalone and requires a support library to be linked with it.  This
+support library is itself covered by the above license.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-slf4j.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-slf4j.txt
new file mode 100644
index 0000000000..a51675a21c
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-slf4j.txt
@@ -0,0 +1,23 @@
+Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland)
+All rights reserved.
+
+Permission is hereby granted, free  of charge, to any person obtaining
+a  copy  of this  software  and  associated  documentation files  (the
+"Software"), to  deal in  the Software without  restriction, including
+without limitation  the rights to  use, copy, modify,  merge, publish,
+distribute,  sublicense, and/or sell  copies of  the Software,  and to
+permit persons to whom the Software  is furnished to do so, subject to
+the following conditions:
+
+The  above  copyright  notice  and  this permission  notice  shall  be
+included in all copies or substantial portions of the Software.
+
+THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-bolt.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-bolt.txt
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-bolt.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-boot.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-boot.txt
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-boot.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-common-tools.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-common-tools.txt
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-common-tools.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-hessian.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-hessian.txt
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-hessian.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-lookout.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-lookout.txt
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-lookout.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-rpc.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-rpc.txt
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-sofa-rpc.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-annotations.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-annotations.txt
new file mode 100644
index 0000000000..e280013182
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-annotations.txt
@@ -0,0 +1,11 @@
+Copyright 2016 SmartBear Software
+
+Licensed 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 [apache.org/licenses/LICENSE-2.0](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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-core.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-core.txt
new file mode 100644
index 0000000000..3e5194180d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-core.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright (c) 2015. SmartBear Software Inc.
+
+   Licensed 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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-models.txt b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-models.txt
new file mode 100644
index 0000000000..e280013182
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/release-docs/licenses/LICENSE-swagger-models.txt
@@ -0,0 +1,11 @@
+Copyright 2016 SmartBear Software
+
+Licensed 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 [apache.org/licenses/LICENSE-2.0](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.
\ No newline at end of file
diff --git a/hugegraph-commons/hugegraph-dist/scripts/apache-release.sh b/hugegraph-commons/hugegraph-dist/scripts/apache-release.sh
new file mode 100755
index 0000000000..66faae9ce9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/scripts/apache-release.sh
@@ -0,0 +1,105 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+GROUP="hugegraph"
+# current repository name
+REPO="${GROUP}-commons"
+# release version (input by committer)
+RELEASE_VERSION=$1
+USERNAME=$2
+PASSWORD=$3
+# git release branch (check it carefully)
+GIT_BRANCH="release-${RELEASE_VERSION}"
+
+RELEASE_VERSION=${RELEASE_VERSION:?"Please input the release version behind script"}
+
+WORK_DIR=$(
+  cd "$(dirname "$0")" || exit
+  pwd
+)
+cd "${WORK_DIR}" || exit
+echo "In the work dir: $(pwd)"
+
+# clean old dir then build a new one
+rm -rf dist && mkdir -p dist/apache-${REPO}
+
+# step1: package the source code
+cd ../../ || exit
+git archive --format=tar.gz \
+  --output="${GROUP}-dist/scripts/dist/apache-${REPO}/apache-${REPO}-incubating-${RELEASE_VERSION}-src.tar.gz" \
+  --prefix="apache-${REPO}-incubating-${RELEASE_VERSION}-src/" "${GIT_BRANCH}" || exit
+
+cd - || exit
+
+# step2: copy the binary file (Optional)
+# Note: it's optional for project to generate binary package (skip this step if not need)
+#cp -v ../../target/apache-${REPO}-incubating-"${RELEASE_VERSION}".tar.gz \
+#  dist/apache-${REPO} || exit
+
+# step3: sign + hash
+##### 3.1 sign in source & binary package
+gpg --version 1>/dev/null || exit
+cd ./dist/apache-${REPO} || exit
+for i in *.tar.gz; do
+  echo "$i" && gpg --armor --output "$i".asc --detach-sig "$i"
+done
+
+##### 3.2 Generate SHA512 file
+shasum --version 1>/dev/null || exit
+for i in *.tar.gz; do
+  shasum -a 512 "$i" | tee "$i".sha512
+done
+
+#### 3.3 check signature & sha512
+echo "#### start to check signature & hashcode ####"
+for i in *.tar.gz; do
+  echo "$i"
+  gpg --verify "$i".asc "$i" || exit
+done
+
+for i in *.tar.gz; do
+  echo "$i"
+  shasum -a 512 --check "$i".sha512 || exit
+done
+
+# step4: upload to Apache-SVN
+SVN_DIR="${GROUP}-svn-dev"
+cd ../
+rm -rfv ${SVN_DIR}
+
+##### 4.1 pull from remote & copy files
+svn co "https://dist.apache.org/repos/dist/dev/incubator/${GROUP}" ${SVN_DIR}
+mkdir -p ${SVN_DIR}/"${RELEASE_VERSION}"
+cp -v apache-${REPO}/*tar.gz* "${SVN_DIR}/${RELEASE_VERSION}"
+cd ${SVN_DIR} || exit
+
+##### 4.2 check status first
+svn status
+svn add --parents "${RELEASE_VERSION}"/apache-${REPO}-*
+# check status again
+svn status
+
+##### 4.3 commit & push files
+if [ "$USERNAME" = "" ]; then
+  svn commit -m "submit files for ${REPO} ${RELEASE_VERSION}" || exit
+else
+  svn commit -m "submit files for ${REPO} ${RELEASE_VERSION}" \
+    --username "${USERNAME}" --password "${PASSWORD}" || exit
+fi
+
+echo "Finished all, please check all steps in script manually again!"
diff --git a/hugegraph-commons/hugegraph-dist/scripts/dependency/check_dependencies.sh b/hugegraph-commons/hugegraph-dist/scripts/dependency/check_dependencies.sh
new file mode 100644
index 0000000000..642c455aa9
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/scripts/dependency/check_dependencies.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+BASE_PATH=$(cd "$(dirname "$0")" || exit; pwd)
+
+# check whether there are new third-party dependencies by diff command,
+# diff generated 'current-dependencies.txt' file with 'known-dependencies.txt' file.
+diff -w -B -U0 <(sort < "${BASE_PATH}"/known-dependencies.txt) \
+  <(sort < "${BASE_PATH}"/current-dependencies.txt) > "${BASE_PATH}"/result.txt
+
+# if has new third-party,the Action will fail and print diff
+if [ -s "${BASE_PATH}"/result.txt ]; then
+  cat "${BASE_PATH}"/result.txt
+  exit 1
+else
+  echo 'All third dependencies is known!'
+fi
diff --git a/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt b/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt
new file mode 100644
index 0000000000..53b4567d5b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/scripts/dependency/known-dependencies.txt
@@ -0,0 +1,77 @@
+animal-sniffer-annotations-1.18.jar
+annotations-4.1.1.4.jar
+annotations-13.0.jar
+bolt-1.6.2.jar
+checker-qual-3.5.0.jar
+commons-beanutils-1.9.4.jar
+commons-codec-1.13.jar
+commons-collections-3.2.2.jar
+commons-configuration-1.10.jar
+commons-configuration2-2.8.0.jar
+commons-io-2.7.jar
+commons-lang-2.6.jar
+commons-lang3-3.12.0.jar
+commons-logging-1.1.1.jar
+commons-text-1.9.jar
+disruptor-3.3.7.jar
+error_prone_annotations-2.3.4.jar
+failureaccess-1.0.1.jar
+grpc-api-1.28.1.jar
+grpc-context-1.28.1.jar
+grpc-core-1.28.1.jar
+grpc-netty-shaded-1.28.0.jar
+grpc-protobuf-1.28.0.jar
+grpc-protobuf-lite-1.28.0.jar
+grpc-stub-1.28.0.jar
+gson-2.8.6.jar
+guava-30.0-jre.jar
+hamcrest-core-1.3.jar
+hessian-3.3.7.jar
+j2objc-annotations-1.3.jar
+jackson-annotations-2.14.0-rc1.jar
+jackson-core-2.14.0-rc1.jar
+jackson-databind-2.14.0-rc1.jar
+jackson-dataformat-yaml-2.9.3.jar
+jackson-jaxrs-base-2.14.0-rc1.jar
+jackson-jaxrs-json-provider-2.14.0-rc1.jar
+jackson-module-jaxb-annotations-2.14.0-rc1.jar
+jakarta.activation-2.0.1.jar
+jakarta.activation-api-1.2.2.jar
+javassist-3.28.0-GA.jar
+javax.json-1.0.jar
+jaxb-core-3.0.2.jar
+jaxb-impl-3.0.2.jar
+joda-time-2.10.8.jar
+jsr305-3.0.1.jar
+junit-4.13.1.jar
+listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
+log4j-api-2.18.0.jar
+log4j-core-2.18.0.jar
+log4j-slf4j-impl-2.18.0.jar
+lookout-api-1.4.1.jar
+netty-all-4.1.42.Final.jar
+opentracing-api-0.22.0.jar
+opentracing-mock-0.22.0.jar
+opentracing-noop-0.22.0.jar
+opentracing-util-0.22.0.jar
+perfmark-api-0.19.0.jar
+proto-google-common-protos-1.17.0.jar
+protobuf-java-3.11.0.jar
+slf4j-api-1.7.25.jar
+snakeyaml-1.18.jar
+sofa-common-tools-1.0.12.jar
+sofa-rpc-all-5.7.6.jar
+swagger-annotations-1.5.18.jar
+swagger-core-1.5.18.jar
+swagger-models-1.5.18.jar
+tracer-core-3.0.8.jar
+validation-api-1.1.0.Final.jar
+kotlin-stdlib-1.6.20.jar
+kotlin-stdlib-common-1.5.31.jar
+kotlin-stdlib-jdk7-1.6.10.jar
+kotlin-stdlib-jdk8-1.6.10.jar
+logging-interceptor-4.10.0.jar
+lombok-1.18.8.jar
+okhttp-4.10.0.jar
+okio-jvm-3.0.0.jar
+
diff --git a/hugegraph-commons/hugegraph-dist/scripts/dependency/regenerate_known_dependencies.sh b/hugegraph-commons/hugegraph-dist/scripts/dependency/regenerate_known_dependencies.sh
new file mode 100644
index 0000000000..91f8b986ad
--- /dev/null
+++ b/hugegraph-commons/hugegraph-dist/scripts/dependency/regenerate_known_dependencies.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+BASE_PATH=$(cd "$(dirname "$0")" || exit; pwd)
+DEP_PATH=$BASE_PATH/all_dependencies
+FILE_NAME=${1:-known-dependencies.txt}
+
+if [[ -d $DEP_PATH ]]; then
+  echo "rm -r -f DEP_PATH"
+  rm -r -f "$DEP_PATH"
+fi
+
+cd "$BASE_PATH"/../../../ || exit
+
+mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory="$DEP_PATH"
+
+ls "$DEP_PATH" | egrep -v "^hugegraph|hubble" | sort -n > "$BASE_PATH"/"$FILE_NAME"
+rm -r -f "$DEP_PATH"
diff --git a/hugegraph-commons/hugegraph-rpc/README.md b/hugegraph-commons/hugegraph-rpc/README.md
new file mode 100644
index 0000000000..c316a9c412
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/README.md
@@ -0,0 +1,14 @@
+# HugeGraph-RPC
+
+HugeGraph Database RPC component, currently it's based on [Sofa-RPC](https://github.com/sofastack/sofa-rpc)
+
+## Features
+
+## Learn More
+
+The [project homepage](https://hugegraph.github.io/hugegraph-doc/) contains more information on 
+HugeGraph and provides links to documentation, getting-started guides and release downloads.
+
+## License
+
+HugeGraph is licensed under Apache 2.0 License.
diff --git a/hugegraph-commons/hugegraph-rpc/pom.xml b/hugegraph-commons/hugegraph-rpc/pom.xml
new file mode 100644
index 0000000000..0637da1c5c
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/pom.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.hugegraph</groupId>
+        <artifactId>hugegraph-commons</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>hugegraph-rpc</artifactId>
+    <name>${project.artifactId}</name>
+    <description>HugeGraph RPC component</description>
+
+    <properties>
+        <!-- Use parent params -->
+    </properties>
+
+    <dependencies>
+        <!-- hugegraph-common -->
+        <dependency>
+            <groupId>org.apache.hugegraph</groupId>
+            <artifactId>hugegraph-common</artifactId>
+            <version>${revision}</version>
+        </dependency>
+
+        <!-- sofa rpc -->
+        <dependency>
+            <groupId>com.lmax</groupId>
+            <artifactId>disruptor</artifactId>
+            <version>3.3.7</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alipay.sofa</groupId>
+            <artifactId>bolt</artifactId>
+            <version>1.6.2</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.alipay.sofa</groupId>
+            <artifactId>sofa-rpc-all</artifactId>
+            <version>5.7.6</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.resteasy</groupId>
+                    <artifactId>resteasy-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.jboss.resteasy</groupId>
+                    <artifactId>resteasy-netty4</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.jboss.resteasy</groupId>
+                    <artifactId>resteasy-jackson2-provider</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpclient</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpcore</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpmime</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.jboss.logging</groupId>
+                    <artifactId>jboss-logging</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>io.grpc</groupId>
+                    <artifactId>grpc-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-core</artifactId>
+            <version>1.28.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>0.8.2</version>
+                <executions>
+                    <execution>
+                        <id>pre-unit-test</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>post-unit-test</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.parent.build.directory}</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>apache-release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-source-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/config/RpcOptions.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/config/RpcOptions.java
new file mode 100644
index 0000000000..09adcbab84
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/config/RpcOptions.java
@@ -0,0 +1,158 @@
+/*
+ * 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.hugegraph.config;
+
+import static org.apache.hugegraph.config.OptionChecker.allowValues;
+import static org.apache.hugegraph.config.OptionChecker.disallowEmpty;
+import static org.apache.hugegraph.config.OptionChecker.rangeInt;
+
+public class RpcOptions extends OptionHolder {
+
+    private RpcOptions() {
+        super();
+    }
+
+    private static volatile RpcOptions instance;
+
+    public static synchronized RpcOptions instance() {
+        if (instance == null) {
+            instance = new RpcOptions();
+            instance.registerOptions();
+        }
+        return instance;
+    }
+
+    public static final ConfigOption<String> RPC_SERVER_HOST =
+            new ConfigOption<>(
+                    "rpc.server_host",
+                    "The hosts/ips bound by rpc server to provide services, " +
+                    "empty value means not enabled.",
+                    null,
+                    ""
+            );
+
+    public static final ConfigOption<Integer> RPC_SERVER_PORT =
+            new ConfigOption<>(
+                    "rpc.server_port",
+                    "The port bound by rpc server to provide services.",
+                    rangeInt(0, Integer.MAX_VALUE),
+                    8090
+            );
+
+    public static final ConfigOption<Boolean> RPC_ADAPTIVE_PORT =
+            new ConfigOption<>(
+                    "rpc.server_adaptive_port",
+                    "Whether the bound port is adaptive, if it's enabled, " +
+                    "when the port is in use, automatically +1 to detect " +
+                    "the next available port. Note that this process is " +
+                    "not atomic, so there may still be port conflicts.",
+                    disallowEmpty(),
+                    false
+            );
+
+    public static final ConfigOption<Integer> RPC_SERVER_TIMEOUT =
+            new ConfigOption<>(
+                    "rpc.server_timeout",
+                    "The timeout(in seconds) of rpc server execution.",
+                    rangeInt(1, Integer.MAX_VALUE),
+                    30
+            );
+
+    public static final ConfigOption<String> RPC_REMOTE_URL =
+            new ConfigOption<>(
+                    "rpc.remote_url",
+                    "The remote urls of rpc peers, it can be set to " +
+                    "multiple addresses, which are concat by ',', " +
+                    "empty value means not enabled.",
+                    null,
+                    ""
+            );
+
+    public static final ConfigOption<Integer> RPC_CLIENT_CONNECT_TIMEOUT =
+            new ConfigOption<>(
+                    "rpc.client_connect_timeout",
+                    "The timeout(in seconds) of rpc client connect to rpc " +
+                    "server.",
+                    rangeInt(1, Integer.MAX_VALUE),
+                    20
+            );
+
+    public static final ConfigOption<Integer> RPC_CLIENT_RECONNECT_PERIOD =
+            new ConfigOption<>(
+                    "rpc.client_reconnect_period",
+                    "The period(in seconds) of rpc client reconnect to rpc " +
+                    "server.",
+                    rangeInt(1, Integer.MAX_VALUE),
+                    10
+            );
+
+    public static final ConfigOption<Integer> RPC_CLIENT_READ_TIMEOUT =
+            new ConfigOption<>(
+                    "rpc.client_read_timeout",
+                    "The timeout(in seconds) of rpc client read from rpc " +
+                    "server.",
+                    rangeInt(1, Integer.MAX_VALUE),
+                    40
+            );
+
+    public static final ConfigOption<Integer> RPC_CLIENT_RETRIES =
+            new ConfigOption<>(
+                    "rpc.client_retries",
+                    "Failed retry number of rpc client calls to rpc server.",
+                    rangeInt(0, Integer.MAX_VALUE),
+                    3
+            );
+
+    public static final ConfigOption<String> RPC_CLIENT_LOAD_BALANCER =
+            new ConfigOption<>(
+                    "rpc.client_load_balancer",
+                    "The rpc client uses a load-balancing algorithm to " +
+                    "access multiple rpc servers in one cluster. Default " +
+                    "value is 'consistentHash', means forwarding by request " +
+                    "parameters.",
+                    allowValues("random", "localPref", "roundRobin",
+                                "consistentHash", "weightRoundRobin"),
+                    "consistentHash"
+            );
+
+    public static final ConfigOption<String> RPC_PROTOCOL =
+            new ConfigOption<>(
+                    "rpc.protocol",
+                    "Rpc communication protocol, client and server need to " +
+                    "be specified the same value.",
+                    allowValues("bolt", "rest", "dubbo", "h2c", "http"),
+                    "bolt"
+            );
+
+    public static final ConfigOption<Integer> RPC_CONFIG_ORDER =
+            new ConfigOption<>(
+                    "rpc.config_order",
+                    "Sofa rpc configuration file loading order, the larger " +
+                    "the more later loading.",
+                    rangeInt(1, Integer.MAX_VALUE),
+                    999
+            );
+
+    public static final ConfigOption<String> RPC_LOGGER_IMPL =
+            new ConfigOption<>(
+                    "rpc.logger_impl",
+                    "Sofa rpc log implementation class.",
+                    disallowEmpty(),
+                    "com.alipay.sofa.rpc.log.SLF4JLoggerImpl"
+            );
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcClientProvider.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcClientProvider.java
new file mode 100644
index 0000000000..2b50468b9f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcClientProvider.java
@@ -0,0 +1,74 @@
+/*
+ * 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.hugegraph.rpc;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.alipay.sofa.rpc.common.utils.StringUtils;
+import org.apache.hugegraph.config.RpcOptions;
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.util.E;
+
+public class RpcClientProvider {
+
+    private final RpcConsumerConfig consumerConfig;
+
+    public RpcClientProvider(HugeConfig config) {
+        // TODO: fetch from registry server
+        String rpcUrl = config.get(RpcOptions.RPC_REMOTE_URL);
+        String selfUrl = config.get(RpcOptions.RPC_SERVER_HOST) + ":" +
+                         config.get(RpcOptions.RPC_SERVER_PORT);
+        rpcUrl = excludeSelfUrl(rpcUrl, selfUrl);
+        this.consumerConfig = StringUtils.isNotBlank(rpcUrl) ?
+                              new RpcConsumerConfig(config, rpcUrl) : null;
+    }
+
+    public boolean enabled() {
+        return this.consumerConfig != null;
+    }
+
+    public RpcConsumerConfig config() {
+        E.checkArgument(this.consumerConfig != null,
+                        "RpcClient is not enabled, please config option '%s' " +
+                        "and ensure to add an address other than self service",
+                        RpcOptions.RPC_REMOTE_URL.name());
+        return this.consumerConfig;
+    }
+
+    public void unreferAll() {
+        if (this.consumerConfig != null) {
+            this.consumerConfig.removeAllServiceProxy();
+        }
+    }
+
+    public void destroy() {
+        if (this.consumerConfig != null) {
+            this.consumerConfig.destroy();
+        }
+    }
+
+    protected static String excludeSelfUrl(String rpcUrl, String selfUrl) {
+        String[] urls = StringUtils.splitWithCommaOrSemicolon(rpcUrl);
+        // Keep urls order via LinkedHashSet
+        Set<String> urlSet = new LinkedHashSet<>(Arrays.asList(urls));
+        urlSet.remove(selfUrl);
+        return String.join(",", urlSet);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcCommonConfig.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcCommonConfig.java
new file mode 100644
index 0000000000..37ec980302
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcCommonConfig.java
@@ -0,0 +1,44 @@
+/*
+ * 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.hugegraph.rpc;
+
+import java.util.Map;
+
+import com.alipay.sofa.rpc.common.RpcConfigs;
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.config.RpcOptions;
+
+public class RpcCommonConfig {
+
+    public static void initRpcConfigs(HugeConfig config) {
+        RpcConfigs.putValue("rpc.config.order",
+                            config.get(RpcOptions.RPC_CONFIG_ORDER));
+        RpcConfigs.putValue("logger.impl",
+                            config.get(RpcOptions.RPC_LOGGER_IMPL));
+    }
+
+    public static void initRpcConfigs(String key, Object value) {
+        RpcConfigs.putValue(key, value);
+    }
+
+    public static void initRpcConfigs(Map<String, Object> conf) {
+        for (Map.Entry<String, Object> entry : conf.entrySet()) {
+            RpcConfigs.putValue(entry.getKey(), entry.getValue());
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcConsumerConfig.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcConsumerConfig.java
new file mode 100644
index 0000000000..c489f5cd9b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcConsumerConfig.java
@@ -0,0 +1,215 @@
+/*
+ * 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.hugegraph.rpc;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.slf4j.Logger;
+
+import com.alipay.sofa.rpc.bootstrap.Bootstraps;
+import com.alipay.sofa.rpc.bootstrap.ConsumerBootstrap;
+import com.alipay.sofa.rpc.client.AbstractCluster;
+import com.alipay.sofa.rpc.client.Cluster;
+import com.alipay.sofa.rpc.client.ProviderInfo;
+import com.alipay.sofa.rpc.config.ConsumerConfig;
+import com.alipay.sofa.rpc.core.exception.RpcErrorType;
+import com.alipay.sofa.rpc.core.exception.SofaRpcException;
+import com.alipay.sofa.rpc.core.request.SofaRequest;
+import com.alipay.sofa.rpc.core.response.SofaResponse;
+import com.alipay.sofa.rpc.ext.Extension;
+import com.alipay.sofa.rpc.ext.ExtensionLoaderFactory;
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.config.RpcOptions;
+import org.apache.hugegraph.util.Log;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class RpcConsumerConfig implements RpcServiceConfig4Client {
+
+    private final HugeConfig conf;
+    private final String remoteUrls;
+    private final Map<String, ConsumerConfig<?>> configs;
+    private final List<ConsumerBootstrap<?>> bootstraps;
+
+    static {
+        ExtensionLoaderFactory.getExtensionLoader(Cluster.class)
+                              .loadExtension(FanoutCluster.class);
+    }
+
+    public RpcConsumerConfig(HugeConfig config, String remoteUrls) {
+        RpcCommonConfig.initRpcConfigs(config);
+        this.conf = config;
+        this.remoteUrls = remoteUrls;
+        this.configs = Maps.newHashMap();
+        this.bootstraps = Lists.newArrayList();
+    }
+
+    @Override
+    public <T> T serviceProxy(String interfaceId) {
+        return this.serviceProxy(null, interfaceId);
+    }
+
+    @Override
+    public <T> T serviceProxy(String graph, String interfaceId) {
+        ConsumerConfig<T> config = this.consumerConfig(graph, interfaceId);
+        ConsumerBootstrap<T> bootstrap = Bootstraps.from(config);
+        this.bootstraps.add(bootstrap);
+        return bootstrap.refer();
+    }
+
+    @Override
+    public void removeAllServiceProxy() {
+        for (ConsumerBootstrap<?> bootstrap : this.bootstraps) {
+            bootstrap.unRefer();
+        }
+    }
+
+    public void destroy() {
+        Set<Cluster> clusters = Sets.newHashSet();
+        for (ConsumerBootstrap<?> bootstrap : this.bootstraps) {
+            bootstrap.unRefer();
+            clusters.add(bootstrap.getCluster());
+        }
+        for (Cluster cluster : clusters) {
+            cluster.destroy();
+        }
+    }
+
+    private <T> ConsumerConfig<T> consumerConfig(String graph,
+                                                 String interfaceId) {
+        String serviceId;
+        if (graph != null) {
+            serviceId = interfaceId + ":" + graph;
+        } else {
+            serviceId = interfaceId;
+        }
+
+        @SuppressWarnings("unchecked")
+        ConsumerConfig<T> consumerConfig = (ConsumerConfig<T>)
+                                           this.configs.get(serviceId);
+        if (consumerConfig != null) {
+            return consumerConfig;
+        }
+
+        assert consumerConfig == null;
+        consumerConfig = new ConsumerConfig<>();
+
+        HugeConfig conf = this.conf;
+        String protocol = conf.get(RpcOptions.RPC_PROTOCOL);
+        int timeout = conf.get(RpcOptions.RPC_CLIENT_READ_TIMEOUT) * 1000;
+        int connectTimeout = conf.get(RpcOptions
+                                      .RPC_CLIENT_CONNECT_TIMEOUT) * 1000;
+        int reconnectPeriod = conf.get(RpcOptions
+                                       .RPC_CLIENT_RECONNECT_PERIOD) * 1000;
+        int retries = conf.get(RpcOptions.RPC_CLIENT_RETRIES);
+        String loadBalancer = conf.get(RpcOptions.RPC_CLIENT_LOAD_BALANCER);
+
+        if (graph != null) {
+            consumerConfig.setId(serviceId).setUniqueId(graph);
+            // Default is FailoverCluster, set to FanoutCluster to broadcast
+            consumerConfig.setCluster("fanout");
+        }
+        consumerConfig.setInterfaceId(interfaceId)
+                      .setProtocol(protocol)
+                      .setDirectUrl(this.remoteUrls)
+                      .setTimeout(timeout)
+                      .setConnectTimeout(connectTimeout)
+                      .setReconnectPeriod(reconnectPeriod)
+                      .setRetries(retries)
+                      .setLoadBalancer(loadBalancer);
+
+        this.configs.put(serviceId, consumerConfig);
+        return consumerConfig;
+    }
+
+    @Extension("fanout")
+    private static class FanoutCluster extends AbstractCluster {
+
+        private static final Logger LOG = Log.logger(FanoutCluster.class);
+
+        FanoutCluster(ConsumerBootstrap<?> consumerBootstrap) {
+            super(consumerBootstrap);
+        }
+
+        @Override
+        protected SofaResponse doInvoke(SofaRequest request)
+                                        throws SofaRpcException {
+            List<ProviderInfo> providers = this.getRouterChain()
+                                               .route(request, null);
+            List<SofaResponse> responses = new ArrayList<>(providers.size());
+            List<SofaRpcException> excepts = new ArrayList<>(providers.size());
+
+            for (ProviderInfo provider : providers) {
+                try {
+                    SofaResponse response = this.doInvoke(request, provider);
+                    responses.add(response);
+                } catch (SofaRpcException e) {
+                    excepts.add(e);
+                    LOG.warn("{}.(error {})", e.getMessage(), e.getErrorType());
+                }
+            }
+
+            if (responses.size() > 0) {
+                /*
+                 * Just choose the first one as result to return, ignore others
+                 * TODO: maybe more strategies should be provided
+                 */
+                return responses.get(0);
+            } else if (excepts.size() > 0) {
+                throw excepts.get(0);
+            } else {
+                assert providers.isEmpty();
+                String method = methodName(request);
+                throw new SofaRpcException(RpcErrorType.CLIENT_ROUTER,
+                                           "No service provider for " + method);
+            }
+        }
+
+        private SofaResponse doInvoke(SofaRequest request,
+                                      ProviderInfo providerInfo) {
+            try {
+                SofaResponse response = this.filterChain(providerInfo, request);
+                if (response != null) {
+                    return response;
+                }
+                String method = methodName(request);
+                throw new SofaRpcException(RpcErrorType.CLIENT_UNDECLARED_ERROR,
+                          "Failed to call " + method + " on remote server " +
+                          providerInfo + ", return null response");
+            } catch (Exception e) {
+                int error = RpcErrorType.CLIENT_UNDECLARED_ERROR;
+                if (e instanceof SofaRpcException) {
+                    error = ((SofaRpcException) e).getErrorType();
+                }
+                String method = methodName(request);
+                throw new SofaRpcException(error,
+                          "Failed to call " + method + " on remote server " +
+                          providerInfo + ", caused by exception: " + e);
+            }
+        }
+
+        private static String methodName(SofaRequest request) {
+            return request.getInterfaceName() + "." +
+                   request.getMethodName() + "()";
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcException.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcException.java
new file mode 100644
index 0000000000..59e80f3d53
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hugegraph.rpc;
+
+public class RpcException extends RuntimeException {
+
+    private static final long serialVersionUID = -6067652498161184537L;
+
+    public RpcException(String message) {
+        super(message);
+    }
+
+    public RpcException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public RpcException(String message, Object... args) {
+        super(String.format(message, args));
+    }
+
+    public RpcException(String message, Throwable cause, Object... args) {
+        super(String.format(message, args), cause);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcProviderConfig.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcProviderConfig.java
new file mode 100644
index 0000000000..dafdfcf5a4
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcProviderConfig.java
@@ -0,0 +1,83 @@
+/*
+ * 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.hugegraph.rpc;
+
+import java.util.Map;
+
+import com.alipay.sofa.rpc.config.ProviderConfig;
+import org.apache.hugegraph.util.E;
+import com.google.common.collect.Maps;
+
+public class RpcProviderConfig implements RpcServiceConfig4Server {
+
+    private final Map<String, ProviderConfig<?>> configs = Maps.newHashMap();
+
+    @Override
+    public <T, S extends T> String addService(Class<T> clazz, S serviceImpl) {
+        return this.addService(null, clazz.getName(), serviceImpl);
+    }
+
+    @Override
+    public <T, S extends T> String addService(String graph,
+                                              Class<T> clazz,
+                                              S serviceImpl) {
+        return this.addService(graph, clazz.getName(), serviceImpl);
+    }
+
+    private <T, S extends T> String addService(String graph,
+                                               String interfaceId,
+                                               S serviceImpl) {
+        ProviderConfig<T> providerConfig = new ProviderConfig<>();
+        String serviceId;
+        if (graph != null) {
+            serviceId = interfaceId + ":" + graph;
+            providerConfig.setId(serviceId).setUniqueId(graph);
+        } else {
+            serviceId = interfaceId;
+        }
+
+        providerConfig.setInterfaceId(interfaceId)
+                      .setRef(serviceImpl);
+
+        E.checkArgument(!this.configs.containsKey(serviceId),
+                        "Not allowed to add service already exist: '%s'",
+                        serviceId);
+        this.configs.put(serviceId, providerConfig);
+        return serviceId;
+    }
+
+    @Override
+    public void removeService(String serviceId) {
+        ProviderConfig<?> config = this.configs.remove(serviceId);
+        E.checkArgument(config != null,
+                        "The service '%s' doesn't exist", serviceId);
+        config.unExport();
+    }
+
+    @Override
+    public void removeAllService() {
+        for (ProviderConfig<?> config : this.configs.values()) {
+            config.unExport();
+        }
+        this.configs.clear();
+    }
+
+    public Map<String, ProviderConfig<?>> configs() {
+        return this.configs;
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServer.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServer.java
new file mode 100644
index 0000000000..fe0b91ac58
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServer.java
@@ -0,0 +1,147 @@
+/*
+ * 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.hugegraph.rpc;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+
+import com.alipay.remoting.RemotingServer;
+import com.alipay.sofa.rpc.common.utils.StringUtils;
+import com.alipay.sofa.rpc.config.ProviderConfig;
+import com.alipay.sofa.rpc.config.ServerConfig;
+import com.alipay.sofa.rpc.server.Server;
+import com.alipay.sofa.rpc.server.bolt.BoltServer;
+import org.apache.hugegraph.config.RpcOptions;
+import org.apache.commons.collections.MapUtils;
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.testutil.Whitebox;
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.Log;
+
+public class RpcServer {
+
+    private static final Logger LOG = Log.logger(RpcServer.class);
+
+    private final HugeConfig conf;
+    private final RpcProviderConfig configs;
+    private final ServerConfig serverConfig;
+
+    public RpcServer(HugeConfig config) {
+        RpcCommonConfig.initRpcConfigs(config);
+        this.conf = config;
+        this.configs = new RpcProviderConfig();
+
+        String host = config.get(RpcOptions.RPC_SERVER_HOST);
+        if (StringUtils.isNotBlank(host)) {
+            int port = config.get(RpcOptions.RPC_SERVER_PORT);
+            boolean adaptivePort = config.get(RpcOptions.RPC_ADAPTIVE_PORT);
+            this.serverConfig = new ServerConfig();
+            this.serverConfig.setProtocol(config.get(RpcOptions.RPC_PROTOCOL))
+                             .setHost(host).setPort(port)
+                             .setAdaptivePort(adaptivePort)
+                             .setDaemon(false);
+        } else {
+            this.serverConfig = null;
+        }
+    }
+
+    public boolean enabled() {
+        return this.serverConfig != null;
+    }
+
+    public RpcProviderConfig config() {
+        this.checkEnabled();
+        return this.configs;
+    }
+
+    public String host() {
+        this.checkEnabled();
+        return this.serverConfig.getBoundHost();
+    }
+
+    public int port() {
+        this.checkEnabled();
+        Server server = this.serverConfig.getServer();
+        if (server instanceof BoltServer && server.isStarted()) {
+            /*
+             * When using random port 0, try to fetch the actual port
+             * NOTE: RemotingServer.port() would return the actual port only
+             *       if sofa-bolt version >= 1.6.1, please see:
+             *       https://github.com/sofastack/sofa-bolt/issues/196
+             * TODO: remove this code after adding Server.port() interface:
+             *       https://github.com/sofastack/sofa-rpc/issues/1022
+             */
+            RemotingServer rs = Whitebox.getInternalState(server,
+                                                          "remotingServer");
+            return rs.port();
+        }
+        // When using random port 0, the returned port is not the actual port
+        return this.serverConfig.getPort();
+    }
+
+    public void exportAll() {
+        this.checkEnabled();
+        LOG.debug("RpcServer starting on port {}", this.port());
+        Map<String, ProviderConfig<?>> configs = this.configs.configs();
+        if (MapUtils.isEmpty(configs)) {
+            LOG.info("RpcServer config is empty, skip starting RpcServer");
+            return;
+        }
+        int timeout = this.conf.get(RpcOptions.RPC_SERVER_TIMEOUT) * 1000;
+        for (ProviderConfig<?> providerConfig : configs.values()) {
+            providerConfig.setServer(this.serverConfig)
+                          .setTimeout(timeout)
+                          .export();
+        }
+        LOG.info("RpcServer started success on port {}", this.port());
+    }
+
+    public void unexportAll() {
+        this.configs.removeAllService();
+    }
+
+    public void unexport(String serviceId) {
+        this.configs.removeService(serviceId);
+    }
+
+    public void destroy() {
+        if (!this.enabled()) {
+            return;
+        }
+        LOG.info("RpcServer stop on port {}", this.port());
+        for (ProviderConfig<?> config : this.configs.configs().values()) {
+            Object service = config.getRef();
+            if (service instanceof AutoCloseable) {
+                try {
+                    ((AutoCloseable) service).close();
+                } catch (Exception e) {
+                    LOG.warn("Failed to close service {}", service, e);
+                }
+            }
+        }
+        this.serverConfig.destroy();
+        this.configs.removeAllService();
+    }
+
+    private void checkEnabled() {
+        E.checkArgument(this.enabled(),
+                        "RpcServer is not enabled, please config option '%s'",
+                        RpcOptions.RPC_SERVER_HOST.name());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java
new file mode 100644
index 0000000000..b08d6327d1
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Client.java
@@ -0,0 +1,35 @@
+/*
+ * 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.hugegraph.rpc;
+
+public interface RpcServiceConfig4Client {
+
+    <T> T serviceProxy(String interfaceId);
+
+    <T> T serviceProxy(String graph, String interfaceId);
+
+    default <T> T serviceProxy(Class<T> clazz) {
+        return this.serviceProxy(clazz.getName());
+    }
+
+    default <T> T serviceProxy(String graph, Class<T> clazz) {
+        return this.serviceProxy(graph, clazz.getName());
+    }
+
+    void removeAllServiceProxy();
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java
new file mode 100644
index 0000000000..cd0290900e
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/rpc/RpcServiceConfig4Server.java
@@ -0,0 +1,29 @@
+/*
+ * 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.hugegraph.rpc;
+
+public interface RpcServiceConfig4Server {
+
+    <T, S extends T> String addService(Class<T> clazz, S serviceImpl);
+
+    <T, S extends T> String addService(String graph, Class<T> clazz, S serviceImpl);
+
+    void removeService(String serviceId);
+
+    void removeAllService();
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java
new file mode 100644
index 0000000000..a2dd3d72c1
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.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.hugegraph.version;
+
+import org.apache.hugegraph.util.VersionUtil.Version;
+
+public class RpcVersion {
+
+    public static final String NAME = "hugegraph-rpc";
+
+    // The second parameter of Version.of() is for all-in-one JAR
+    public static final Version VERSION = Version.of(RpcVersion.class, "1.5.0");
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/BaseUnitTest.java b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/BaseUnitTest.java
new file mode 100644
index 0000000000..919ba151f0
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/BaseUnitTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.hugegraph.unit;
+
+import java.net.URL;
+
+import org.junit.BeforeClass;
+
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.config.OptionSpace;
+import org.apache.hugegraph.rpc.RpcServer;
+
+public class BaseUnitTest {
+
+    @BeforeClass
+    public static void initEnv() {
+        OptionSpace.register("rpc", "org.apache.hugegraph.config.RpcOptions");
+    }
+
+    protected static HugeConfig config(boolean server) {
+        return config(server ? "server" : "client");
+    }
+
+    protected static HugeConfig config(String type) {
+        String name = String.format("rpc-%s.properties", type);
+        URL conf = BaseUnitTest.class.getClassLoader().getResource(name);
+        return new HugeConfig(conf.getPath());
+    }
+
+    protected static void startServer(RpcServer rpcServer) {
+        rpcServer.config().configs().values().forEach(c -> {
+            c.setRepeatedExportLimit(100);
+        });
+
+        rpcServer.exportAll();
+    }
+
+    protected static void stopServer(RpcServer rpcServer) {
+        rpcServer.destroy();
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/ExceptionTest.java b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/ExceptionTest.java
new file mode 100644
index 0000000000..ae5f2edc43
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/ExceptionTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.hugegraph.unit;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.rpc.RpcException;
+import org.apache.hugegraph.testutil.Assert;
+
+public class ExceptionTest {
+
+    @Test
+    public void testExceptionWithMessage() {
+        RpcException e = new RpcException("test");
+        Assert.assertEquals("test", e.getMessage());
+        Assert.assertNull(e.getCause());
+    }
+
+    @Test
+    public void testExceptionWithMessageAndCause() {
+        Exception cause = new Exception();
+        RpcException e = new RpcException("test", cause);
+        Assert.assertEquals("test", e.getMessage());
+        Assert.assertEquals(cause, e.getCause());
+    }
+
+    @Test
+    public void testExceptionWithMessageAndArgs() {
+        RpcException e = new RpcException("test %s", 168);
+        Assert.assertEquals("test 168", e.getMessage());
+        Assert.assertNull(e.getCause());
+    }
+
+    @Test
+    public void testExceptionWithMessageAndArgsAndCause() {
+        Exception cause = new Exception();
+        RpcException e = new RpcException("test %s", cause, 168);
+        Assert.assertEquals("test 168", e.getMessage());
+        Assert.assertEquals(cause, e.getCause());
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/ServerClientTest.java b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/ServerClientTest.java
new file mode 100644
index 0000000000..6b800c02c2
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/ServerClientTest.java
@@ -0,0 +1,778 @@
+/*
+ * 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.hugegraph.unit;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.alipay.sofa.rpc.common.RpcOptions;
+import com.alipay.sofa.rpc.core.exception.SofaRpcException;
+import com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException;
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.rpc.RpcClientProvider;
+import org.apache.hugegraph.rpc.RpcCommonConfig;
+import org.apache.hugegraph.rpc.RpcConsumerConfig;
+import org.apache.hugegraph.rpc.RpcProviderConfig;
+import org.apache.hugegraph.rpc.RpcServer;
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.testutil.Whitebox;
+import org.apache.hugegraph.util.E;
+import com.google.common.collect.ImmutableMap;
+
+public class ServerClientTest extends BaseUnitTest {
+
+    private static RpcServer rpcServer;
+    private static RpcClientProvider rpcClient;
+
+    @BeforeClass
+    public static void init() {
+        rpcServer = new RpcServer(config(true));
+        rpcClient = new RpcClientProvider(config(false));
+    }
+
+    @AfterClass
+    public static void clear() {
+        if (rpcClient != null) {
+            rpcClient.destroy();
+        }
+        if (rpcServer != null) {
+            rpcServer.destroy();
+        }
+    }
+
+    @After
+    public void teardown() {
+        if (rpcClient != null) {
+            rpcClient.unreferAll();
+        }
+        if (rpcServer != null) {
+            rpcServer.unexportAll();
+        }
+    }
+
+    @Test
+    public void testSimpleService() {
+        // Init server
+        RpcProviderConfig serverConfig = rpcServer.config();
+        serverConfig.addService(HelloService.class, new HelloServiceImpl());
+        startServer(rpcServer);
+
+        // Init client
+        RpcConsumerConfig clientConfig = rpcClient.config();
+        HelloService client = clientConfig.serviceProxy(HelloService.class);
+
+        // Test call
+        Assert.assertEquals("hello tom!", client.hello("tom"));
+        Assert.assertEquals("tom", client.echo("tom"));
+        Assert.assertEquals(5.14, client.sum(2, 3.14), 0.00000001d);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            client.hello("");
+        }, e -> {
+            Assert.assertContains("empty hello parameter", e.getMessage());
+        });
+    }
+
+    @Test
+    public void testMultiService() {
+        // Init server
+        GraphHelloServiceImpl g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl g2 = new GraphHelloServiceImpl("g2");
+        GraphHelloServiceImpl g3 = new GraphHelloServiceImpl("g3");
+
+        RpcProviderConfig serverConfig = rpcServer.config();
+        serverConfig.addService(g1.graph(), HelloService.class, g1);
+        serverConfig.addService(g2.graph(), HelloService.class, g2);
+        serverConfig.addService(g3.graph(), HelloService.class, g3);
+        startServer(rpcServer);
+
+        // Init client
+        RpcConsumerConfig clientConfig = rpcClient.config();
+        HelloService c1 = clientConfig.serviceProxy("g1", HelloService.class);
+        HelloService c2 = clientConfig.serviceProxy("g2", HelloService.class);
+        HelloService c3 = clientConfig.serviceProxy("g3", HelloService.class);
+
+        // Test call
+        Assert.assertEquals("g1: hello tom!", c1.hello("tom"));
+        Assert.assertEquals("g1: tom", c1.echo("tom"));
+        Assert.assertEquals(5.14, c1.sum(2, 3.14), 0.00000001d);
+
+        Assert.assertEquals("g2: hello tom!", c2.hello("tom"));
+        Assert.assertEquals("g2: tom", c2.echo("tom"));
+        Assert.assertEquals(6.14, c2.sum(3, 3.14), 0.00000001d);
+
+        Assert.assertEquals("g3: hello tom!", c3.hello("tom"));
+        Assert.assertEquals("g3: tom", c3.echo("tom"));
+        Assert.assertEquals(103.14, c3.sum(100, 3.14), 0.00000001d);
+
+        Assert.assertEquals(5.14, g1.result(), 0.00000001d);
+        Assert.assertEquals(6.14, g2.result(), 0.00000001d);
+        Assert.assertEquals(103.14, g3.result(), 0.00000001d);
+    }
+
+    @Test
+    public void testStartServerWithRandomPort() {
+        // Init server
+        RpcServer rpcServerRandom = new RpcServer(config("server-random"));
+        RpcProviderConfig serverConfig = rpcServerRandom.config();
+        serverConfig.addService(HelloService.class, new HelloServiceImpl());
+        startServer(rpcServerRandom);
+
+        Assert.assertNotEquals(0, rpcServerRandom.port());
+        Assert.assertNotEquals(8090, rpcServerRandom.port());
+
+        // Init client
+        HugeConfig config = config(false);
+        String url = rpcServerRandom.host() + ":" + rpcServerRandom.port();
+        String remoteUrlKey = org.apache.hugegraph.config.RpcOptions.RPC_REMOTE_URL.name();
+        config.setProperty(remoteUrlKey, url);
+        RpcClientProvider rpcClientRandom = new RpcClientProvider(config);
+
+        RpcConsumerConfig clientConfig = rpcClientRandom.config();
+        HelloService client = clientConfig.serviceProxy(HelloService.class);
+
+        // Test call
+        Assert.assertEquals("hello tom!", client.hello("tom"));
+        Assert.assertEquals("tom", client.echo("tom"));
+        Assert.assertEquals(5.14, client.sum(2, 3.14), 0.00000001d);
+
+        // Destroy all
+        rpcClientRandom.destroy();
+        stopServer(rpcServerRandom);
+    }
+
+    @Test
+    public void testStartServerWithAdaptivePort() throws IOException {
+        // Init server
+        RpcServer rpcServerAdaptive = new RpcServer(config("server-adaptive"));
+        RpcProviderConfig serverConfig = rpcServerAdaptive.config();
+        serverConfig.addService(HelloService.class, new HelloServiceImpl());
+
+        // Start other server bound the port
+        int usedPort = rpcServerAdaptive.port();
+        InetAddress ip = InetAddress.getByName(rpcServerAdaptive.host());
+        ServerSocket inUse = new ServerSocket(usedPort,50, ip);
+
+        // Start server after the port in use
+        startServer(rpcServerAdaptive);
+
+        Assert.assertNotEquals(0, rpcServerAdaptive.port());
+        Assert.assertNotEquals(usedPort, rpcServerAdaptive.port());
+
+        // Init client
+        HugeConfig config = config(false);
+        String url = rpcServerAdaptive.host() + ":" + rpcServerAdaptive.port();
+        String remoteUrlKey = org.apache.hugegraph.config.RpcOptions.RPC_REMOTE_URL.name();
+        config.setProperty(remoteUrlKey, url);
+        RpcClientProvider rpcClientAdaptive = new RpcClientProvider(config);
+
+        RpcConsumerConfig clientConfig = rpcClientAdaptive.config();
+        HelloService client = clientConfig.serviceProxy(HelloService.class);
+
+        // Test call
+        Assert.assertEquals("hello tom!", client.hello("tom"));
+        Assert.assertEquals("tom", client.echo("tom"));
+        Assert.assertEquals(5.14, client.sum(2, 3.14), 0.00000001d);
+
+        // Destroy all
+        rpcClientAdaptive.destroy();
+        stopServer(rpcServerAdaptive);
+
+        inUse.close();
+    }
+
+    @Test
+    public void testStartBothServerAndClientThroughSameConfig() {
+        // Init server1
+        HugeConfig server1 = config("server1-client");
+        RpcServer rpcServer1 = new RpcServer(server1);
+        RpcClientProvider rpcClient1 = new RpcClientProvider(server1);
+
+        GraphHelloServiceImpl s1g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s1g2 = new GraphHelloServiceImpl("g2");
+
+        rpcServer1.config().addService(s1g1.graph(), HelloService.class, s1g1);
+        rpcServer1.config().addService(s1g2.graph(), HelloService.class, s1g2);
+
+        startServer(rpcServer1);
+
+        // Init server2
+        HugeConfig server2 = config("server2-client");
+        RpcServer rpcServer2 = new RpcServer(server2);
+        RpcClientProvider rpcClient2 = new RpcClientProvider(server2);
+
+        GraphHelloServiceImpl s2g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s2g2 = new GraphHelloServiceImpl("g2");
+
+        rpcServer2.config().addService(s2g1.graph(), HelloService.class, s2g1);
+        rpcServer2.config().addService(s2g2.graph(), HelloService.class, s2g2);
+
+        startServer(rpcServer2);
+
+        // Init client1
+        HelloService s2g1Client = rpcClient1.config().serviceProxy(
+                                  "g1", HelloService.class);
+        HelloService s2g2Client = rpcClient1.config().serviceProxy(
+                                  "g2", HelloService.class);
+
+        // Init client2
+        HelloService s1g1Client = rpcClient2.config().serviceProxy(
+                                  "g1", HelloService.class);
+        HelloService s1g2Client = rpcClient2.config().serviceProxy(
+                                  "g2", HelloService.class);
+
+        // Test call
+        Assert.assertEquals(2.1, s2g1Client.sum(1, 1.1), 0.00000001d);
+        Assert.assertEquals(2.2, s2g2Client.sum(1, 1.2), 0.00000001d);
+
+        Assert.assertEquals(1.1, s1g1Client.sum(1, 0.1), 0.00000001d);
+        Assert.assertEquals(1.2, s1g2Client.sum(0, 1.2), 0.00000001d);
+
+        Assert.assertEquals(1.1, s1g1.result(), 0.00000001d);
+        Assert.assertEquals(1.2, s1g2.result(), 0.00000001d);
+        Assert.assertEquals(2.1, s2g1.result(), 0.00000001d);
+        Assert.assertEquals(2.2, s2g2.result(), 0.00000001d);
+
+        // Destroy all
+        rpcClient1.destroy();
+        rpcClient2.destroy();
+        stopServer(rpcServer1);
+        stopServer(rpcServer2);
+    }
+
+    @Test
+    public void testFanoutCallService() {
+        // Init 3 servers
+        HugeConfig server3 = config("server3");
+        RpcServer rpcServer3 = new RpcServer(server3);
+
+        HugeConfig server4 = config("server4");
+        RpcServer rpcServer4 = new RpcServer(server4);
+
+        HugeConfig server5 = config("server5");
+        RpcServer rpcServer5 = new RpcServer(server5);
+
+        GraphHelloServiceImpl s3g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s4g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s5g1 = new GraphHelloServiceImpl("g1");
+
+        rpcServer3.config().addService(s3g1.graph(), HelloService.class, s3g1);
+        rpcServer4.config().addService(s4g1.graph(), HelloService.class, s4g1);
+        rpcServer5.config().addService(s5g1.graph(), HelloService.class, s5g1);
+
+        startServer(rpcServer3);
+        startServer(rpcServer4);
+        startServer(rpcServer5);
+
+        // Init client
+        HugeConfig client345 = config("client345");
+        RpcClientProvider rpcClient345 = new RpcClientProvider(client345);
+
+        HelloService g1 = rpcClient345.config()
+                                      .serviceProxy("g1", HelloService.class);
+
+        // Test fanout
+        Assert.assertEquals("g1: fanout", g1.echo("fanout"));
+        Assert.assertEquals(16.8, g1.sum(10, 6.8), 0.00000001d);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            g1.hello("");
+        }, e -> {
+            Assert.assertContains("empty hello parameter", e.getMessage());
+        });
+
+        Assert.assertEquals(16.8, s3g1.result(), 0.00000001d);
+        Assert.assertEquals(16.8, s4g1.result(), 0.00000001d);
+        Assert.assertEquals(16.8, s5g1.result(), 0.00000001d);
+
+        // Destroy all
+        rpcClient345.destroy();
+
+        stopServer(rpcServer3);
+        stopServer(rpcServer4);
+        stopServer(rpcServer5);
+    }
+
+    @Test
+    public void testFanoutCallServiceWithError() {
+        // Init 3 servers
+        HugeConfig server3 = config("server3");
+        RpcServer rpcServer3 = new RpcServer(server3);
+
+        HugeConfig server4 = config("server4");
+        RpcServer rpcServer4 = new RpcServer(server4);
+
+        HugeConfig server5 = config("server5");
+        RpcServer rpcServer5 = new RpcServer(server5);
+
+        GraphHelloServiceImpl s3g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s4g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s5g1 = new GraphHelloServiceImpl("g1");
+
+        rpcServer3.config().addService(s3g1.graph(), HelloService.class, s3g1);
+        rpcServer4.config().addService(s4g1.graph(), HelloService.class, s4g1);
+        rpcServer5.config().addService(s5g1.graph(), HelloService.class, s5g1);
+
+        startServer(rpcServer3);
+        startServer(rpcServer4);
+        startServer(rpcServer5);
+
+        // Init client with one server unavailable
+        HugeConfig client346 = config("client346");
+        RpcClientProvider rpcClient346 = new RpcClientProvider(client346);
+
+        HelloService g1 = rpcClient346.config()
+                                      .serviceProxy("g1", HelloService.class);
+
+        // Test fanout with one failed
+        Assert.assertEquals("g1: fanout", g1.echo("fanout"));
+        Assert.assertEquals(16.8, g1.sum(10, 6.8), 0.00000001d);
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            g1.hello("");
+        }, e -> {
+            Assert.assertContains("empty hello parameter", e.getMessage());
+        });
+
+        Assert.assertEquals(16.8, s3g1.result(), 0.00000001d);
+        Assert.assertEquals(16.8, s4g1.result(), 0.00000001d);
+        Assert.assertEquals(0.0, s5g1.result(), 0.00000001d);
+
+        s3g1.resetResult();
+        s4g1.resetResult();
+        s5g1.resetResult();
+
+        // Init client with all servers unavailable
+        HugeConfig client67 = config("client67");
+        RpcClientProvider rpcClient67 = new RpcClientProvider(client67);
+
+        HelloService g67 = rpcClient67.config()
+                                      .serviceProxy("g1", HelloService.class);
+
+        // Test fanout with all failed
+        Assert.assertThrows(SofaRpcException.class, () -> {
+            g67.echo("fanout");
+        }, e -> {
+            Assert.assertContains("Failed to call", e.getMessage());
+            Assert.assertContains("echo() on remote server", e.getMessage());
+        });
+
+        Assert.assertEquals(0.0, s3g1.result(), 0.00000001d);
+        Assert.assertEquals(0.0, s4g1.result(), 0.00000001d);
+        Assert.assertEquals(0.0, s5g1.result(), 0.00000001d);
+
+        // Init client with none service provider
+        RpcClientProvider rpcClient0 = new RpcClientProvider(client67);
+        Whitebox.setInternalState(rpcClient0, "consumerConfig.remoteUrls",
+                                  "");
+        HelloService g0 = rpcClient0.config()
+                                    .serviceProxy("g1", HelloService.class);
+
+        Assert.assertThrows(SofaRpcException.class, () -> {
+            g0.echo("fanout");
+        }, e -> {
+            Assert.assertContains("No service provider for", e.getMessage());
+        });
+
+        // Destroy all
+        rpcClient346.destroy();
+        rpcClient67.destroy();
+
+        stopServer(rpcServer3);
+        stopServer(rpcServer4);
+        stopServer(rpcServer5);
+    }
+
+    @Test
+    public void testLoadBalancer() {
+        // Init 3 servers
+        HugeConfig server3 = config("server3");
+        RpcServer rpcServer3 = new RpcServer(server3);
+
+        HugeConfig server4 = config("server4");
+        RpcServer rpcServer4 = new RpcServer(server4);
+
+        HugeConfig server5 = config("server5");
+        RpcServer rpcServer5 = new RpcServer(server5);
+
+        GraphHelloServiceImpl s3g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s4g1 = new GraphHelloServiceImpl("g1");
+        GraphHelloServiceImpl s5g1 = new GraphHelloServiceImpl("g1");
+
+        rpcServer3.config().addService(HelloService.class, s3g1);
+        rpcServer4.config().addService(HelloService.class, s4g1);
+        rpcServer5.config().addService(HelloService.class, s5g1);
+
+        startServer(rpcServer3);
+        startServer(rpcServer4);
+        startServer(rpcServer5);
+
+        // Test LB "consistentHash"
+        HugeConfig clientLB = config("client-lb");
+        RpcClientProvider rpcClientCHash = new RpcClientProvider(clientLB);
+        HelloService cHash = rpcClientCHash.config()
+                                           .serviceProxy(HelloService.class);
+
+        Assert.assertEquals("g1: load", cHash.echo("load"));
+        Assert.assertEquals(16.8, cHash.sum(10, 6.8), 0.00000001d);
+        Assert.assertEquals(16.8, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        Assert.assertEquals("g1: load", cHash.echo("load"));
+        Assert.assertEquals(16.8, cHash.sum(10, 6.8), 0.00000001d);
+        Assert.assertEquals(16.8, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        Assert.assertEquals("g1: load", cHash.echo("load"));
+        Assert.assertEquals(16.8, cHash.sum(10, 6.8), 0.00000001d);
+        Assert.assertEquals(16.8, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        s3g1.resetResult();
+        s4g1.resetResult();
+        s5g1.resetResult();
+
+        // Test LB "roundRobin"
+        String lbKey = org.apache.hugegraph.config.RpcOptions.RPC_CLIENT_LOAD_BALANCER.name();
+        clientLB.setProperty(lbKey, "roundRobin");
+        RpcClientProvider rpcClientRound = new RpcClientProvider(clientLB);
+        HelloService round = rpcClientRound.config()
+                                           .serviceProxy(HelloService.class);
+
+        Assert.assertEquals("g1: load", round.echo("load"));
+        Assert.assertEquals(1.1, round.sum(1, 0.1), 0.00000001d);
+        Assert.assertEquals(1.1, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        Assert.assertEquals("g1: load", round.echo("load"));
+        Assert.assertEquals(1.1, round.sum(1, 0.1), 0.00000001d);
+        Assert.assertEquals(2.2, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        Assert.assertEquals("g1: load", round.echo("load"));
+        Assert.assertEquals(1.1, round.sum(1, 0.1), 0.00000001d);
+        Assert.assertEquals(3.3, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        s3g1.resetResult();
+        s4g1.resetResult();
+        s5g1.resetResult();
+
+        // Test LB "random"
+        clientLB.setProperty(lbKey, "random");
+        RpcClientProvider rpcClientRandom = new RpcClientProvider(clientLB);
+        HelloService random = rpcClientRandom.config()
+                                             .serviceProxy(HelloService.class);
+
+        Assert.assertEquals("g1: load", random.echo("load"));
+        Assert.assertEquals(1.1, random.sum(1, 0.1), 0.00000001d);
+        Assert.assertEquals(1.1, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        Assert.assertEquals("g1: load", random.echo("load"));
+        Assert.assertEquals(1.1, random.sum(1, 0.1), 0.00000001d);
+        double sum = s3g1.result() + s4g1.result() + s5g1.result();
+        Assert.assertTrue(2.2 == sum || 1.1 == sum);
+
+        Assert.assertEquals("g1: load", random.echo("load"));
+        Assert.assertEquals(1.1, random.sum(1, 0.1), 0.00000001d);
+        double sum2 = s3g1.result() + s4g1.result() + s5g1.result();
+        Assert.assertTrue(sum == sum2 || sum + 1.1 == sum2);
+
+        for (int i = 0; i < 9; i++) {
+            Assert.assertEquals(1.1, random.sum(1, 0.1), 0.00000001d);
+        }
+        Assert.assertEquals(3.3, s3g1.result() + s4g1.result() + s5g1.result(),
+                            0.00000001d);
+
+        s3g1.resetResult();
+        s4g1.resetResult();
+        s5g1.resetResult();
+
+        // Destroy all
+        rpcClientCHash.destroy();
+        rpcClientRound.destroy();
+        rpcClientRandom.destroy();
+
+        stopServer(rpcServer3);
+        stopServer(rpcServer4);
+        stopServer(rpcServer5);
+    }
+
+    @Test
+    public void testServiceProxy() {
+        // Init server
+        RpcProviderConfig serverConfig = rpcServer.config();
+        serverConfig.addService(HelloService.class, new HelloServiceImpl());
+        serverConfig.addService("graph", HelloService.class,
+                                new GraphHelloServiceImpl("graph"));
+        startServer(rpcServer);
+
+        // Init client
+        RpcConsumerConfig clientConfig = rpcClient.config();
+        HelloService client = clientConfig.serviceProxy(HelloService.class);
+        HelloService client2 = clientConfig.serviceProxy(HelloService.class);
+        HelloService clientG = clientConfig.serviceProxy("graph",
+                                                         HelloService.class);
+
+        // Test call
+        Assert.assertNotEquals(client, client2);
+        Assert.assertEquals("hello tom!", client.hello("tom"));
+        Assert.assertEquals("hello tom!", client2.hello("tom"));
+        Assert.assertEquals("graph: hello tom!", clientG.hello("tom"));
+
+        // Test call after unrefer
+        rpcClient.unreferAll();
+
+        Assert.assertThrows(SofaRpcRuntimeException.class, () -> {
+            client.hello("tom");
+        });
+        Assert.assertThrows(SofaRpcRuntimeException.class, () -> {
+            client2.hello("tom");
+        });
+        Assert.assertThrows(SofaRpcRuntimeException.class, () -> {
+            clientG.hello("tom");
+        });
+    }
+
+    @Test
+    public void testAddServiceMultiTimesOfSameService() {
+        RpcServer rpcServerExport = new RpcServer(config(true));
+
+        rpcServerExport.config().addService(HelloService.class,
+                                            new HelloServiceImpl());
+
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            rpcServerExport.config().addService(HelloService.class,
+                                                new HelloServiceImpl());
+        }, e -> {
+            Assert.assertContains("Not allowed to add service already exist",
+                                  e.getMessage());
+        });
+
+        rpcServerExport.exportAll();
+
+        stopServer(rpcServerExport);
+    }
+
+    @Test
+    public void testExportMultiTimesOfSameServer() {
+        RpcServer rpcServerExport = new RpcServer(config(true));
+        rpcServerExport.config().addService(HelloService.class,
+                                            new HelloServiceImpl());
+        rpcServerExport.exportAll();
+        rpcServerExport.exportAll();
+
+        stopServer(rpcServerExport);
+    }
+
+    @Test
+    public void testExportMultiTimesOfSameService() {
+        RpcServer rpcServerExport = new RpcServer(config(true));
+        rpcServerExport.config().addService(HelloService.class,
+                                            new HelloServiceImpl());
+        rpcServerExport.exportAll();
+
+        rpcServerExport.config().addService("graph", HelloService.class,
+                                            new HelloServiceImpl());
+        rpcServerExport.exportAll();
+
+        stopServer(rpcServerExport);
+    }
+
+    @Test
+    public void testExportNoneService() {
+        RpcServer rpcServerNoneService = new RpcServer(config(true));
+
+        // Will be ignored if none service added
+        rpcServerNoneService.exportAll();
+
+        stopServer(rpcServerNoneService);
+    }
+
+    @Test
+    public void testUnexportService() {
+        RpcServer rpcServerUnexport = new RpcServer(config(true));
+
+        RpcProviderConfig serverConfig = rpcServerUnexport.config();
+        String service = serverConfig.addService(HelloService.class,
+                                                 new HelloServiceImpl());
+        rpcServerUnexport.exportAll();
+
+        RpcConsumerConfig clientConfig = rpcClient.config();
+        HelloService client = clientConfig.serviceProxy(HelloService.class);
+
+        Assert.assertEquals("hello tom!", client.hello("tom"));
+
+        rpcServerUnexport.unexport(service);
+
+        Assert.assertThrows(SofaRpcException.class, () -> {
+            client.hello("tom");
+        });
+
+        stopServer(rpcServerUnexport);
+    }
+
+    @Test
+    public void testUnexportAllService() {
+        RpcServer rpcServerUnexport = new RpcServer(config(true));
+
+        RpcProviderConfig serverConfig = rpcServerUnexport.config();
+        serverConfig.addService(HelloService.class, new HelloServiceImpl());
+        serverConfig.addService("graph", HelloService.class,
+                                new GraphHelloServiceImpl("graph"));
+        rpcServerUnexport.exportAll();
+
+        RpcConsumerConfig clientConfig = rpcClient.config();
+        HelloService client = clientConfig.serviceProxy(HelloService.class);
+        HelloService clientG = clientConfig.serviceProxy("graph",
+                                                         HelloService.class);
+
+        Assert.assertEquals("hello tom!", client.hello("tom"));
+        Assert.assertEquals("graph: hello tom!", clientG.hello("tom"));
+
+        rpcServerUnexport.unexportAll();
+
+        Assert.assertThrows(SofaRpcException.class, () -> {
+            client.hello("tom");
+        });
+        Assert.assertThrows(SofaRpcException.class, () -> {
+            clientG.hello("tom");
+        });
+
+        stopServer(rpcServerUnexport);
+    }
+
+    @Test
+    public void testUnexportNotExistService() {
+        Assert.assertThrows(IllegalArgumentException.class, () -> {
+            rpcServer.unexport("fake");
+        }, e -> {
+            Assert.assertContains("The service 'fake' doesn't exist",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testServerDisabled() {
+        HugeConfig clientConf = config(false);
+        RpcServer rpcServerDisabled = new RpcServer(clientConf);
+
+        Assert.assertFalse(rpcServerDisabled.enabled());
+        Assert.assertThrows(IllegalArgumentException.class, rpcServerDisabled::config, e -> {
+            Assert.assertContains("RpcServer is not enabled", e.getMessage());
+        });
+
+        stopServer(rpcServerDisabled);
+    }
+
+    @Test
+    public void testClientDisabled() {
+        HugeConfig serverConf = config(true);
+        RpcClientProvider rpcClientDisabled = new RpcClientProvider(serverConf);
+
+        Assert.assertFalse(rpcClientDisabled.enabled());
+        Assert.assertThrows(IllegalArgumentException.class, rpcClientDisabled::config, e -> {
+            Assert.assertContains("RpcClient is not enabled", e.getMessage());
+        });
+
+        rpcClientDisabled.destroy();
+    }
+
+    @Test
+    public void testInitRpcConfigs() {
+        ImmutableMap<String, Object> fixedOptions = ImmutableMap.of(
+                RpcOptions.PROVIDER_REPEATED_EXPORT_LIMIT, 1);
+        RpcCommonConfig.initRpcConfigs(fixedOptions);
+
+        RpcCommonConfig.initRpcConfigs(RpcOptions.CONSUMER_RETRIES, 2);
+    }
+
+    public interface HelloService {
+
+        String hello(String string);
+
+        String echo(String string);
+
+        double sum(long a, double b);
+    }
+
+    public static class HelloServiceImpl implements HelloService {
+
+        @Override
+        public String hello(String string) {
+            E.checkArgument(!string.isEmpty(), "empty hello parameter");
+            return "hello " + string + "!";
+        }
+
+        @Override
+        public String echo(String string) {
+            return string;
+        }
+
+        @Override
+        public double sum(long a, double b) {
+            return a + b;
+        }
+    }
+
+    public static class GraphHelloServiceImpl implements HelloService {
+
+        private final String graph;
+        private double result;
+
+        public GraphHelloServiceImpl(String graph) {
+            this.graph = graph;
+        }
+
+        public String graph() {
+            return this.graph;
+        }
+
+        public void resetResult() {
+            this.result = 0.0;
+        }
+
+        public double result() {
+            return this.result;
+        }
+
+        @Override
+        public String hello(String string) {
+            E.checkArgument(!string.isEmpty(), "empty hello parameter");
+            return this.graph + ": hello " + string + "!";
+        }
+
+        @Override
+        public String echo(String string) {
+            return this.graph + ": " + string;
+        }
+
+        @Override
+        public double sum(long a, double b) {
+            this.result = a + b;
+            return this.result;
+        }
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
new file mode 100644
index 0000000000..a19b5522c8
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
@@ -0,0 +1,30 @@
+/*
+ * 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.hugegraph.unit;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    VersionTest.class,
+    ExceptionTest.class,
+    ServerClientTest.class
+})
+public class UnitTestSuite {
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/VersionTest.java b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/VersionTest.java
new file mode 100644
index 0000000000..56d0bc552c
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/java/org/apache/hugegraph/unit/VersionTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.unit;
+
+import org.junit.Test;
+
+import org.apache.hugegraph.testutil.Assert;
+import org.apache.hugegraph.util.VersionUtil;
+import org.apache.hugegraph.version.RpcVersion;
+
+public class VersionTest {
+
+    @Test
+    public void testGetRpcVersion() {
+        String pomVersion = VersionUtil.getPomVersion();
+        Assert.assertNotNull(pomVersion);
+        String version = RpcVersion.VERSION.get();
+        Assert.assertNotNull(version);
+        Assert.assertEquals(pomVersion, version);
+    }
+}
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/log4j2.xml b/hugegraph-commons/hugegraph-rpc/src/test/resources/log4j2.xml
new file mode 100644
index 0000000000..e84e39584f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/log4j2.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<configuration status="error">
+    <appenders>
+        <Console name="console" target="SYSTEM_OUT">
+            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
+            <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %-5r [%t] [%-5p] %c %x - %m%n"/>
+        </Console>
+
+        <RollingFile name="file" fileName="logs/hugegraph-rpc.log"
+                     filePattern="logs/$${date:yyyy-MM}/hugegraph-rpc-%d{yyyy-MM-dd}-%i.log">
+            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
+            <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %-5r [%t] [%-5p] %c %x - %m%n"/>
+            <SizeBasedTriggeringPolicy size="100MB"/>
+        </RollingFile>
+    </appenders>
+    <loggers>
+        <root level="INFO">
+            <appender-ref ref="console"/>
+            <appender-ref ref="file"/>
+        </root>
+        <logger name="org.apache.hugegraph" level="INFO" additivity="false">
+            <appender-ref ref="console"/>
+            <appender-ref ref="file"/>
+        </logger>
+    </loggers>
+</configuration>
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client-lb.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client-lb.properties
new file mode 100644
index 0000000000..3040bf78cd
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client-lb.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+#rpc.server_host=127.0.0.1
+#rpc.server_port=8090
+#rpc.server_timeout=30
+rpc.remote_url=127.0.0.1:8093,127.0.0.1:8094,127.0.0.1:8095
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client.properties
new file mode 100644
index 0000000000..332a4fb5a5
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+#rpc.server_host=127.0.0.1
+#rpc.server_port=8090
+#rpc.server_timeout=30
+rpc.remote_url=127.0.0.1:8090
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client345.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client345.properties
new file mode 100644
index 0000000000..ef6b36dc27
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client345.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+#rpc.server_host=127.0.0.1
+#rpc.server_port=8090
+#rpc.server_timeout=30
+rpc.remote_url=127.0.0.1:8093,127.0.0.1:8094,127.0.0.1:8095
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client346.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client346.properties
new file mode 100644
index 0000000000..6c651bcabb
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client346.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+#rpc.server_host=127.0.0.1
+#rpc.server_port=8090
+#rpc.server_timeout=30
+rpc.remote_url=127.0.0.1:8093,127.0.0.1:8094,127.0.0.1:8096
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client67.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client67.properties
new file mode 100644
index 0000000000..7c266da60d
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-client67.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+#rpc.server_host=127.0.0.1
+#rpc.server_port=8090
+#rpc.server_timeout=30
+rpc.remote_url=127.0.0.1:8096,127.0.0.1:8097
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server-adaptive.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server-adaptive.properties
new file mode 100644
index 0000000000..043f99cda7
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server-adaptive.properties
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=8098
+rpc.server_adaptive_port=true
+#rpc.server_timeout=30
+#rpc.remote_url=127.0.0.1:8090
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server-random.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server-random.properties
new file mode 100644
index 0000000000..6fd695764b
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server-random.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=0
+#rpc.server_timeout=30
+#rpc.remote_url=127.0.0.1:8090
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server.properties
new file mode 100644
index 0000000000..baaf638b4c
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=8090
+#rpc.server_timeout=30
+#rpc.remote_url=127.0.0.1:8090
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server1-client.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server1-client.properties
new file mode 100644
index 0000000000..d40a797f6f
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server1-client.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=8091
+#rpc.server_timeout=30
+rpc.remote_url=127.0.0.1:8092
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server2-client.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server2-client.properties
new file mode 100644
index 0000000000..b368a0a403
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server2-client.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=8092
+#rpc.server_timeout=30
+rpc.remote_url=127.0.0.1:8091
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server3.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server3.properties
new file mode 100644
index 0000000000..56c5719f21
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server3.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=8093
+#rpc.server_timeout=30
+#rpc.remote_url=127.0.0.1:8090
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server4.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server4.properties
new file mode 100644
index 0000000000..1cb7e582d5
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server4.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=8094
+#rpc.server_timeout=30
+#rpc.remote_url=127.0.0.1:8090
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server5.properties b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server5.properties
new file mode 100644
index 0000000000..ec7b647172
--- /dev/null
+++ b/hugegraph-commons/hugegraph-rpc/src/test/resources/rpc-server5.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+rpc.server_host=127.0.0.1
+rpc.server_port=8095
+#rpc.server_timeout=30
+#rpc.remote_url=127.0.0.1:8090
+#rpc.client_connect_timeout=20
+#rpc.client_reconnect_period=10
+#rpc.client_read_timeout=40
+#rpc.client_retries=3
+#rpc.client_load_balancer=consistentHash
diff --git a/hugegraph-commons/pom.xml b/hugegraph-commons/pom.xml
new file mode 100644
index 0000000000..be482743c6
--- /dev/null
+++ b/hugegraph-commons/pom.xml
@@ -0,0 +1,353 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hugegraph-commons</artifactId>
+    <version>${revision}</version>
+    <packaging>pom</packaging>
+
+    <name>${project.artifactId}</name>
+    <url>https://github.com/apache/hugegraph-commons</url>
+    <description>
+        hugegraph-commons is a common module for HugeGraph-Common and HugeGraph-Rpc with their
+        peripheral components.
+        It includes rpc frame, locks, configurations, events, iterators, rest and some numeric or
+        collection util classes to simplify the development of HugeGraph and its components.
+    </description>
+
+    <parent>
+        <groupId>org.apache.hugegraph</groupId>
+        <artifactId>hugegraph</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <developers>
+        <developer>
+            <id>Apache Hugegraph(Incubating)</id>
+            <email>dev-subscribe@hugegraph.apache.org</email>
+            <url>https://hugegraph.apache.org/</url>
+        </developer>
+    </developers>
+
+    <mailingLists>
+        <mailingList>
+            <name>Developer List</name>
+            <subscribe>dev-subscribe@hugegraph.apache.org</subscribe>
+            <unsubscribe>dev-unsubscribe@hugegraph.apache.org</unsubscribe>
+            <post>dev@hugegraph.incubator.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>Commits List</name>
+            <subscribe>commits-subscribe@hugegraph.apache.org</subscribe>
+            <unsubscribe>commits-unsubscribe@hugegraph.apache.org</unsubscribe>
+            <post>commits@hugegraph.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>Issues List</name>
+            <subscribe>issues-subscribe@hugegraph.apache.org</subscribe>
+            <unsubscribe>issues-unsubscribe@hugegraph.apache.org</unsubscribe>
+            <post>issues@hugegraph.apache.org</post>
+        </mailingList>
+    </mailingLists>
+
+    <issueManagement>
+        <system>Github Issues</system>
+        <url>https://github.com/apache/hugegraph-commons/issues</url>
+    </issueManagement>
+
+    <scm>
+        <url>https://github.com/apache/hugegraph-commons</url>
+        <connection>scm:git:https://github.com/apache/hugegraph-commons.git</connection>
+        <developerConnection>scm:git:https://github.com/apache/hugegraph-commons.git</developerConnection>
+    </scm>
+
+    <properties>
+        <!-- Note: We need also update the version in CommonVersion.java & RpcVersion.java now -->
+        <revision>1.5.0</revision>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <top.level.dir>${project.basedir}/..</top.level.dir>
+        <compiler.source>1.8</compiler.source>
+        <compiler.target>1.8</compiler.target>
+        <log4j2.version>2.18.0</log4j2.version>
+        <commons.configuration.version>1.10</commons.configuration.version>
+        <commons.configuration2.version>2.8.0</commons.configuration2.version>
+        <commons.beanutils.version>1.9.4</commons.beanutils.version>
+        <commons.collections.version>3.2.2</commons.collections.version>
+        <commons.lang3.version>3.12.0</commons.lang3.version>
+        <commons.io.version>2.7</commons.io.version>
+        <commons.codec.version>1.13</commons.codec.version>
+        <guava.version>30.0-jre</guava.version>
+        <javax.json.version>1.0</javax.json.version>
+        <jsr305.version>3.0.1</jsr305.version>
+        <javassist.version>3.28.0-GA</javassist.version>
+        <jersey.version>3.0.3</jersey.version>
+        <jersey.hk2.version>3.0.3</jersey.hk2.version>
+        <jackson.version>2.14.0-rc1</jackson.version>
+        <junit.version>4.13.1</junit.version>
+        <mockito.version>4.1.0</mockito.version>
+        <jakarta.xml.version>4.0.0-RC2</jakarta.xml.version>
+        <sun.xml.version>3.0.2</sun.xml.version>
+        <checkstyle.plugin.version>3.1.2</checkstyle.plugin.version>
+        <checkstyle.version>8.45</checkstyle.version>
+        <skipCommonsTests>true</skipCommonsTests>
+    </properties>
+
+    <modules>
+        <module>hugegraph-common</module>
+        <module>hugegraph-rpc</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${compiler.source}</source>
+                    <target>${compiler.target}</target>
+                    <compilerArguments>
+                        <Xmaxerrs>500</Xmaxerrs>
+                    </compilerArguments>
+                    <compilerArgs>
+                        <arg>-Xlint:unchecked</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>${checkstyle.plugin.version}</version>
+                <dependencies>
+                    <dependency>
+                        <groupId>com.puppycrawl.tools</groupId>
+                        <artifactId>checkstyle</artifactId>
+                        <version>${checkstyle.version}</version>
+                    </dependency>
+                </dependencies>
+                <configuration>
+                    <configLocation>style/checkstyle.xml</configLocation>
+                    <encoding>UTF-8</encoding>
+                    <consoleOutput>true</consoleOutput>
+                    <failsOnError>true</failsOnError>
+                    <linkXRef>false</linkXRef>
+                    <includeTestSourceDirectory>false</includeTestSourceDirectory>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>validate</id>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>check</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <index>true</index>
+                        <manifest>
+                            <addDefaultImplementationEntries>false</addDefaultImplementationEntries>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                        </manifest>
+                        <manifestEntries>
+                            <!-- Must be on one line, otherwise the automatic
+                                 upgrade script cannot replace the version number -->
+                            <Implementation-Version>${project.version}</Implementation-Version>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>0.8.7</version>
+                <executions>
+                    <execution>
+                        <id>pre-unit-test</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>post-unit-test</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.build.directory}</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <!-- Apache RAT for license check -->
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>**/*.versionsBackup</exclude>
+                        <exclude>**/*.log</exclude>
+                        <exclude>**/*.txt</exclude>
+                        <exclude>**/*.json</exclude>
+                        <exclude>**/*.conf</exclude>
+                        <exclude>dist/**/*</exclude>
+                        <exclude>docs/**/*</exclude>
+                        <exclude>scripts/dev/reviewers</exclude>
+                        <exclude>**/*.md</exclude>
+                        <exclude>**/.flattened-pom.xml</exclude>
+                        <exclude>**/logs/*.log</exclude>
+                        <exclude>**/target/*</exclude>
+                        <exclude>style/*</exclude>
+                        <exclude>ChangeLog</exclude>
+                        <exclude>CONFIG.ini</exclude>
+                        <exclude>GROUPS</exclude>
+                        <exclude>OWNERS</exclude>
+                        <exclude>DISCLAIMER</exclude>
+                        <!-- GitHub -->
+                        <exclude>.github/**/*</exclude>
+                        <!-- Intellij -->
+                        <exclude>**/*.iml</exclude>
+                        <exclude>**/*.iws</exclude>
+                        <exclude>**/*.ipr</exclude>
+                        <exclude>**/META-INF/MANIFEST.MF</exclude>
+                        <!-- Maven -->
+                        <exclude>.repository/**</exclude>
+                    </excludes>
+                    <consoleOutput>true</consoleOutput>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>flatten-maven-plugin</artifactId>
+                <version>1.3.0</version>
+                <configuration>
+                    <updatePomFile>true</updatePomFile>
+                    <flattenMode>resolveCiFriendliesOnly</flattenMode>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>flatten</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>flatten</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>flatten.clean</id>
+                        <phase>clean</phase>
+                        <goals>
+                            <goal>clean</goal>
+                        </goals>
+                    </execution>
+                    <!-- auto delete .flattened-pom.xml after "install" step, it will influence deploy step -->
+                    <!--execution>
+                        <id>remove-flattened-pom</id>
+                        <phase>install</phase>
+                        <goals>
+                            <goal>clean</goal>
+                        </goals>
+                    </execution-->
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.20</version>
+                <configuration>
+                    <skipTests>${skipCommonsTests}</skipTests>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>apache-release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-source-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-sources</id>
+                                <goals>
+                                    <goal>jar-no-fork</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-javadocs</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <doclint>none</doclint>
+                            <failOnError>false</failOnError>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>sign-artifacts</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <!-- Prevent `gpg` from using pinentry programs -->
+                            <gpgArguments>
+                                <arg>--pinentry-mode</arg>
+                                <arg>loopback</arg>
+                            </gpgArguments>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/hugegraph-pd/Dockerfile b/hugegraph-pd/Dockerfile
index e507900ade..6ab5817f24 100644
--- a/hugegraph-pd/Dockerfile
+++ b/hugegraph-pd/Dockerfile
@@ -23,7 +23,7 @@ COPY . /pkg
 WORKDIR /pkg
 ARG MAVEN_ARGS
 
-RUN mvn package $MAVEN_ARGS -e -B -ntp -DskipTests -Dmaven.javadoc.skip=true && pwd && ls -l && rm \
+RUN mvn package $MAVEN_ARGS -e -B -ntp -Dmaven.test.skip=true -Dmaven.javadoc.skip=true && pwd && ls -l && rm \
     ./hugegraph-server/*.tar.gz && rm ./hugegraph-pd/*.tar.gz && rm ./hugegraph-store/*.tar.gz
 
 # 2nd stage: runtime env
diff --git a/hugegraph-server/Dockerfile b/hugegraph-server/Dockerfile
index 0e39704fd6..6e68149f0a 100644
--- a/hugegraph-server/Dockerfile
+++ b/hugegraph-server/Dockerfile
@@ -23,14 +23,14 @@ COPY . /pkg
 WORKDIR /pkg
 ARG MAVEN_ARGS
 
-RUN mvn package $MAVEN_ARGS -e -B -ntp -DskipTests -Dmaven.javadoc.skip=true && pwd && ls -l && rm \
+RUN mvn package $MAVEN_ARGS -e -B -ntp -Dmaven.test.skip=true -Dmaven.javadoc.skip=true && pwd && ls -l && rm \
     ./hugegraph-server/*.tar.gz && rm ./hugegraph-pd/*.tar.gz && rm ./hugegraph-store/*.tar.gz
 
 # 2nd stage: runtime env
 # Note: ZGC (The Z Garbage Collector) is only supported on ARM-Mac with java > 13 
 FROM openjdk:11-slim
 
-COPY --from=build /pkg/hugegraph-server/apache-hugegraph-incubating-server-*/ /hugegraph-server/
+COPY --from=build /pkg/hugegraph-server/apache-hugegraph-server-incubating-*/ /hugegraph-server/
 LABEL maintainer="HugeGraph Docker Maintainers <dev@hugegraph.apache.org>"
 
 # TODO: use g1gc or zgc as default
diff --git a/hugegraph-server/Dockerfile-hstore b/hugegraph-server/Dockerfile-hstore
new file mode 100644
index 0000000000..47f758b0d5
--- /dev/null
+++ b/hugegraph-server/Dockerfile-hstore
@@ -0,0 +1,73 @@
+#
+# 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.
+#
+
+# Dockerfile for HugeGraph Server
+# 1st stage: build source code
+FROM maven:3.9.0-eclipse-temurin-11 AS build
+
+COPY . /pkg
+WORKDIR /pkg
+ARG MAVEN_ARGS
+
+RUN mvn package $MAVEN_ARGS -e -B -ntp -DskipTests -Dmaven.javadoc.skip=true && pwd && ls -l && rm \
+    ./hugegraph-server/*.tar.gz && rm ./hugegraph-pd/*.tar.gz && rm ./hugegraph-store/*.tar.gz
+
+# 2nd stage: runtime env
+# Note: ZGC (The Z Garbage Collector) is only supported on ARM-Mac with java > 13 
+FROM openjdk:11-slim
+
+COPY --from=build /pkg/hugegraph-server/apache-hugegraph-server-incubating-*/ /hugegraph-server/
+# remove hugegraph.properties and rename hstore.properties.template for default hstore backend
+RUN cd /hugegraph-server/conf/graphs \
+    && rm hugegraph.properties && mv hstore.properties.template hugegraph.properties
+
+LABEL maintainer="HugeGraph Docker Maintainers <dev@hugegraph.apache.org>"
+
+# TODO: use g1gc or zgc as default
+ENV JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseContainerSupport -XX:MaxRAMPercentage=50 -XshowSettings:vm" \
+    HUGEGRAPH_HOME="hugegraph-server"
+
+#COPY . /hugegraph/hugegraph-server
+WORKDIR /hugegraph-server/
+
+# 1. Install environment and init HugeGraph Sever
+RUN set -x \
+    && apt-get -q update \
+    && apt-get -q install -y --no-install-recommends --no-install-suggests \
+       dumb-init \
+       procps \
+       curl \
+       lsof \
+       vim \
+       cron \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/* \
+    && service cron start \
+    && pwd && cd /hugegraph-server/ \
+    && sed -i "s/^restserver.url.*$/restserver.url=http:\/\/0.0.0.0:8080/g" ./conf/rest-server.properties
+
+# 2. Init docker script
+COPY hugegraph-server/hugegraph-dist/docker/scripts/remote-connect.groovy ./scripts
+COPY hugegraph-server/hugegraph-dist/docker/scripts/detect-storage.groovy ./scripts
+COPY hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh .
+RUN chmod 755 ./docker-entrypoint.sh
+
+EXPOSE 8080
+VOLUME /hugegraph-server
+
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+CMD ["./docker-entrypoint.sh"]
diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/GraphSpaceFilter.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/GraphSpaceFilter.java
new file mode 100644
index 0000000000..97e0cec935
--- /dev/null
+++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/GraphSpaceFilter.java
@@ -0,0 +1,126 @@
+/*
+ * 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.hugegraph.api.filter;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import org.apache.hugegraph.config.HugeConfig;
+import org.apache.hugegraph.config.ServerOptions;
+import org.apache.hugegraph.util.Log;
+import org.slf4j.Logger;
+
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.PreMatching;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.ext.Provider;
+
+/**
+ * TODO: Change the adaptor logic to keep compatibility with the non-"GraphSpace" version after we
+ * support "GraphSpace"
+ */
+@Provider
+@Singleton
+@PreMatching
+public class GraphSpaceFilter implements ContainerRequestFilter {
+
+    private static final Logger LOG = Log.logger(GraphSpaceFilter.class);
+
+    private static final String GRAPHSPACES_PATH = "graphspaces/";
+
+    @Context
+    private jakarta.inject.Provider<HugeConfig> configProvider;
+
+    /**
+     * Filters incoming HTTP requests to modify the request URI if it matches certain criteria.
+     * <p>
+     * This filter checks if the request URI starts with the {@link #GRAPHSPACES_PATH} path
+     * segment. If it does,
+     * the filter removes the {@link #GRAPHSPACES_PATH} segment along with the following segment
+     * and then reconstructs
+     * the remaining URI. The modified URI is set back into the request context. This is useful for
+     * supporting legacy paths or adapting to new API structures.
+     * </p>
+     *
+     * <p><b>Example:</b></p>
+     * <pre>
+     * URI baseUri = URI.create("http://localhost:8080/");
+     * URI requestUri = URI.create("http://localhost:8080/graphspaces/DEFAULT/graphs");
+     *
+     * // Before filter:
+     * context.getUriInfo().getRequestUri();  // returns http://localhost:8080/graphspaces/DEFAULT/graphs
+     *
+     * // After filter:
+     * context.getUriInfo().getRequestUri();  // returns http://localhost:8080/graphs
+     * </pre>
+     *
+     * @param context The {@link ContainerRequestContext} which provides access to the request
+     *                details.
+     * @throws IOException If an input or output exception occurs.
+     */
+    @Override
+    public void filter(ContainerRequestContext context) throws IOException {
+        HugeConfig config = configProvider.get();
+        if (!config.get(ServerOptions.REST_SERVER_ENABLE_GRAPHSPACES_FILTER)) {
+            return;
+        }
+
+        // Step 1: Get relativePath
+        URI baseUri = context.getUriInfo().getBaseUri();
+        URI requestUri = context.getUriInfo().getRequestUri();
+        URI relativePath = baseUri.relativize(requestUri);
+
+        String relativePathStr = relativePath.getPath();
+        // TODO: remember remove the logic after we support "GraphSpace"
+        if (!relativePathStr.startsWith(GRAPHSPACES_PATH)) {
+            return;
+        }
+
+        // Step 2: Extract the next substring after {@link #GRAPHSPACES_PATH}
+        String[] parts = relativePathStr.split("/");
+        if (parts.length <= 1) {
+            return;
+        }
+
+        String ignoredPart = Arrays.stream(parts)
+                                   .limit(2) // Ignore the first two segments
+                                   .collect(Collectors.joining("/"));
+
+        // Reconstruct the remaining path
+        String newPath = Arrays.stream(parts)
+                               .skip(2) // Skip the first two segments
+                               .collect(Collectors.joining("/"));
+
+        // Step 3: Modify RequestUri and log the ignored part
+        URI newUri = UriBuilder.fromUri(baseUri)
+                               .path(newPath)
+                               .replaceQuery(requestUri.getRawQuery())
+                               .build();
+        context.setRequestUri(newUri);
+
+        // Log the ignored part
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Ignored graphspaces segment: {}", ignoredPart);
+        }
+    }
+}
diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java
index 63da169c99..084e9a338f 100644
--- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java
+++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java
@@ -47,6 +47,14 @@ public static synchronized ServerOptions instance() {
                     "http://127.0.0.1:8080"
             );
 
+    public static final ConfigOption<Boolean> REST_SERVER_ENABLE_GRAPHSPACES_FILTER =
+            new ConfigOption<>(
+                    "restserver.enable_graphspaces_filter",
+                    "Whether to enable graphspaces url filter.",
+                    disallowEmpty(),
+                    false
+            );
+
     public static final ConfigOption<String> SERVER_ID =
             new ConfigOption<>(
                     "server.id",
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hstore.properties.template b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hstore.properties.template
new file mode 100644
index 0000000000..3e90c5f4b7
--- /dev/null
+++ b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hstore.properties.template
@@ -0,0 +1,90 @@
+# gremlin entrance to create graph
+# auth config: org.apache.hugegraph.auth.HugeFactoryAuthProxy
+gremlin.graph=org.apache.hugegraph.HugeFactory
+
+# cache config
+#schema.cache_capacity=100000
+# vertex-cache default is 1000w, 10min expired
+vertex.cache_type=l2
+#vertex.cache_capacity=10000000
+#vertex.cache_expire=600
+# edge-cache default is 100w, 10min expired
+edge.cache_type=l2
+#edge.cache_capacity=1000000
+#edge.cache_expire=600
+
+
+# schema illegal name template
+#schema.illegal_name_regex=\s+|~.*
+
+#vertex.default_label=vertex
+
+backend=hstore
+serializer=binary
+
+store=hugegraph
+
+# pd config
+pd.peers=127.0.0.1:8686
+
+# task config
+task.scheduler_type=local
+task.schedule_period=10
+task.retry=0
+task.wait_timeout=10
+
+# search config
+search.text_analyzer=jieba
+search.text_analyzer_mode=INDEX
+
+# rocksdb backend config
+#rocksdb.data_path=/path/to/disk
+#rocksdb.wal_path=/path/to/disk
+
+
+# cassandra backend config
+cassandra.host=localhost
+cassandra.port=9042
+cassandra.username=
+cassandra.password=
+#cassandra.connect_timeout=5
+#cassandra.read_timeout=20
+#cassandra.keyspace.strategy=SimpleStrategy
+#cassandra.keyspace.replication=3
+
+# hbase backend config
+#hbase.hosts=localhost
+#hbase.port=2181
+#hbase.znode_parent=/hbase
+#hbase.threads_max=64
+# IMPORTANT: recommend to modify the HBase partition number
+#            by the actual/env data amount & RS amount before init store
+#            It will influence the load speed a lot
+#hbase.enable_partition=true
+#hbase.vertex_partitions=10
+#hbase.edge_partitions=30
+
+# mysql backend config
+#jdbc.driver=com.mysql.jdbc.Driver
+#jdbc.url=jdbc:mysql://127.0.0.1:3306
+#jdbc.username=root
+#jdbc.password=
+#jdbc.reconnect_max_times=3
+#jdbc.reconnect_interval=3
+#jdbc.ssl_mode=false
+
+# postgresql & cockroachdb backend config
+#jdbc.driver=org.postgresql.Driver
+#jdbc.url=jdbc:postgresql://localhost:5432/
+#jdbc.username=postgres
+#jdbc.password=
+#jdbc.postgresql.connect_database=template1
+
+# palo backend config
+#palo.host=127.0.0.1
+#palo.poll_interval=10
+#palo.temp_dir=./palo-data
+#palo.file_limit_size=32
+
+# WARNING: These raft configurations are deprecated, please use the latest version instead.
+# raft.mode=false
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties
index 1a3532914b..52c81bef1d 100644
--- a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties
+++ b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/graphs/hugegraph.properties
@@ -19,13 +19,13 @@ edge.cache_type=l2
 
 #vertex.default_label=vertex
 
-backend=hstore
+backend=rocksdb
 serializer=binary
 
 store=hugegraph
 
 # pd config
-pd.peers=127.0.0.1:8686
+#pd.peers=127.0.0.1:8686
 
 # task config
 task.scheduler_type=local
@@ -33,28 +33,6 @@ task.schedule_period=10
 task.retry=0
 task.wait_timeout=10
 
-# raft config
-raft.mode=false
-raft.path=./raft-log
-raft.safe_read=true
-raft.use_replicator_pipeline=true
-raft.election_timeout=10000
-raft.snapshot_interval=3600
-raft.backend_threads=48
-raft.read_index_threads=8
-raft.snapshot_threads=4
-raft.snapshot_parallel_compress=false
-raft.snapshot_compress_threads=4
-raft.snapshot_decompress_threads=4
-raft.read_strategy=ReadOnlyLeaseBased
-raft.queue_size=16384
-raft.queue_publish_timeout=60
-raft.apply_batch=1
-raft.rpc_threads=80
-raft.rpc_connect_timeout=5000
-raft.rpc_timeout=60
-raft.install_snapshot_rpc_timeout=36000
-
 # search config
 search.text_analyzer=jieba
 search.text_analyzer_mode=INDEX
@@ -107,3 +85,6 @@ cassandra.password=
 #palo.poll_interval=10
 #palo.temp_dir=./palo-data
 #palo.file_limit_size=32
+
+# WARNING: These raft configurations are deprecated, please use the latest version instead.
+# raft.mode=false
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/rest-server.properties b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/rest-server.properties
index 507867380c..f89966e6cd 100644
--- a/hugegraph-server/hugegraph-dist/src/assembly/static/conf/rest-server.properties
+++ b/hugegraph-server/hugegraph-dist/src/assembly/static/conf/rest-server.properties
@@ -1,6 +1,7 @@
 # bind url
 # could use '0.0.0.0' or specified (real)IP to expose external network access
 restserver.url=http://127.0.0.1:8080
+#restserver.enable_graphspaces_filter=false
 # gremlin server url, need to be consistent with host and port in gremlin-server.yaml
 #gremlinserver.url=http://127.0.0.1:8182
 
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/graphs/hugegraph.properties b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/graphs/hugegraph.properties
index 2d315b21e8..6b04fffb75 100644
--- a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/graphs/hugegraph.properties
+++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft1/graphs/hugegraph.properties
@@ -26,6 +26,5 @@ serializer=binary
 rocksdb.data_path=rocksdb-data-raft1
 rocksdb.wal_path=rocksdb-data-raft1
 
-raft.mode=true
-raft.path=rocksdb-raftlog1
-raft.safe_read=true
+# WARNING: These raft configurations are deprecated, please use the latest version instead.
+# raft.mode=false
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/graphs/hugegraph.properties b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/graphs/hugegraph.properties
index 772d387ad6..b04c8a494e 100644
--- a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/graphs/hugegraph.properties
+++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft2/graphs/hugegraph.properties
@@ -26,6 +26,5 @@ serializer=binary
 rocksdb.data_path=rocksdb-data-raft2
 rocksdb.wal_path=rocksdb-data-raft2
 
-raft.mode=true
-raft.path=rocksdb-raftlog2
-raft.safe_read=true
+# WARNING: These raft configurations are deprecated, please use the latest version instead.
+# raft.mode=false
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/graphs/hugegraph.properties b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/graphs/hugegraph.properties
index fc805c3c57..f7dc3f2711 100644
--- a/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/graphs/hugegraph.properties
+++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/conf-raft3/graphs/hugegraph.properties
@@ -26,6 +26,5 @@ serializer=binary
 rocksdb.data_path=rocksdb-data-raft3
 rocksdb.wal_path=rocksdb-data-raft3
 
-raft.mode=true
-raft.path=rocksdb-raftlog3
-raft.safe_read=true
+# WARNING: These raft configurations are deprecated, please use the latest version instead.
+# raft.mode=false
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test-for-raft.sh b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test-for-raft.sh
index 529874f58b..2b998d57aa 100755
--- a/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test-for-raft.sh
+++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test-for-raft.sh
@@ -35,7 +35,7 @@ JACOCO_PORT=36320
 RAFT_TOOLS=$RAFT1_DIR/bin/raft-tools.sh
 RAFT_LEADER="127.0.0.1:8091"
 
-mvn package -DskipTests
+mvn package -Dmaven.test.skip=true
 
 # mkdir for each raft-server
 cp -r $SERVER_DIR $RAFT1_DIR
diff --git a/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test.sh b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test.sh
index 8008f39cdb..2a3c2c35ee 100755
--- a/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test.sh
+++ b/hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test.sh
@@ -29,7 +29,7 @@ REST_SERVER_CONF=$SERVER_DIR/conf/rest-server.properties
 GREMLIN_SERVER_CONF=$SERVER_DIR/conf/gremlin-server.yaml
 JACOCO_PORT=36320
 
-mvn package -DskipTests -ntp
+mvn package -Dmaven.test.skip=true -ntp
 
 # add mysql dependency
 wget -P $SERVER_DIR/lib/ https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.28/mysql-connector-java-8.0.28.jar
@@ -41,6 +41,7 @@ fi
 # config rest-server
 sed -i 's/#auth.authenticator=/auth.authenticator=org.apache.hugegraph.auth.StandardAuthenticator/' $REST_SERVER_CONF
 sed -i 's/#auth.admin_token=/auth.admin_token=pa/' $REST_SERVER_CONF
+sed -i 's/#restserver.enable_graphspaces_filter=false/restserver.enable_graphspaces_filter=true/' $REST_SERVER_CONF
 
 # config hugegraph.properties
 sed -i 's/gremlin.graph=.*/gremlin.graph=org.apache.hugegraph.auth.HugeFactoryAuthProxy/' $CONF
diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java
index 255528932e..e3053a2096 100644
--- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java
+++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java
@@ -21,6 +21,7 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 import org.apache.commons.collections.map.MultiValueMap;
 import org.apache.hugegraph.HugeFactory;
@@ -77,7 +78,13 @@ public static void main(String[] args) throws Exception {
         List<HugeGraph> graphs = new ArrayList<>(graph2ConfigPaths.size());
         try {
             for (Map.Entry<String, String> entry : graph2ConfigPaths.entrySet()) {
-                graphs.add(initGraph(entry.getValue()));
+                String configPath = entry.getValue();
+                HugeConfig config = new HugeConfig(configPath);
+                if (Objects.equals(config.get(CoreOptions.BACKEND), "hstore")) {
+                    // skip initializing hstore backend
+                    continue;
+                }
+                graphs.add(initGraph(configPath));
             }
             StandardAuthenticator.initAdminUserIfNeeded(restConf);
         } finally {
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/ApiTestSuite.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/ApiTestSuite.java
index 11d3e64095..cca27a78c2 100644
--- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/ApiTestSuite.java
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/ApiTestSuite.java
@@ -17,6 +17,7 @@
 
 package org.apache.hugegraph.api;
 
+import org.apache.hugegraph.api.graphspaces.GraphSpaceApiTestSuite;
 import org.apache.hugegraph.api.traversers.TraversersApiTestSuite;
 import org.apache.hugegraph.dist.RegisterUtil;
 import org.junit.BeforeClass;
@@ -40,7 +41,8 @@
         ProjectApiTest.class,
         TraversersApiTestSuite.class,
         CypherApiTest.class,
-        ArthasApiTest.class
+        ArthasApiTest.class,
+        GraphSpaceApiTestSuite.class
 })
 public class ApiTestSuite {
 
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java
index 4b6c0ed7f4..72821ecb1a 100644
--- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/BaseApiTest.java
@@ -55,7 +55,7 @@
 
 public class BaseApiTest {
 
-    private static final String BASE_URL = "http://127.0.0.1:8080";
+    protected static final String BASE_URL = "http://127.0.0.1:8080";
     private static final String GRAPH = "hugegraph";
     private static final String USERNAME = "admin";
     private static final String PASSWORD = "pa";
@@ -71,7 +71,7 @@ public class BaseApiTest {
 
     protected static final String TRAVERSERS_API = URL_PREFIX + "/traversers";
 
-    private static RestClient client;
+    protected static RestClient client;
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
@@ -84,6 +84,7 @@ public static void init() {
     @AfterClass
     public static void clear() throws Exception {
         client.close();
+        client = null;
     }
 
     @After
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceApiTestSuite.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceApiTestSuite.java
new file mode 100644
index 0000000000..d5090058b1
--- /dev/null
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceApiTestSuite.java
@@ -0,0 +1,34 @@
+/*
+ * 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.hugegraph.api.graphspaces;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+        GraphSpacePropertyKeyApiTest.class,
+        GraphSpaceVertexLabelApiTest.class,
+        GraphSpaceEdgeLabelApiTest.class,
+        GraphSpaceIndexLabelApiTest.class,
+        GraphSpaceEdgeApiTest.class,
+        GraphSpaceVertexApiTest.class
+})
+public class GraphSpaceApiTestSuite {
+
+}
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceEdgeApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceEdgeApiTest.java
new file mode 100644
index 0000000000..643888a953
--- /dev/null
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceEdgeApiTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.api.graphspaces;
+
+import java.util.Objects;
+
+import org.apache.hugegraph.api.BaseApiTest;
+import org.apache.hugegraph.api.EdgeApiTest;
+import org.junit.BeforeClass;
+
+public class GraphSpaceEdgeApiTest extends EdgeApiTest {
+
+    @BeforeClass
+    public static void init() {
+        if (Objects.nonNull(client)) {
+            client.close();
+        }
+        client = new RestClient(String.join("/", BASE_URL, "graphspaces", "DEFAULT"));
+        BaseApiTest.clearData();
+    }
+}
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceEdgeLabelApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceEdgeLabelApiTest.java
new file mode 100644
index 0000000000..80e21b1631
--- /dev/null
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceEdgeLabelApiTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.api.graphspaces;
+
+import java.util.Objects;
+
+import org.apache.hugegraph.api.BaseApiTest;
+import org.apache.hugegraph.api.EdgeLabelApiTest;
+import org.junit.BeforeClass;
+
+public class GraphSpaceEdgeLabelApiTest extends EdgeLabelApiTest {
+
+    @BeforeClass
+    public static void init() {
+        if (Objects.nonNull(client)) {
+            client.close();
+        }
+        client = new RestClient(String.join("/", BASE_URL, "graphspaces", "DEFAULT"));
+        BaseApiTest.clearData();
+    }
+}
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceIndexLabelApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceIndexLabelApiTest.java
new file mode 100644
index 0000000000..f5f3e4c4d8
--- /dev/null
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceIndexLabelApiTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.api.graphspaces;
+
+import java.util.Objects;
+
+import org.apache.hugegraph.api.BaseApiTest;
+import org.apache.hugegraph.api.IndexLabelApiTest;
+import org.junit.BeforeClass;
+
+public class GraphSpaceIndexLabelApiTest extends IndexLabelApiTest {
+
+    @BeforeClass
+    public static void init() {
+        if (Objects.nonNull(client)) {
+            client.close();
+        }
+        client = new RestClient(String.join("/", BASE_URL, "graphspaces", "DEFAULT"));
+        BaseApiTest.clearData();
+    }
+}
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpacePropertyKeyApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpacePropertyKeyApiTest.java
new file mode 100644
index 0000000000..6096c10ee2
--- /dev/null
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpacePropertyKeyApiTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.api.graphspaces;
+
+import java.util.Objects;
+
+import org.apache.hugegraph.api.BaseApiTest;
+import org.apache.hugegraph.api.PropertyKeyApiTest;
+import org.junit.BeforeClass;
+
+public class GraphSpacePropertyKeyApiTest extends PropertyKeyApiTest {
+
+    @BeforeClass
+    public static void init() {
+        if (Objects.nonNull(client)) {
+            client.close();
+        }
+        client = new RestClient(String.join("/", BASE_URL, "graphspaces", "DEFAULT"));
+        BaseApiTest.clearData();
+    }
+}
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceVertexApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceVertexApiTest.java
new file mode 100644
index 0000000000..f967540e1d
--- /dev/null
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceVertexApiTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.api.graphspaces;
+
+import java.util.Objects;
+
+import org.apache.hugegraph.api.BaseApiTest;
+import org.apache.hugegraph.api.VertexApiTest;
+import org.junit.BeforeClass;
+
+public class GraphSpaceVertexApiTest extends VertexApiTest {
+
+    @BeforeClass
+    public static void init() {
+        if (Objects.nonNull(client)) {
+            client.close();
+        }
+        client = new RestClient(String.join("/", BASE_URL, "graphspaces", "DEFAULT"));
+        BaseApiTest.clearData();
+    }
+}
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceVertexLabelApiTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceVertexLabelApiTest.java
new file mode 100644
index 0000000000..5b12576a67
--- /dev/null
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/api/graphspaces/GraphSpaceVertexLabelApiTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hugegraph.api.graphspaces;
+
+import java.util.Objects;
+
+import org.apache.hugegraph.api.BaseApiTest;
+import org.apache.hugegraph.api.VertexLabelApiTest;
+import org.junit.BeforeClass;
+
+public class GraphSpaceVertexLabelApiTest extends VertexLabelApiTest {
+
+    @BeforeClass
+    public static void init() {
+        if (Objects.nonNull(client)) {
+            client.close();
+        }
+        client = new RestClient(String.join("/", BASE_URL, "graphspaces", "DEFAULT"));
+        BaseApiTest.clearData();
+    }
+}
diff --git a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java
index 1a6738a8e3..da059ee85c 100644
--- a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java
+++ b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/TaskCoreTest.java
@@ -552,7 +552,7 @@ public void testGremlinJobAndCancel() throws TimeoutException {
 
         HugeTask<Object> task = runGremlinJob("Thread.sleep(1000 * 10);");
 
-        sleepAWhile();
+        sleepAWhile(200 * 6);
         task = scheduler.task(task.id());
         scheduler.cancel(task);
 
diff --git a/hugegraph-store/Dockerfile b/hugegraph-store/Dockerfile
index 042ceef42f..b677da2f6b 100644
--- a/hugegraph-store/Dockerfile
+++ b/hugegraph-store/Dockerfile
@@ -23,7 +23,7 @@ COPY . /pkg
 WORKDIR /pkg
 ARG MAVEN_ARGS
 
-RUN mvn package $MAVEN_ARGS -e -B -ntp -DskipTests -Dmaven.javadoc.skip=true && pwd && ls -l && rm \
+RUN mvn package $MAVEN_ARGS -e -B -ntp -Dmaven.test.skip=true -Dmaven.javadoc.skip=true && pwd && ls -l && rm \
     ./hugegraph-server/*.tar.gz && rm ./hugegraph-pd/*.tar.gz && rm ./hugegraph-store/*.tar.gz
 
 # 2nd stage: runtime env
diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/PartitionEngine.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/PartitionEngine.java
index 11538478cc..ee65162f7c 100644
--- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/PartitionEngine.java
+++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/PartitionEngine.java
@@ -249,6 +249,7 @@ public LogStorage createLogStorage(final String uri, final RaftOptions raftOptio
         raftOptions.setMaxReplicatorInflightMsgs(
                 options.getRaftOptions().getMaxReplicatorInflightMsgs());
         raftOptions.setMaxByteCountPerRpc(1024 * 1024);
+        raftOptions.setMaxBodySize(options.getRaftOptions().getMaxBodySize());
         nodeOptions.setEnableMetrics(true);
 
         final PeerId serverId = JRaftUtils.getPeerId(options.getRaftAddress());
diff --git a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java
index 18d145fb40..c315d3440e 100644
--- a/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java
+++ b/hugegraph-store/hg-store-core/src/main/java/org/apache/hugegraph/store/options/HgStoreEngineOptions.java
@@ -99,6 +99,10 @@ public static class RaftOptions {
          * The maximum number of entries in AppendEntriesRequest
          */
         private int maxEntriesSize = 256;
+        /**
+         * The maximum byte size of AppendEntriesRequest
+         */
+        private int maxBodySize = 512 * 1024;
         /**
          * Raft cluster data backlog occurs, rate limiting wait time in milliseconds.
          **/
diff --git a/hugegraph-store/hg-store-dist/src/assembly/static/bin/start-hugegraph-store.sh b/hugegraph-store/hg-store-dist/src/assembly/static/bin/start-hugegraph-store.sh
index b363b7ab45..d70f2fbd13 100644
--- a/hugegraph-store/hg-store-dist/src/assembly/static/bin/start-hugegraph-store.sh
+++ b/hugegraph-store/hg-store-dist/src/assembly/static/bin/start-hugegraph-store.sh
@@ -74,13 +74,13 @@ export FILE_LIMITN=1024
 
 function check_evn_limit() {
     local limit_check=$(ulimit -n)
-    if [ ${limit_check} -lt ${FILE_LIMITN} ]; then
-        echo -e "${BASH_SOURCE[0]##*/}:${LINENO}:\E[1;32m ulimit -n 可以打开的最大文件描述符数太少,需要(${FILE_LIMITN})!! \E[0m"
+    if [[ ${limit_check} != "unlimited" && ${limit_check} -lt ${FILE_LIMITN} ]]; then
+        echo -e "${BASH_SOURCE[0]##*/}:${LINENO}:\E[1;32m ulimit -n can open too few maximum file descriptors, need (${FILE_LIMITN})!! \E[0m"
         return 1
     fi
     limit_check=$(ulimit -u)
-    if [ ${limit_check} -lt ${PROC_LIMITN} ]; then
-        echo -e "${BASH_SOURCE[0]##*/}:${LINENO}:\E[1;32m ulimit -u  用户最大可用的进程数太少,需要(${PROC_LIMITN})!! \E[0m"
+    if [[ ${limit_check} != "unlimited" && ${limit_check} -lt ${PROC_LIMITN} ]]; then
+        echo -e "${BASH_SOURCE[0]##*/}:${LINENO}:\E[1;32m ulimit -u too few available processes for the user, need (${PROC_LIMITN})!! \E[0m"
         return 2
     fi
     return 0
@@ -148,7 +148,7 @@ if [ "$JAVA_OPTIONS" = "" ]; then
     # JAVA_OPTIONS="-Xms${MIN_MEM}m -Xmx${XMX}m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${LOGS} ${USER_OPTION}"
 
     # Rolling out detailed GC logs
-    JAVA_OPTIONS="${JAVA_OPTIONS} -Xlog:gc=info:file=./logs/gc.log:tags,uptime,level:filecount=3,filesize=100m "
+    JAVA_OPTIONS="${JAVA_OPTIONS} -Xlog:gc=info:file=./logs/gc.log:time,uptime,level,tags:filecount=3,filesize=100m"
 fi
 
 # Using G1GC as the default garbage collector (Recommended for large memory machines)
diff --git a/hugegraph-store/hg-store-dist/src/assembly/static/conf/application-pd.yml b/hugegraph-store/hg-store-dist/src/assembly/static/conf/application-pd.yml
index df535953fc..0315c4b4fe 100644
--- a/hugegraph-store/hg-store-dist/src/assembly/static/conf/application-pd.yml
+++ b/hugegraph-store/hg-store-dist/src/assembly/static/conf/application-pd.yml
@@ -26,9 +26,9 @@ management:
         include: "*"
 
 rocksdb:
-  # rocksdb 使用的总内存大小,达到该值强制写盘
+  # rocksdb total memory usage, force flush to disk when reaching this value
   total_memory_size: 32000000000
-  # rocksdb 使用的 memtable 大小
+  # memtable size used by rocksdb
   write_buffer_size: 32000000
-  # 对于每个 rocksdb 来说,memtable 个数达到该值进行写盘
+  # For each rocksdb, the number of memtables reaches this value for writing to disk.
   min_write_buffer_number_to_merge: 16
diff --git a/hugegraph-store/hg-store-dist/src/assembly/static/conf/application.yml b/hugegraph-store/hg-store-dist/src/assembly/static/conf/application.yml
index 4ca3d34dd6..8e2b8d4f74 100644
--- a/hugegraph-store/hg-store-dist/src/assembly/static/conf/application.yml
+++ b/hugegraph-store/hg-store-dist/src/assembly/static/conf/application.yml
@@ -16,7 +16,7 @@
 #
 
 pdserver:
-  # pd 服务地址,多个 pd 地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 
 management:
@@ -30,24 +30,24 @@ management:
         include: "*"
 
 grpc:
-  # grpc 的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8500
   netty-server:
     max-inbound-message-size: 1000MB
 raft:
-  # raft 缓存队列大小
+  # raft cache queue size
   disruptorBufferSize: 1024
   address: 127.0.0.1:8510
   max-log-file-size: 600000000000
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, in seconds
   snapshotInterval: 1800
 server:
-  # rest 服务地址
+  # rest service address
   port: 8520
 
 app:
-  # 存储路径,支持多个路径,逗号分割
+  # Storage path, support multiple paths, separated by commas
   data-path: ./storage
   #raft-path: ./storage
 
diff --git a/hugegraph-store/hg-store-grpc/pom.xml b/hugegraph-store/hg-store-grpc/pom.xml
index 3e7cc6adda..75f4594a0d 100644
--- a/hugegraph-store/hg-store-grpc/pom.xml
+++ b/hugegraph-store/hg-store-grpc/pom.xml
@@ -91,23 +91,23 @@
                     <pluginArtifact>
                         io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
                     </pluginArtifact>
-                    <!--默认值-->
+                    <!-- Default value -->
                     <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
-                    <!--默认值-->
+                    <!-- Default value -->
                     <!--<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>-->
                     <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
-                    <!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
+                    <!-- Set whether to clear the files in outputDirectory before generating java files, the default value is true, and it will also override files with the same name when set to false -->
                     <clearOutputDirectory>false</clearOutputDirectory>
-                    <!--更多配置信息可以查看https://www.xolstice.org/protobuf-maven-plugin/compile-mojo.html-->
+                    <!-- More configuration information can be found at https://www.xolstice.org/protobuf-maven-plugin/compile-mojo.html -->
                 </configuration>
                 <executions>
                     <execution>
-                        <!--在执行mvn compile的时候会执行以下操作-->
+                        <!-- When executing mvn compile, the following operations will be performed -->
                         <phase>generate-sources</phase>
                         <goals>
-                            <!--生成OuterClass类-->
+                            <!-- Generate OuterClass class -->
                             <goal>compile</goal>
-                            <!--生成Grpc类-->
+                            <!-- Generate Grpc classes -->
                             <goal>compile-custom</goal>
                         </goals>
                     </execution>
diff --git a/hugegraph-store/hg-store-grpc/src/main/proto/graphpb.proto b/hugegraph-store/hg-store-grpc/src/main/proto/graphpb.proto
index a245002f85..6e9d16d2eb 100644
--- a/hugegraph-store/hg-store-grpc/src/main/proto/graphpb.proto
+++ b/hugegraph-store/hg-store-grpc/src/main/proto/graphpb.proto
@@ -30,20 +30,20 @@ message ScanPartitionRequest{
     SCAN_VERTEX = 1;
     SCAN_EDGE = 2;
   }
-  // 请求参数
+  // Request parameters
   message Request{
     ScanType scan_type = 1;
     string graph_name = 2;
     uint32 partition_id = 3;
     uint32 start_code = 4;
     uint32 end_code = 5;
-    // 过滤条件
+    // Filter conditions
     string condition = 6;
     string table = 7;
     int64 limit = 8;
     int32 boundary = 9;
     bytes position = 10;
-    // 返回条件
+    // Return condition
     repeated int64 properties = 11;
   }
 
@@ -54,14 +54,14 @@ message ScanPartitionRequest{
   RequestHeader header = 1;
   oneof request {
     Request scan_request = 2;
-    // 每消费一个数据包,通知服务端一次,返回消息序号
+    // Each time a data packet is consumed, notify the server once, return the message sequence number
     Reply reply_request = 4;
   }
 }
 
 message ScanResponse{
   ResponseHeader header = 1;
-  // 消息序号
+  // Message Sequence Number
   int32     seq_no = 2;
   repeated  Vertex vertex = 3;
   repeated  Edge edge = 4;
@@ -74,19 +74,19 @@ message Property{
 }
 
 message Vertex{
-  int64 label = 1; // 点类型
-  Variant id = 2;  // 点ID
-  repeated Property properties = 3; //点属性
+  int64 label = 1; // Point type
+  Variant id = 2;  // Point ID
+  repeated Property properties = 3; // Point properties
 }
 
 message Edge{
-  int64 label = 1;        // 边类型
+  int64 label = 1;        // Edge type
   int64 sourceLabel = 2;
   int64 targetLabel = 3;
-  Variant source_id = 4;  // 源点ID
-  Variant target_id = 5;  // 目标点ID
+  Variant source_id = 4;  // Source point ID
+  Variant target_id = 5;  // Target point ID
 
-  repeated Property properties = 6; //边属性
+  repeated Property properties = 6; // Edge properties
 }
 
 message Variant {
@@ -116,7 +116,7 @@ enum VariantType {
 
 
 message RequestHeader {
-  // 发送者 ID.
+  // Sender ID.
   uint64 sender_id = 2;
 }
 
diff --git a/hugegraph-store/hg-store-grpc/src/main/proto/store_common.proto b/hugegraph-store/hg-store-grpc/src/main/proto/store_common.proto
index fc9934dec4..bc45670198 100644
--- a/hugegraph-store/hg-store-grpc/src/main/proto/store_common.proto
+++ b/hugegraph-store/hg-store-grpc/src/main/proto/store_common.proto
@@ -82,10 +82,10 @@ enum ScanMethod {
 }
 
 enum ScanOrderType{
-  // 批量接口下,返回顺序的要求
-  ORDER_NONE = 0;             // 允许无序
-  ORDER_WITHIN_VERTEX = 1;    // 一个点内的边不会被打断,单不同点之间为无序
-  ORDER_STRICT = 2;           // 保证原始的输入点顺序
+  // Under batch interface, the requirement for return order
+  ORDER_NONE = 0;             // Allow unordered
+  ORDER_WITHIN_VERTEX = 1;    // Edges within a vertex will not be broken, but the order between different vertices is unordered.
+  ORDER_STRICT = 2;           // Ensure the original input point order
 }
 
 enum OpType {
diff --git a/hugegraph-store/hg-store-grpc/src/main/proto/store_session.proto b/hugegraph-store/hg-store-grpc/src/main/proto/store_session.proto
index b659645a63..e9cb940881 100644
--- a/hugegraph-store/hg-store-grpc/src/main/proto/store_session.proto
+++ b/hugegraph-store/hg-store-grpc/src/main/proto/store_session.proto
@@ -122,11 +122,11 @@ message PartitionLeader {
 
 enum PartitionFaultType{
   PARTITION_FAULT_TYPE_UNKNOWN = 0;
-  // 当前不是Leader,返回Leader所在store
+  // Currently not the Leader, return the store where the Leader is located.
   PARTITION_FAULT_TYPE_NOT_LEADER = 1;
-  // 等待Leader超时,可能raft group创建失败
+  // Wait for Leader timeout, possibly raft group creation failed
   PARTITION_FAULT_TYPE_WAIT_LEADER_TIMEOUT = 2;
-  // 分区不属于本机
+  // Partition does not belong to this machine
   PARTITION_FAULT_TYPE_NOT_LOCAL = 3;
 
 }
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java
index c656912235..674a7fe417 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppConfig.java
@@ -49,14 +49,14 @@ public class AppConfig {
     @Value("${server.port}")
     private int restPort;
 
-    //内置pd模式,用于单机部署
+    // Built-in pd mode, for standalone deployment
     @Value("${app.data-path: store}")
     private String dataPath;
 
     @Value("${app.raft-path:}")
     private String raftPath;
 
-    //内置pd模式,用于单机部署
+    // Built-in pd mode, for standalone deployment
     @Value("${app.fake-pd: false}")
     private boolean fakePd;
     @Autowired
@@ -97,7 +97,7 @@ public void init() {
         if (raft.getDisruptorBufferSize() == 0) {
             int size = (int) (totalMemory / 1000 / 1000 / 1000);
             size = (int) Math.pow(2, Math.round(Math.log(size) / Math.log(2))) * 32;
-            raft.setDisruptorBufferSize(size); // 每32M增加一个buffer
+            raft.setDisruptorBufferSize(size); // Increase one buffer every 32M
         }
 
         if (!rocksdb.containsKey("write_buffer_size") ||
@@ -172,11 +172,11 @@ public class Raft {
         private int snapshotInterval;
         @Value("${raft.disruptorBufferSize:0}")
         private int disruptorBufferSize;
-        @Value("${raft.max-log-file-size: 50000000000}")
+        @Value("${raft.max-log-file-size:50000000000}")
         private long maxLogFileSize;
-        @Value("${ave-logEntry-size-ratio : 0.95}")
+        @Value("${ave-logEntry-size-ratio:0.95}")
         private double aveLogEntrySizeRation;
-        @Value("${raft.useRocksDBSegmentLogStorage: true}")
+        @Value("${raft.useRocksDBSegmentLogStorage:true}")
         private boolean useRocksDBSegmentLogStorage;
         @Value("${raft.maxSegmentFileSize:67108864}")
         private int maxSegmentFileSize;
@@ -184,6 +184,8 @@ public class Raft {
         private int maxReplicatorInflightMsgs;
         @Value("${raft.maxEntriesSize:256}")
         private int maxEntriesSize;
+        @Value("${raft.maxBodySize:524288}")
+        private int maxBodySize;
 
     }
 
@@ -211,7 +213,7 @@ public class FakePdConfig {
         @Value("${fake-pd.store-list:''}")
         private String storeList;
         @Value("${fake-pd.peers-list:''}")
-        private String peersList;   //fakePd模式下,raft集群初始配置
+        private String peersList;   // fakePd mode, raft cluster initial configuration
         @Value("${fake-pd.partition-count:3}")
         private int partitionCount;
         @Value("${fake-pd.shard-count:3}")
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppShutdownHook.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppShutdownHook.java
index 4b02e4e498..b239a327a5 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppShutdownHook.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/AppShutdownHook.java
@@ -43,7 +43,7 @@ public void run() {
         doSomethingForShutdown();
 
         try {
-            mainThread.join(); //当收到停止信号时,等待mainThread的执行完成
+            mainThread.join(); // Wait for mainThread to finish when a stop signal is received.
         } catch (InterruptedException ignored) {
         }
         System.out.println("Shut down complete.");
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/StoreNodeApplication.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/StoreNodeApplication.java
index c74ccc3295..c793ed96f2 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/StoreNodeApplication.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/StoreNodeApplication.java
@@ -39,7 +39,7 @@ public static void main(String[] args) {
     }
 
     public static void start() {
-        // 设置solt用到的日志位置
+        // Set the log location for the slot usage
         String logPath = System.getProperty("logging.path");
         if (StringUtils.isBlank(logPath)) {
             System.setProperty("logging.path", "logs");
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/HgTestController.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/HgTestController.java
index 8c23621b54..157c7dfdaf 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/HgTestController.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/HgTestController.java
@@ -34,7 +34,7 @@
 import lombok.extern.slf4j.Slf4j;
 
 /**
- * 仅用于测试
+ * For testing only
  */
 @RestController
 @Slf4j
@@ -75,7 +75,7 @@ public String deleteRaftNode(@PathVariable(value = "groupId") int groupId) {
             nodeService.getStoreEngine().destroyPartitionEngine(groupId, graphs);
             return "OK";
         } else {
-            return "未找到分区";
+            return "Partition not found";
         }
 
     }
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/PartitionAPI.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/PartitionAPI.java
index 9247f35c75..d55bcbf28a 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/PartitionAPI.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/PartitionAPI.java
@@ -98,7 +98,7 @@ public Map<String, Object> getPartitions(
                 String graphName = partitionEntry.getKey();
                 Partition pt = partitionEntry.getValue();
                 PartitionInfo partition = new PartitionInfo(pt);
-                // 此处为了打开所有的图,metric只返回已打开的图
+                // Here to open all the graphs, metric only returns the opened graph
                 businessHandler.getLatestSequenceNumber(graphName, pt.getId());
                 partition.setMetric(
                         businessHandler.getPartitionMetric(graphName, pt.getId(), accurate));
@@ -142,7 +142,7 @@ public Raft getPartition(@PathVariable(value = "id") int id) {
     }
 
     /**
-     * 打印分区的所有key
+     * Print all keys in the partition
      */
     @GetMapping(value = "/partition/dump/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
     public Map<String, Object> dumpPartition(@PathVariable(value = "id") int id) throws
@@ -171,7 +171,7 @@ public Map<String, Object> dumpPartition(@PathVariable(value = "id") int id) thr
     }
 
     /**
-     * 打印分区的所有key
+     * Print all keys in the partition
      */
     @GetMapping(value = "/partition/clean/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
     public Map<String, Object> cleanPartition(@PathVariable(value = "id") int id) throws
@@ -196,7 +196,7 @@ public Map<String, Object> arthasstart(
         ArthasAgent.attach(configMap);
 //        DashResponse retPose = new DashResponse();
         List<String> ret = new ArrayList<>();
-        ret.add("Arthas 启动成功");
+        ret.add("Arthas started successfully");
         return okMap("arthasstart", ret);
     }
 
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/BatchGrpcClosure.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/BatchGrpcClosure.java
index d4ee59cfaa..14c0926787 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/BatchGrpcClosure.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/BatchGrpcClosure.java
@@ -44,7 +44,7 @@
 import lombok.extern.slf4j.Slf4j;
 
 /**
- * 批量处理的grpc回调封装类
+ * Batch processing grpc callback wrapper class
  *
  * @param <V>
  */
@@ -95,7 +95,7 @@ public void run(Status status) {
     }
 
     /**
-     * 不使用计数器latch
+     * Not using counter latch
      *
      * @return
      */
@@ -158,13 +158,13 @@ public String getErrorMsg() {
     }
 
     /**
-     * 等待raft执行结束,返回结果给grpc
+     * Wait for the raft execution to complete, return the result to grpc
      */
     public void waitFinish(StreamObserver<V> observer, Function<List<V>, V> ok, long timeout) {
         try {
             countDownLatch.await(timeout, TimeUnit.MILLISECONDS);
 
-            if (errorStatus.isEmpty()) {  // 没有错误时,合并结果
+            if (errorStatus.isEmpty()) {  // No error, merge results
                 observer.onNext(ok.apply(results));
             } else {
                 observer.onNext((V) FeedbackRes.newBuilder()
@@ -186,7 +186,7 @@ public void waitFinish(StreamObserver<V> observer, Function<List<V>, V> ok, long
     }
 
     /**
-     * 从多个结果中选择一个错误的结果返回,如果没有错误,返回第一个
+     * Select one incorrect result from multiple results, if there are no errors, return the first one.
      */
     public FeedbackRes selectError(List<FeedbackRes> results) {
         if (!CollectionUtils.isEmpty(results)) {
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/GrpcClosure.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/GrpcClosure.java
index 785739edde..0d65066e99 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/GrpcClosure.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/GrpcClosure.java
@@ -36,7 +36,7 @@ abstract class GrpcClosure<V> implements RaftClosure {
     private V result;
 
     /**
-     * 设置输出结果给raftClosure,对于Follower来说,raftClosure为空
+     * Set the output result to raftClosure, for Follower, raftClosure is empty.
      */
     public static <V> void setResult(RaftClosure raftClosure, V result) {
         GrpcClosure closure = (GrpcClosure) raftClosure;
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java
index 6c88555160..0305bd03c7 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreNodeService.java
@@ -101,6 +101,7 @@ public void init() {
                 setMaxSegmentFileSize(appConfig.getRaft().getMaxSegmentFileSize());
                 setMaxReplicatorInflightMsgs(appConfig.getRaft().getMaxReplicatorInflightMsgs());
                 setMaxEntriesSize(appConfig.getRaft().getMaxEntriesSize());
+                setMaxBodySize(appConfig.getRaft().getMaxBodySize());
             }});
             setFakePdOptions(new FakePdOptions() {{
                 setStoreList(appConfig.getFakePdConfig().getStoreList());
@@ -182,7 +183,7 @@ public boolean invoke(int partId, byte[] request, RaftClosure response) throws
                     invoke(partId, methodId, CleanReq.parseFrom(input), response);
                     break;
                 default:
-                    return false; // 未处理
+                    return false; // Unhandled
             }
         } catch (IOException e) {
             throw new HgStoreException(e.getMessage(), e);
@@ -213,7 +214,7 @@ public boolean invoke(int partId, byte methodId, Object req, RaftClosure respons
                 hgStoreSession.doClean(partId, (CleanReq) req, response);
                 break;
             default:
-                return false; // 未处理
+                return false; // Unhandled
         }
         return true;
     }
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreSessionImpl.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreSessionImpl.java
index b7766ea230..2bc0c27b86 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreSessionImpl.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreSessionImpl.java
@@ -130,12 +130,12 @@ public void clean(CleanReq request,
 
         String graph = request.getHeader().getGraph();
         int partition = request.getPartition();
-        // 发给不同的raft执行
+        // Send to different raft to execute
         BatchGrpcClosure<FeedbackRes> closure = new BatchGrpcClosure<>(1);
         storeService.addRaftTask(HgStoreNodeService.CLEAN_OP, graph, partition,
                                  request,
                                  closure.newRaftClosure());
-        // 等待返回结果
+        // Waiting for the return result
         closure.waitFinish(responseObserver, r -> closure.selectError(r),
                            appConfig.getRaft().getRpcTimeOut());
     }
@@ -228,7 +228,7 @@ public void batch(BatchReq request, StreamObserver<FeedbackRes> observer) {
                         GraphMode graphMode = graphState.getMode();
                         if (graphMode != null &&
                             graphMode.getNumber() == GraphMode.ReadOnly_VALUE) {
-                            // 状态为只读时从pd获取最新的图状态,图只读状态会在pd的通知中更新
+                            // When in read-only state, get the latest graph state from pd, the graph's read-only state will be updated in pd's notification.
                             Metapb.Graph pdGraph =
                                     pd.getPDClient().getGraph(graph);
                             Metapb.GraphState pdGraphState =
@@ -237,13 +237,13 @@ public void batch(BatchReq request, StreamObserver<FeedbackRes> observer) {
                                 pdGraphState.getMode() != null &&
                                 pdGraphState.getMode().getNumber() ==
                                 GraphMode.ReadOnly_VALUE) {
-                                // 确认pd中存储的当前状态也是只读,则不允许插入数据
+                                // Confirm that the current state stored in pd is also read-only, then inserting data is not allowed.
                                 throw new PDException(-1,
                                                       "the graph space size " +
                                                       "has " +
                                                       "reached the threshold");
                             }
-                            // pd状态与本地缓存不一致,本地缓存更新为pd中的状态
+                            // pd status is inconsistent with local cache, update local cache to the status in pd
                             managerGraph.setProtoObj(pdGraph);
                         }
                     }
@@ -262,12 +262,12 @@ public void batch(BatchReq request, StreamObserver<FeedbackRes> observer) {
             return;
         }
 
-        // 按分区拆分数据
+        // Split data by partition
         Map<Integer, List<BatchEntry>> groups = new HashMap<>();
         list.forEach((entry) -> {
             Key startKey = entry.getStartKey();
             if (startKey.getCode() == HgStoreConst.SCAN_ALL_PARTITIONS_ID) {
-                // 所有Leader分区
+                // All Leader partitions
                 List<Integer> ids =
                         storeService.getGraphLeaderPartitionIds(graph);
                 ids.forEach(id -> {
@@ -277,7 +277,7 @@ public void batch(BatchReq request, StreamObserver<FeedbackRes> observer) {
                     groups.get(id).add(entry);
                 });
             } else {
-                // 根据keyCode查询所属分区ID,按分区ID分组
+                // According to keyCode to query the belonging partition ID, group by partition ID
                 Integer partitionId =
                         pd.getPartitionByCode(graph, startKey.getCode())
                           .getId();
@@ -288,7 +288,7 @@ public void batch(BatchReq request, StreamObserver<FeedbackRes> observer) {
             }
         });
 
-        // 发给不同的raft执行
+        // Send to different raft to execute
         BatchGrpcClosure<FeedbackRes> closure =
                 new BatchGrpcClosure<>(groups.size());
         groups.forEach((partition, entries) -> {
@@ -306,7 +306,7 @@ public void batch(BatchReq request, StreamObserver<FeedbackRes> observer) {
 
         if (!graph.isEmpty()) {
             log.debug(" batch: waiting raft...");
-            // 等待返回结果
+            // Wait for the return result
             closure.waitFinish(observer, r -> closure.selectError(r),
                                appConfig.getRaft().getRpcTimeOut());
             log.debug(" batch: ended waiting");
@@ -382,16 +382,16 @@ public void table(TableReq request, StreamObserver<FeedbackRes> observer) {
         }
 
         String graph = request.getHeader().getGraph();
-        // 所有Leader分区
+        // All Leader partitions
         List<Integer> ids = storeService.getGraphLeaderPartitionIds(graph);
-        // 按分区拆分数据
+        // Split data by partition
         Map<Integer, TableReq> groups = new HashMap<>();
-        // 按分区拆分数据
+        // Split data by partition
         ids.forEach(id -> {
             groups.put(id, request);
         });
 
-        // 发给不同的raft执行
+        // Send to different raft for execution
         BatchGrpcClosure<FeedbackRes> closure = new BatchGrpcClosure<>(groups.size());
         groups.forEach((partition, entries) -> {
             storeService.addRaftTask(HgStoreNodeService.TABLE_OP, graph, partition,
@@ -401,7 +401,7 @@ public void table(TableReq request, StreamObserver<FeedbackRes> observer) {
 
         if (!groups.isEmpty()) {
             //   log.info(" table waiting raft...");
-            // 等待返回结果
+            // Wait for the return result
             closure.waitFinish(observer, r -> closure.selectError(r),
                                appConfig.getRaft().getRpcTimeOut());
             //  log.info(" table ended waiting raft");
@@ -470,16 +470,16 @@ public void graph(GraphReq request, StreamObserver<FeedbackRes> observer) {
         }
 
         String graph = request.getHeader().getGraph();
-        // 所有Leader分区
+        // All Leader partitions
         List<Integer> ids = storeService.getGraphLeaderPartitionIds(graph);
-        // 按分区拆分数据
+        // Split data by partition
         Map<Integer, GraphReq> groups = new HashMap<>();
-        // 按分区拆分数据
+        // Split data by partitioning
         ids.forEach(id -> {
             groups.put(id, request);
         });
 
-        // 发给不同的raft执行
+        // Send to different raft for execution
         BatchGrpcClosure<FeedbackRes> closure = new BatchGrpcClosure<>(groups.size());
         groups.forEach((partition, entries) -> {
             storeService.addRaftTask(HgStoreNodeService.GRAPH_OP, graph, partition,
@@ -488,7 +488,7 @@ public void graph(GraphReq request, StreamObserver<FeedbackRes> observer) {
         });
 
         if (!groups.isEmpty()) {
-            // 等待返回结果
+            // Waiting for the return result
             closure.waitFinish(observer, r -> closure.selectError(r),
                                appConfig.getRaft().getRpcTimeOut());
 
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java
index 78355e1785..26e7f2357f 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/HgStoreWrapperEx.java
@@ -113,7 +113,7 @@ public boolean doTable(int partId, TableMethod method, String graph, String tabl
 
     public boolean doGraph(int partId, GraphMethod method, String graph) {
         boolean flag = true;
-        if (method == GRAPH_METHOD_DELETE) {// 交给 raft 执行,此处不处理
+        if (method == GRAPH_METHOD_DELETE) {// Hand over to raft for execution, no processing here
             flag = true;
         } else {
             throw new UnsupportedOperationException("GraphMethod: " + method.name());
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ParallelScanIterator.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ParallelScanIterator.java
index 430d466c0d..1f34b043f6 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ParallelScanIterator.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ParallelScanIterator.java
@@ -43,7 +43,7 @@
 import lombok.extern.slf4j.Slf4j;
 
 /**
- * 支持平行读取的批量查询迭代器
+ * Support parallel read batch query iterator
  */
 @Slf4j
 public class ParallelScanIterator implements ScanIterator {
@@ -86,7 +86,7 @@ private ParallelScanIterator(Supplier<KVPair<QueryCondition, ScanIterator>> iter
                     Math.max(1, Math.min(query.getConditionCount() / 16, maxWorkThreads));
         }
         this.maxInQueue = maxWorkThreads * 2;
-        // 边有序需要更大的队列
+        // Edge sorted requires a larger queue
         queue = new LinkedBlockingQueue<>(maxInQueue * 2);
         createScanner();
     }
@@ -107,7 +107,7 @@ public boolean hasNext() {
         while (current == null && tryTimes < waitDataMaxTryTimes) {
             try {
                 if (queue.size() != 0 || !finished) {
-                    current = queue.poll(100, TimeUnit.MILLISECONDS);  //定期检查client是否被关闭了
+                    current = queue.poll(100, TimeUnit.MILLISECONDS);  // Regularly check if the client has been closed.
                     if (current == null && !finished) {
                         wakeUpScanner();
                     }
@@ -159,7 +159,7 @@ public void close() {
     }
 
     /**
-     * 创建扫描器
+     * Create Scanner
      */
     private void createScanner() {
         synchronized (scanners) {
@@ -173,7 +173,7 @@ private void createScanner() {
     }
 
     /**
-     * 唤醒扫描器
+     * Wake up scanner
      */
     private void wakeUpScanner() {
         synchronized (pauseScanners) {
@@ -187,7 +187,7 @@ private void wakeUpScanner() {
     }
 
     /**
-     * 休眠扫描器
+     * Sleep Scanner
      *
      * @param scanner
      */
@@ -209,10 +209,10 @@ private void quitScanner(KVScanner scanner) {
     }
 
     /**
-     * 添加到队列,返回队列是否已满
+     * Add to queue, return whether the queue is full
      *
      * @param data
-     * @return false: 队列已满
+     * @return false: Queue is full
      */
     private boolean putData(List<KV> data) {
         try {
@@ -238,7 +238,7 @@ private boolean putData(List<KV> data, boolean hasNext) {
                 queueLock.unlock();
             }
         }
-        // 数据未结束,线程继续执行
+        // Data not ended, thread continues to execute
         return hasNext || this.queue.size() < maxInQueue;
     }
 
@@ -305,7 +305,7 @@ class KVScanner {
         private volatile boolean closed = false;
 
         private ScanIterator getIterator() {
-            // 迭代器没有数据,或该点以达到limit,切换新的迭代器
+            // Iterator has no data, or the point has reached the limit, switch to a new iterator.
             if (iterator == null || !iterator.hasNext() || counter >= limit) {
                 if (iterator != null) {
                     iterator.close();
@@ -343,7 +343,7 @@ public void scanKV() {
                     if ((entriesSize >= batchSize || bodySize >= maxBodySize) ||
                         (orderEdge && bodySize >= maxBodySize / 2)) {
                         if (orderEdge) {
-                            //边排序,保证一个点的所有边连续,阻止其他点插入
+                            // Sort the edges, ensure all edges of one point are consecutive, prevent other points from inserting.
                             canNext = putData(dataList, iterator != null && iterator.hasNext());
                         } else {
                             canNext = putData(dataList);
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponse.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponse.java
index 3712fbd7cc..99ce662fe7 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponse.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponse.java
@@ -37,10 +37,10 @@
 import lombok.extern.slf4j.Slf4j;
 
 /**
- * 批量查询处理器,批量查询数据,流式返回数据。
- * 1、服务端流式发送数据给客户端
- * 2、客户端每消费一批次数据,返回批次号给服务端
- * 3、服务端根据批次号决定发送多少数据,保证传送数据的不间断,
+ * Batch query processor, batch query data, stream back data.
+ * 1. Server-side streaming data to the client
+ * 2. The client returns the batch number to the server after consuming each batch of data.
+ * 3. The server decides how much data to send based on the batch number, ensuring the uninterrupted transmission of data,
  */
 @Slf4j
 public class ScanBatchResponse implements StreamObserver<ScanStreamBatchReq> {
@@ -50,24 +50,24 @@ public class ScanBatchResponse implements StreamObserver<ScanStreamBatchReq> {
     static ByteBufferAllocator alloc =
             new ByteBufferAllocator(ParallelScanIterator.maxBodySize * 3 / 2, 1000);
     private final int maxInFlightCount = PropertyUtil.getInt("app.scan.stream.inflight", 16);
-    private final int activeTimeout = PropertyUtil.getInt("app.scan.stream.timeout", 60); //单位秒
+    private final int activeTimeout = PropertyUtil.getInt("app.scan.stream.timeout", 60); // unit: second
     private final StreamObserver<KvStream> sender;
     private final HgStoreWrapperEx wrapper;
     private final ThreadPoolExecutor executor;
     private final Object stateLock = new Object();
     private final Lock iteratorLock = new ReentrantLock();
-    // 当前正在遍历的迭代器
+    // Currently traversing iterator
     private ScanIterator iterator;
-    // 下一次发送的序号
+    // Next send sequence number
     private volatile int seqNo;
-    // Client已消费的序号
+    // Client consumed sequence number
     private volatile int clientSeqNo;
-    // 已经发送的条目数
+    // Number of entries sent
     private volatile long count;
-    // 客户端要求返回的最大条目数
+    // Client requests the maximum number of entries to return
     private volatile long limit;
     private ScanQueryRequest query;
-    // 上次读取数据时间
+    // Last read data time
     private long activeTime;
     private volatile State state;
 
@@ -83,20 +83,20 @@ public ScanBatchResponse(StreamObserver<KvStream> response, HgStoreWrapperEx wra
     }
 
     /**
-     * 接收客户端发送的消息
-     * 服务端另起线程处理消息,不阻塞网络
+     * Receive messages sent by the client
+     * Server starts a new thread to process messages, does not block the network.
      *
      * @param request
      */
     @Override
     public void onNext(ScanStreamBatchReq request) {
         switch (request.getQueryCase()) {
-            case QUERY_REQUEST: // 查询条件
+            case QUERY_REQUEST: // query conditions
                 executor.execute(() -> {
                     startQuery(request.getHeader().getGraph(), request.getQueryRequest());
                 });
                 break;
-            case RECEIPT_REQUEST:   // 消息异步应答
+            case RECEIPT_REQUEST:   // Message asynchronous response
                 this.clientSeqNo = request.getReceiptRequest().getTimes();
                 if (seqNo - clientSeqNo < maxInFlightCount) {
                     synchronized (stateLock) {
@@ -111,7 +111,7 @@ public void onNext(ScanStreamBatchReq request) {
                     }
                 }
                 break;
-            case CANCEL_REQUEST:    // 关闭流
+            case CANCEL_REQUEST: // close stream
                 closeQuery();
                 break;
             default:
@@ -132,7 +132,7 @@ public void onCompleted() {
     }
 
     /**
-     * 生成迭代器
+     * Generate iterator
      *
      * @param request
      */
@@ -152,7 +152,7 @@ private void startQuery(String graphName, ScanQueryRequest request) {
     }
 
     /**
-     * 生成迭代器
+     * Generate iterator
      */
     private void closeQuery() {
         setStateDone();
@@ -178,7 +178,7 @@ private void closeIter() {
     }
 
     /**
-     * 发送数据
+     * Send data
      */
     private void sendEntries() {
         if (state == State.DONE || iterator == null) {
@@ -255,7 +255,7 @@ private State setStateIdle() {
     }
 
     /**
-     * 检查是否活跃,超过一定时间客户端没有请求数据,认为已经不活跃,关闭连接释放资源
+     * Check for activity, if the client does not request data for a certain period of time, it is considered inactive, close the connection to release resources.
      */
     public void checkActiveTimeout() {
         if ((System.currentTimeMillis() - activeTime) > activeTimeout * 1000L) {
@@ -265,7 +265,7 @@ public void checkActiveTimeout() {
     }
 
     /**
-     * 任务状态
+     * Task Status
      */
     private enum State {
         IDLE,
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponseFactory.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponseFactory.java
index 9c6dafc776..43abfd97ce 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponseFactory.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanBatchResponseFactory.java
@@ -54,7 +54,7 @@ public int removeStreamObserver(StreamObserver observer) {
     }
 
     /**
-     * 检查是否Stream是否活跃,超时的Stream及时关闭
+     * Check if the Stream is active, and close the timed-out Stream in a timely manner.
      */
     public void checkStreamActive() {
         streamObservers.forEach(streamObserver -> {
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java
index 0148fa0b25..e2fcff42e5 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/ScanUtil.java
@@ -149,7 +149,7 @@ static ScanIterator getIterator(String graph, ScanQueryRequest request,
     }
 
     /**
-     * 支持并行读取的多迭代器
+     * Support for multi-iterators with parallel reading
      */
     static ScanIterator getParallelIterator(String graph, ScanQueryRequest request,
                                             HgStoreWrapperEx wrapper, ThreadPoolExecutor executor) {
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/GraphStoreImpl.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/GraphStoreImpl.java
index dcfc0549a8..6583e59745 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/GraphStoreImpl.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/GraphStoreImpl.java
@@ -34,7 +34,7 @@
 import lombok.extern.slf4j.Slf4j;
 
 /**
- * graphpb.proto 实现类
+ * graphpb.proto implementation class
  */
 @Slf4j
 @GRpcService
@@ -67,9 +67,9 @@ public ThreadPoolExecutor getExecutor() {
     }
 
     /**
-     * 流式回复消息,每个消息带有seqNo
-     * 客户端每消费一个消息,应答一个seqNo
-     * 服务端根据客户端的seqNo决定发送几个数据包
+     * Streaming reply messages, each message with a seqNo
+     * Client side should respond with a seqNo for each message consumed.
+     * The server decides how many packets to send based on the client's seqNo.
      *
      * @param ro
      * @return
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/ScanResponseObserver.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/ScanResponseObserver.java
index b5b49d0398..dc57dae368 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/ScanResponseObserver.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/grpc/scan/ScanResponseObserver.java
@@ -71,17 +71,17 @@ public class ScanResponseObserver<T> implements
     private volatile Future<?> readTask;
 
     /*
-     * 2022年11月1日
-     * 1.onNext 需要进行异步处理,以防止grpc的调用阻塞
-     * 2.不要读取迭代器或者发送数据不要产生线程等待
-     * 3.在发送前,尽量准备好要发送的数据
+     * November 1, 2022
+     * 1. onNext needs to be processed asynchronously to prevent the grpc call from being blocked.
+     * 2. Do not read iterators or send data do not produce thread waiting.
+     * 3. Before sending, try to prepare the data to be sent as much as possible.
      * */
 
     /*
-     * 2022年11月2日
-     * 1.读取rocksdb迭代器的线程read
-     * 2.进行数据转换并发送到阻塞队列的线程offer
-     * 3.从阻塞队列读取数据,并发送的线程,包括在没有读取到数据的情况下唤醒读取和发送的线程send
+     * November 2, 2022
+     * 1. Read the thread of rocksdb iterator read
+     * 2. Perform data conversion and send to the blocking queue thread offer
+     * 3. Thread for reading data from the blocking queue and sending, including waking up the reading and sending threads when no data is read
      * */
 
     public ScanResponseObserver(StreamObserver<ScanResponse> sender,
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/listener/PdConfigureListener.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/listener/PdConfigureListener.java
index 709e7fdb9d..d818e5627a 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/listener/PdConfigureListener.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/listener/PdConfigureListener.java
@@ -103,7 +103,7 @@ public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
             client.listen(TIMESTAMP_KEY, (Consumer<WatchResponse>) o -> {
                 log.info("receive message to restart :" + o);
                 try {
-                    // 优先更新最新配置文件,以免修改像端口之类的参数导致旧文件被优先加载
+                    // Prioritize updating the latest configuration file to avoid old files being loaded first when modifying parameters like ports.
                     ScanPrefixResponse responseNew = client.scanPrefix(CONFIG_PREFIX);
                     Map<String, String> kvsMapNew = responseNew.getKvsMap();
                     String config = kvsMapNew.get(CONFIG_FIX_PREFIX);
diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/util/HgGrpc.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/util/HgGrpc.java
index fb824c56aa..0bb68895f6 100644
--- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/util/HgGrpc.java
+++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/util/HgGrpc.java
@@ -109,7 +109,7 @@ public static StatusRuntimeException toErr(Status status,
                                                String des,
                                                Throwable t) {
         if (t != null) {
-            // 为给client返回完整异常信息
+            // To return complete exception information to the client
             des = (des == null ? "" : des + ",") +
                   Throwables.getStackTraceAsString(t);
         }
diff --git a/hugegraph-store/hg-store-node/src/main/resources/application-pd.yml b/hugegraph-store/hg-store-node/src/main/resources/application-pd.yml
index dc198c3c89..7985e67da1 100644
--- a/hugegraph-store/hg-store-node/src/main/resources/application-pd.yml
+++ b/hugegraph-store/hg-store-node/src/main/resources/application-pd.yml
@@ -16,7 +16,7 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 
 management:
@@ -33,6 +33,6 @@ logging:
   level:
     root: info
 rocksdb:
-  # rocksdb 使用的总内存大小
+  # total memory size used by rocksdb
   total_memory_size: 32000000000
   write_buffer_size: 32000000
diff --git a/hugegraph-store/hg-store-node/src/main/resources/application.yml b/hugegraph-store/hg-store-node/src/main/resources/application.yml
index 962101aac8..0b65270608 100644
--- a/hugegraph-store/hg-store-node/src/main/resources/application.yml
+++ b/hugegraph-store/hg-store-node/src/main/resources/application.yml
@@ -16,11 +16,11 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8500
   netty-server:
@@ -28,14 +28,14 @@ grpc:
 raft:
   address: 127.0.0.1:8510
   max-log-file-size: 600000000000
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, unit: seconds
   snapshotInterval: 1800
 server:
-  # rest 服务地址
+  # rest service address
   port: 8520
 
 app:
-  # 存储路径,支持多个路径,逗号分割
+  # Storage path, support multiple paths, separated by commas
   data-path: ./storage
 
 spring:
diff --git a/hugegraph-store/hg-store-node/src/test/java/org/apache/hugegraph/store/node/HgStoreNodeServiceTest.java b/hugegraph-store/hg-store-node/src/test/java/org/apache/hugegraph/store/node/HgStoreNodeServiceTest.java
index 0ff80ff2e6..336428f998 100644
--- a/hugegraph-store/hg-store-node/src/test/java/org/apache/hugegraph/store/node/HgStoreNodeServiceTest.java
+++ b/hugegraph-store/hg-store-node/src/test/java/org/apache/hugegraph/store/node/HgStoreNodeServiceTest.java
@@ -27,16 +27,16 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * HgStore单元测试
- * 1、测试raft多副本入库
- * 2、测试快照同步
- * 3、测试副本增减
- * 4、测试单幅本关闭日志入库
+ * HgStore unit testing
+ * 1. Test raft multi-copy storage entry
+ * 2. Test snapshot synchronization
+ * 3, test copy addition and subtraction
+ * 4. Test single frame with log storage turned off
  */
 public class HgStoreNodeServiceTest {
 
     String yml =
-            "rocksdb:\n" + "  # rocksdb 使用的总内存大小\n" + "  total_memory_size: 32000000000\n" +
+            "rocksdb:\n" + "  # Total memory size used by rocksdb\n" + "  total_memory_size: 32000000000\n" +
             "  max_background_jobs: 8\n" + "  max_subcompactions: 4\n" +
             "  target_file_size_multiplier: 4\n" + "  min_write_buffer_number_to_merge: 8\n" +
             "  target_file_size_base: 512000000";
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-pd.yml b/hugegraph-store/hg-store-node/src/test/resources/application-pd.yml
index 58673f5c23..4047e27af5 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-pd.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-pd.yml
@@ -16,7 +16,7 @@
 #
 
 rocksdb:
-  # rocksdb 使用的总内存大小
+  # total memory size used by RocksDB
   total_memory_size: 32000000000
   max_background_jobs: 8
   max_subcompactions: 4
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-server00.yml b/hugegraph-store/hg-store-node/src/test/resources/application-server00.yml
index 49b33b2ea2..c4e2c5ed15 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-server00.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-server00.yml
@@ -16,10 +16,10 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8500
   netty-server:
@@ -28,11 +28,11 @@ raft:
   # enable: false
   address: 127.0.0.1:8510
   data-path: ${app.data-path}/raft
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, unit: seconds
   snapshotInterval: 30
   max-log-file-size: 60000000
 server:
-  # rest 服务地址
+  # rest service address
   port: 8520
 
 app:
@@ -60,14 +60,14 @@ rocksdb:
   snapshot_path: ${app.data-path}/snapshot
   bloom_filter_bits_per_key: 10
   compression_per_level: "[none, zstd, zstd, zstd, zstd, zstd, zstd]"
-#fakePd配置参数
+# fakePd configuration parameters
 fake-pd:
-  # fake-pd模式下,store grpc集群列表
+  # fake-pd mode, store grpc cluster list
   store-list: 127.0.0.1:8500
-  # fake-pd模式下,设置raft集群列表
+  # fake-pd mode, set raft cluster list
   peers-list: 127.0.0.1:8510
-  # 分区数量
+  # Partition Count
   partition-count: 10
-  # 每个分区副本数量
+  # Number of replicas per partition
   shard-count: 3
 
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-server01.yml b/hugegraph-store/hg-store-node/src/test/resources/application-server01.yml
index 72482bc28c..0a9c7972f8 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-server01.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-server01.yml
@@ -16,10 +16,10 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8501
   netty-server:
@@ -28,11 +28,11 @@ raft:
   # enable: false
   address: 127.0.0.1:8511
   useRocksDBSegmentLogStorage: false
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, in seconds
   snapshotInterval: 300
   disruptorBufferSize: 128
 server:
-  # rest 服务地址
+  # rest service address
   port: 8521
 
 app:
@@ -58,13 +58,13 @@ rocksdb:
   write_buffer_size: 2000000
   level0_file_num_compaction_trigger: 2
   bloom_filter_bits_per_key: 10
-#fakePd配置参数
+# fakePd configuration parameters
 fake-pd:
-  # fake-pd模式下,store grpc集群列表
+  # fake-pd mode, store grpc cluster list
   store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
-  # fake-pd模式下,设置raft集群列表
+  # fake-pd mode, set raft cluster list
   peers-list: 127.0.0.1:8511,127.0.0.1:8512,127.0.0.1:8513
-  # 分区数量
+  # Partition Number
   partition-count: 10
-  # 每个分区副本数量
+  # Number of replicas per partition
   shard-count: 3
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-server02.yml b/hugegraph-store/hg-store-node/src/test/resources/application-server02.yml
index b69e0535e3..b419a4f054 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-server02.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-server02.yml
@@ -16,10 +16,10 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8502
   netty-server:
@@ -28,11 +28,11 @@ raft:
   #  enable: false
   address: 127.0.0.1:8512
   useRocksDBSegmentLogStorage: false
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, in seconds
   snapshotInterval: 300
   disruptorBufferSize: 128
 server:
-  # rest 服务地址
+  # rest service address
   port: 8522
 
 app:
@@ -57,13 +57,13 @@ management:
 rocksdb:
   db_max_alive_time: 120
 
-#fakePd配置参数
+# fakePd configuration parameters
 fake-pd:
-  # fake-pd模式下,store grpc集群列表
+  # fake-pd mode, store grpc cluster list
   store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
-  # fake-pd模式下,设置raft集群列表
+  # fake-pd mode, set raft cluster list
   peers-list: 127.0.0.1:8511,127.0.0.1:8512,127.0.0.1:8513
-  # 分区数量
+  # Partition Count
   partition-count: 10
-  # 每个分区副本数量
+  # Number of replicas per partition
   shard-count: 3
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-server03.yml b/hugegraph-store/hg-store-node/src/test/resources/application-server03.yml
index 8028dffd9f..709370c3c8 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-server03.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-server03.yml
@@ -16,10 +16,10 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8503
   netty-server:
@@ -29,11 +29,11 @@ raft:
   address: 127.0.0.1:8513
   snapshotLogIndexMargin: 1024
   useRocksDBSegmentLogStorage: false
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, in seconds
   snapshotInterval: 300
   disruptorBufferSize: 128
 server:
-  # rest 服务地址
+  # rest service address
   port: 8523
 
 app:
@@ -59,13 +59,13 @@ rocksdb:
   db_max_alive_time: 120
 
 
-#fakePd配置参数
+# fakePd configuration parameters
 fake-pd:
-  # fake-pd模式下,store grpc集群列表
+  # fake-pd mode, store grpc cluster list
   store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
-  # fake-pd模式下,设置raft集群列表
+  # fake-pd mode, set raft cluster list
   peers-list: 127.0.0.1:8511,127.0.0.1:8512,127.0.0.1:8513
-  # 分区数量
+  # Partition Count
   partition-count: 10
-  # 每个分区副本数量
+  # Number of replicas per partition
   shard-count: 3
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-server04.yml b/hugegraph-store/hg-store-node/src/test/resources/application-server04.yml
index b9d35f443d..b06a92c8dd 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-server04.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-server04.yml
@@ -16,10 +16,10 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8504
   netty-server:
@@ -28,10 +28,10 @@ raft:
   # enable: false
   address: 127.0.0.1:8514
 
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, unit: seconds
   snapshotInterval: 300
 server:
-  # rest 服务地址
+  # rest service address
   port: 8524
 
 app:
@@ -56,13 +56,13 @@ management:
 rocksdb:
 
 
-#fakePd配置参数
+# fakePd configuration parameters
 fake-pd:
-  # fake-pd模式下,store grpc集群列表
+  # fake-pd mode, store grpc cluster list
   store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
-  # fake-pd模式下,设置raft集群列表
+  # fake-pd mode, set raft cluster list
   peers-list: 127.0.0.1:8511,127.0.0.1:8512,127.0.0.1:8513
-  # 分区数量
+  # Partition Number
   partition-count: 3
-  # 每个分区副本数量
+  # Number of replicas per partition
   shard-count: 3
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-server05.yml b/hugegraph-store/hg-store-node/src/test/resources/application-server05.yml
index 02b83f9a5c..e3637051ce 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-server05.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-server05.yml
@@ -16,10 +16,10 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8505
   netty-server:
@@ -28,10 +28,10 @@ raft:
   # enable: false
   address: 127.0.0.1:8515
   data-path: ${app.data-path}/raft
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, unit: seconds
   snapshotInterval: 300
 server:
-  # rest 服务地址
+  # rest service address
   port: 8525
 
 app:
@@ -58,13 +58,13 @@ rocksdb:
   wal_path: ${app.data-path}/db
   snapshot_path: ${app.data-path}/snapshot
 
-#fakePd配置参数
+# fakePd configuration parameters
 fake-pd:
-  # fake-pd模式下,store grpc集群列表
+  # fake-pd mode, store grpc cluster list
   store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
-  # fake-pd模式下,设置raft集群列表
+  # fake-pd mode, set raft cluster list
   peers-list: 127.0.0.1:8511,127.0.0.1:8512,127.0.0.1:8513
-  # 分区数量
+  # Partition Quantity
   partition-count: 3
-  # 每个分区副本数量
+  # Number of replicas per partition
   shard-count: 3
diff --git a/hugegraph-store/hg-store-node/src/test/resources/application-server06.yml b/hugegraph-store/hg-store-node/src/test/resources/application-server06.yml
index eeef451c1c..8574bc3705 100644
--- a/hugegraph-store/hg-store-node/src/test/resources/application-server06.yml
+++ b/hugegraph-store/hg-store-node/src/test/resources/application-server06.yml
@@ -16,10 +16,10 @@
 #
 
 pdserver:
-  # pd服务地址,多个pd地址用逗号分割
+  # PD service address, multiple PD addresses separated by commas
   address: localhost:8686
 grpc:
-  # grpc的服务地址
+  # grpc service address
   host: 127.0.0.1
   port: 8506
   netty-server:
@@ -28,10 +28,10 @@ raft:
   # enable: false
   address: 127.0.0.1:8516
   data-path: ${app.data-path}/raft
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, in seconds
   snapshotInterval: 300
 server:
-  # rest 服务地址
+  # rest service address
   port: 8526
 
 app:
@@ -58,13 +58,13 @@ rocksdb:
   wal_path: ${app.data-path}/db
   snapshot_path: ${app.data-path}/snapshot
 
-#fakePd配置参数
+# fakePd configuration parameters
 fake-pd:
-  # fake-pd模式下,store grpc集群列表
+  # fake-pd mode, store grpc cluster list
   store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
-  # fake-pd模式下,设置raft集群列表
+  # fake-pd mode, set raft cluster list
   peers-list: 127.0.0.1:8511,127.0.0.1:8512,127.0.0.1:8513
-  # 分区数量
+  # Partition Count
   partition-count: 3
-  # 每个分区副本数量
+  # Number of replicas per partition
   shard-count: 3
diff --git a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBFactory.java b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBFactory.java
index 2ec56fa2bd..ce5dc665a6 100644
--- a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBFactory.java
+++ b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBFactory.java
@@ -87,7 +87,7 @@ private RocksDBFactory() {
                                  watcher.dbSession.getRefCount(),
                                  (System.currentTimeMillis() - watcher.timestamp) / 1000);
                     } else {
-                        // 超时强制删除 (30min)
+                        // Force delete after timeout (30min)
                         watcher.dbSession.forceResetRefCount();
                     }
                 }
@@ -188,7 +188,7 @@ public Map<String, Long> getTotalKey() {
     }
 
     /**
-     * 释放rocksdb对象
+     * Release rocksdb object
      *
      * @param dbName
      * @return
@@ -213,7 +213,7 @@ public boolean releaseGraphDB(String dbName) {
     }
 
     /**
-     * 销毁图,并删除数据文件
+     * Destroy the graph, and delete the data file.
      *
      * @param dbName
      */
@@ -221,7 +221,7 @@ public void destroyGraphDB(String dbName) {
         log.info("destroy {} 's  rocksdb.", dbName);
         RocksDBSession dbSession = dbSessionMap.get(dbName);
         releaseGraphDB(dbName);
-        //增加删除标记
+        // Add delete mark
         if (dbSession != null) {
             destroyGraphDBs.add(new DBSessionWatcher(dbSession));
             rocksdbChangedListeners.forEach(listener -> {
diff --git a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBSession.java b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBSession.java
index d1f89262a3..c3356de248 100644
--- a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBSession.java
+++ b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/RocksDBSession.java
@@ -358,7 +358,7 @@ private String findLatestDBPath(String path, long version) {
                 if (i == dbCount - 1) {
                     latestDBPath = curDBPath;
                 } else {
-                    // delete old db,在删除队列的文件不要删除
+                    // delete old db, do not delete files in the deletion queue
                     if (!factory.findPathInRemovedList(curDBPath)) {
                         try {
                             FileUtils.deleteDirectory(new File(curDBPath));
@@ -373,7 +373,7 @@ private String findLatestDBPath(String path, long version) {
             latestDBPath = Paths.get(parentFile.getPath(), defaultName).toString();
         }
         if (factory.findPathInRemovedList(latestDBPath)) {
-            // 已经被删除,创建新的目录
+            // Has been deleted, create a new directory
             latestDBPath =
                     Paths.get(parentFile.getPath(), String.format("%s_%d", defaultName, version))
                          .toString();
diff --git a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperator.java b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperator.java
index 12c0d3759f..e6de91a53c 100644
--- a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperator.java
+++ b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperator.java
@@ -38,7 +38,7 @@ public interface SessionOperator {
     ScanIterator scan(String tableName, byte[] keyFrom, byte[] keyTo, int scanType);
 
     /**
-     * 扫描所有cf指定范围的数据
+     * Scan all data in the specified cf range
      */
     ScanIterator scanRaw(byte[] keyFrom, byte[] keyTo, long startSeqNum);
 
@@ -62,7 +62,7 @@ public interface SessionOperator {
     void deleteRange(String table, byte[] keyFrom, byte[] keyTo) throws DBStoreException;
 
     /**
-     * 删除所有cf指定范围的数据
+     * Delete all data specified by the cf range
      */
     void deleteRange(byte[] keyFrom, byte[] keyTo) throws DBStoreException;
 
diff --git a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperatorImpl.java b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperatorImpl.java
index f4f8987151..eca6a83a2a 100644
--- a/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperatorImpl.java
+++ b/hugegraph-store/hg-store-rocksdb/src/main/java/org/apache/hugegraph/rocksdb/access/SessionOperatorImpl.java
@@ -219,7 +219,7 @@ public void prepare() {
     }
 
     /**
-     * commit抛出异常后一定要调用rollback,否则会造成cfHandleReadLock未释放
+     * commit throws an exception, you must call rollback, otherwise it will cause cfHandleReadLock not to be released.
      */
     @Override
     public Integer commit() throws DBStoreException {
@@ -302,13 +302,13 @@ public ScanIterator scan(String tableName, byte[] keyFrom, byte[] keyTo, int sca
     }
 
     /**
-     * 遍历所有cf指定范围的数据
-     * TODO: rocksdb7.x 不支持 setStartSeqNum,改为使用 Timestamp
+     * Traverse all data in the specified range of cf
+     * TODO: rocksdb7.x does not support setStartSeqNum, switch to using Timestamp instead.
      * refer: https://github.com/facebook/rocksdb/wiki/User-defined-Timestamp
      */
     @Override
     public ScanIterator scanRaw(byte[] keyFrom, byte[] keyTo, long startSeqNum) {
-        int kNumInternalBytes = 8;      //internal key 增加的8个字节后缀
+        int kNumInternalBytes = 8;      //internal key added 8-byte suffix
         Snapshot snapshot = rocksdb().getSnapshot();
         Iterator<String> cfIterator = session.getTables().keySet().iterator();
 
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java
index b4e19f104d..84584efc0c 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerOneRaftFakePDTest.java
@@ -35,14 +35,14 @@
 import org.junit.Assert;
 
 /**
- * 使用fake-pd,支持raft的单元测试
+ * Using fake-pd, supporting unit tests for raft.
  */
 public class HgSessionManagerOneRaftFakePDTest {
     private static final Map<Integer, Long> leaderMap = new ConcurrentHashMap<>();
     private static final Map<Long, String> storeMap = new ConcurrentHashMap<>();
 
     private static final int partitionCount = 3;
-    // 需要与store的application.yml的fake-pd.partition-count保持一致
+    // Need to be consistent with the store's application.yml fake-pd.partition-count
     private static final String[] storeAddress = {
             "127.0.0.1:8500"
     };
@@ -68,7 +68,7 @@ public static void init() {
                        Arrays.equals(startKey, endKey)) {
                 builder.add(leaderMap.get(startCode % partitionCount), startCode);
             } else {
-                Assert.fail("OwnerKey转成HashCode后已经无序了, 按照OwnerKey范围查询没意义");
+                Assert.fail("OwnerKey converted to HashCode is no longer ordered, querying by OwnerKey range is meaningless");
                 builder.add(leaderMap.get(startCode % partitionCount), startCode);
                 builder.add(leaderMap.get(endCode % partitionCount), endCode);
             }
@@ -174,8 +174,8 @@ public void batchGet() {
     }
 
     // @Test
-    //CAUTION: ONLY FOR LONG!
-    //注意:目前只可以对long类型value进行Merge操作。
+    // CAUTION: ONLY FOR LONG!
+    // Note: Currently, only Merge operations can be performed on long type values.
     public void merge() {
         System.out.println("--- test merge (1+1=2)---");
         HgStoreSession session = getStoreSession();
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftFakePDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftFakePDTest.java
index d014864870..cb3eae8a79 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftFakePDTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftFakePDTest.java
@@ -35,16 +35,16 @@
 import org.junit.Assert;
 
 /**
- * 使用fake-pd,支持raft的单元测试
+ * Use fake-pd, support unit tests for raft RuntimeMethodHandle.op_Implicit(Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageResult)
  */
 public class HgSessionManagerRaftFakePDTest {
     private static final Map<Integer, Long> leaderMap = new ConcurrentHashMap<>();
     private static final Map<Long, String> storeMap = new ConcurrentHashMap<>();
 
     private static final int partitionCount = 3;
-    // 需要与store的application.yml的fake-pd.partition-count保持一致
+    // Need to be consistent with the fake-pd.partition-count in the store's application.yml
     private static final String[] storeAddress =
-            { // 需要与store的application.yml的fake-pd.store-list保持一致
+            { // Need to be consistent with the store's application.yml fake-pd.store-list
               "127.0.0.1:8501", "127.0.0.1:8502", "127.0.0.1:8503"
             };
 
@@ -72,7 +72,7 @@ public static void init() {
                        Arrays.equals(startKey, endKey)) {
                 builder.add(leaderMap.get(startCode % partitionCount), startCode);
             } else {
-                Assert.fail("OwnerKey转成HashCode后已经无序了, 按照OwnerKey范围查询没意义");
+                Assert.fail("OwnerKey converted to HashCode is no longer ordered, querying by OwnerKey range is meaningless");
                 builder.add(leaderMap.get(startCode % partitionCount), startCode);
                 builder.add(leaderMap.get(endCode % partitionCount), endCode);
             }
@@ -216,8 +216,8 @@ public void batchGet() {
     }
 
     // @Test
-    //CAUTION: ONLY FOR LONG!
-    //注意:目前只可以对long类型value进行Merge操作。
+    // CAUTION: ONLY FOR LONG!
+    // Note: Currently, only Merge operations can be performed on long type values.
     public void merge() {
         System.out.println("--- test merge (1+1=2)---");
         HgStoreSession session = getStoreSession();
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftPDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftPDTest.java
index 9820457d78..3b7dc64fd5 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftPDTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerRaftPDTest.java
@@ -52,7 +52,7 @@
 
 
 /**
- * 使用pd,支持raft的单元测试
+ * Use pd, support unit tests for raft
  */
 @Slf4j
 public class HgSessionManagerRaftPDTest {
@@ -262,8 +262,8 @@ public void testBatchPutMultiGraph() throws IOException {
     }
 
     // @Test
-    //CAUTION: ONLY FOR LONG!
-    //注意:目前只可以对long类型value进行Merge操作。
+    // CAUTION: ONLY FOR LONG!
+    // Note: Currently, only long type values can be merged.
     public void merge() {
         System.out.println("--- test merge (1+1=2)---");
         HgStoreSession session = getStoreSession();
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerTest.java
index 9a63ce74ff..1ebaa9462f 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/HgSessionManagerTest.java
@@ -56,7 +56,7 @@ public class HgSessionManagerTest {
                                                                                      "unit-test"));
 
     private static final int partitionCount = 10;
-    // 需要与 store 的 application.yml 的 fake-pd.partition-count 保持一致
+    // Need to be consistent with the store's application.yml fake-pd.partition-count
 
     //private static String[] storeAddress = {"127.0.0.1:8500"};
     private static final String[] storeAddress =
@@ -91,7 +91,7 @@ public static void init() {
                 //log.info("leader-> {}",leaderMap.get(startCode / PARTITION_LENGTH));
                 builder.add(leaderMap.get(startCode / PARTITION_LENGTH), startCode);
             } else {
-                Assert.fail("OwnerKey 转成 HashCode 后已经无序了,按照 OwnerKey 范围查询没意义");
+                Assert.fail("OwnerKey converted to HashCode is already unordered, querying by OwnerKey range is meaningless");
                 builder.add(leaderMap.get(startCode / PARTITION_LENGTH), startCode);
                 builder.add(leaderMap.get(endCode / PARTITION_LENGTH), endCode);
             }
@@ -172,8 +172,8 @@ public void batchPrefix() {
     }
 
     @Test
-    //CAUTION: ONLY FOR LONG!
-    //注意:目前只可以对 long 类型 value 进行 Merge 操作。
+    // CAUTION: ONLY FOR LONG!
+    // Note: Currently, only long type values can be merged.
     public void merge() {
         System.out.println("--- test merge (1+1=2)---");
         HgStoreSession session = getStoreSession();
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/PartitionEngineTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/PartitionEngineTest.java
index 7115aaa65d..1bfe03b543 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/PartitionEngineTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/PartitionEngineTest.java
@@ -78,7 +78,7 @@ public void test() {
                                                                          .contains(peer))
                                           .collect(Collectors.toList());
 
-        // 新增 6、7
+        // Add 6, 7
         Assert.assertEquals(2, addedNodes.size());
         addedNodes.clear();
         addedNodes.addAll(Arrays.asList(peers));
@@ -88,7 +88,7 @@ public void test() {
 
         addedNodes.forEach(s -> System.out.print(s + " "));
         System.out.println();
-        // 删除 4,5
+        // Delete 4, 5
         Assert.assertEquals(2, removedNodes.size());
 
         removedNodes.clear();
@@ -98,7 +98,7 @@ public void test() {
         Assert.assertEquals(2, removedNodes.size());
         removedNodes.forEach(s -> System.out.print(s + " "));
         System.out.println();
-        // 交集 5
+        // Intersection 5
         Assert.assertEquals(1, mixedPeer.size());
         oldPeers1.removeAll(Arrays.asList(learners));
         Assert.assertEquals(1, oldPeers1.size());
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ChangeShardNumTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ChangeShardNumTest.java
index be0c869969..f3c94e6691 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ChangeShardNumTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/ChangeShardNumTest.java
@@ -27,7 +27,7 @@
 import org.junit.Test;
 
 /**
- * 测试修改副本数
+ * Test modify copy number
  */
 public class ChangeShardNumTest extends HgStoreClientBase {
 
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgSessionManagerRaftPDTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgSessionManagerRaftPDTest.java
index e52ae8d2d7..f6b5e7c353 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgSessionManagerRaftPDTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/client/HgSessionManagerRaftPDTest.java
@@ -240,8 +240,8 @@ public void testBatchPutMultiGraph() throws IOException {
     }
 
     //     @Test
-    // CAUTION: ONLY FOR LONG!
-    // 注意:目前只可以对 long 类型 value 进行 Merge 操作。
+    // CAUTION: ONLY FOR LONG!
+    // Note: Currently, only long type values can be merged.
     public void merge() {
         System.out.println("--- test merge (1+1=2)---");
         HgStoreSession session = getStoreSession();
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreSuiteTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreSuiteTest.java
index 9781b06a7b..68530367a0 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreSuiteTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/CoreSuiteTest.java
@@ -39,7 +39,7 @@
 //        ZipUtilsTest.class,
 //        MiscUtilClassTest.class,
 //        PartitionInstructionProcessorTest.class,
-//        // 尽量放到最后
+//        // Try to put it last
 //        HgBusinessImplTest.class
 //})
 
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgCmdClientTest.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgCmdClientTest.java
index d31e01724a..8468f1b504 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgCmdClientTest.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/HgCmdClientTest.java
@@ -93,8 +93,8 @@ public static String getMd5(String txt) {
     }
 
     public static Long getId() {
-        // 如果需要更长 或者更大冗余空间,只需要 time * 10^n   即可
-        // 当前可保证 1 毫秒 生成 10000 条不重复
+        // If needed longer or more redundant space, just use time * 10^n
+        // Currently guaranteed to generate 10000 non-duplicate in 1 millisecond
         Long time = Long.valueOf(new SimpleDateFormat("HHmmssSSS").format(new Date())) * 10000 +
                     (long) (Math.random() * 100);
 //        Long time = Long.valueOf(new SimpleDateFormat("MMddhhmmssSSS").format(new Date())
@@ -144,7 +144,7 @@ public Endpoint getPartitionLeader(String graphName, int partitionId) {
         session.createTable(tableName);
         String createGraph = "create_graph";
         HgOwnerKey hgOwnerKey = toOwnerKey(createGraph);
-        // 需要写数据,才会创建图
+        // Need to write data, then the graph will be created.
         session.put(tableName,
                     hgOwnerKey, createGraph.getBytes(StandardCharsets.UTF_8));
         Assert.assertEquals(createGraph, toStr(session.get(tableName, hgOwnerKey)));
@@ -215,7 +215,7 @@ public Endpoint getPartitionLeader(String graphName, int partitionId) {
         session.createTable(tableName);
         String createGraph = "create_graph";
         HgOwnerKey hgOwnerKey = toOwnerKey(createGraph);
-        // 需要写数据,才会创建图
+        // Need to write data, then the graph will be created.
         session.put(tableName,
                     hgOwnerKey, createGraph.getBytes(StandardCharsets.UTF_8));
         Assert.assertEquals(createGraph, toStr(session.get(tableName, hgOwnerKey)));
@@ -264,7 +264,7 @@ public Endpoint getPartitionLeader(String graphName, int partitionId) {
         session.createTable(tableName);
         String createGraph = "create_graph";
         HgOwnerKey hgOwnerKey = toOwnerKey(createGraph);
-        // 需要写数据,才会创建图
+        // Need to write data, then the graph will be created.
         session.put(tableName,
                     hgOwnerKey, createGraph.getBytes(StandardCharsets.UTF_8));
         Assert.assertEquals(createGraph, toStr(session.get(tableName, hgOwnerKey)));
diff --git a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/StoreEngineTestBase.java b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/StoreEngineTestBase.java
index 267b5a566d..67596dc103 100644
--- a/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/StoreEngineTestBase.java
+++ b/hugegraph-store/hg-store-test/src/main/java/org/apache/hugegraph/store/core/StoreEngineTestBase.java
@@ -38,7 +38,7 @@
 import lombok.extern.slf4j.Slf4j;
 
 /**
- * 使用 FakePd 和 FakePdOptions,初始化 HgStoreEngine,该类的各项 get 函数可用
+ * Use FakePd and FakePdOptions to initialize HgStoreEngine, the get functions of this class are available.
  */
 @Slf4j
 public class StoreEngineTestBase {
@@ -92,7 +92,7 @@ public static Partition getPartition(int partitionId, String graphName) {
     }
 
     /**
-     * 创建 分区为 0 的 partition engine. 该分区 1 个 shard,为 leader, graph name: graph0
+     * Create partition 0's partition engine. The partition has 1 shard, as the leader, graph name: graph0.
      *
      * @return
      */
diff --git a/hugegraph-store/hg-store-test/src/main/resources/pd-server.yml b/hugegraph-store/hg-store-test/src/main/resources/pd-server.yml
index 5608dc9dd4..5782782028 100644
--- a/hugegraph-store/hg-store-test/src/main/resources/pd-server.yml
+++ b/hugegraph-store/hg-store-test/src/main/resources/pd-server.yml
@@ -41,31 +41,31 @@ pd:
 
   patrol-interval: 3000000
   data-path: tmp/8686
-  # 最少节点数,少于该数字,集群停止入库
+  # Minimum number of nodes, less than this number, the cluster stops ingesting data.
   initial-store-count: 1
-  # 初始store列表,在列表内的store自动激活
+  # Initial store list, stores within the list are automatically activated.
   initial-store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
   #initial-store-list: 127.0.0.1:8501
 raft:
   address: 127.0.0.1:8610
-  # raft集群
+  # raft cluster
   peers-list: 127.0.0.1:8610
-  # raft rpc读写超时时间,单位毫秒
+  # raft rpc read-write timeout, unit in milliseconds
   rpc-timeout: 10000
-  # 快照生成时间间隔,单位秒
+  # Snapshot generation interval, unit: seconds
   snapshotInterval: 30000
   metrics: true
 store:
-  # store心跳超时时间,超过该时间,认为store临时不可用,转移Leader到其他副本,单位秒
+  # store heartbeat timeout, if exceeds this time, consider the store temporarily unavailable, transfer Leader to another replica, in seconds
   keepAlive-timeout: 300
-  # store下线时间。超过该时间,认为store永久不可用,分配副本到其他机器,单位秒
+  # store offline time. Beyond this time, it is considered that the store is permanently unavailable, and the replica is allocated to other machines, in seconds.
   max-down-time: 180000
 partition:
-  # 默认每个分区副本数
+  # Default number of replicas per partition
   default-shard-count: 3
-  # 默认每机器最大副本数,初始分区数= store-max-shard-count * store-number / default-shard-count
+  # Default maximum number of replicas per machine, initial number of partitions = store-max-shard-count * store-number / default-shard-count
   store-max-shard-count: 1
 
 discovery:
-  #客户端注册后,无心跳最长次数,超过后,之前的注册信息会被删除
+  # After client registration, no heartbeat longest number, after exceeding, previous registration information will be deleted.
   heartbeat-try-count: 3
diff --git a/install-dist/scripts/dependency/known-dependencies.txt b/install-dist/scripts/dependency/known-dependencies.txt
index 1bbf7241fe..9caa8ecab8 100644
--- a/install-dist/scripts/dependency/known-dependencies.txt
+++ b/install-dist/scripts/dependency/known-dependencies.txt
@@ -1,6 +1,7 @@
 accessors-smart-1.2.jar
 airline-0.8.jar
 android-json-0.0.20131108.vaadin1.jar
+animal-sniffer-annotations-1.18.jar
 animal-sniffer-annotations-1.19.jar
 annotations-13.0.jar
 annotations-4.1.1.4.jar
@@ -25,6 +26,7 @@ assertj-core-3.19.0.jar
 ast-9.0-9.0.20190305.jar
 audience-annotations-0.5.0.jar
 auto-service-annotations-1.0.jar
+bolt-1.6.2.jar
 bolt-1.6.4.jar
 byte-buddy-1.10.20.jar
 byte-buddy-1.10.5.jar
@@ -104,21 +106,28 @@ groovy-jsr223-2.5.14-indy.jar
 groovy-swing-2.5.14.jar
 groovy-templates-2.5.14.jar
 groovy-xml-2.5.14.jar
+grpc-api-1.28.1.jar
 grpc-api-1.39.0.jar
 grpc-api-1.47.0.jar
+grpc-context-1.28.1.jar
 grpc-context-1.39.0.jar
 grpc-context-1.47.0.jar
+grpc-core-1.28.1.jar
 grpc-core-1.39.0.jar
 grpc-core-1.47.0.jar
 grpc-grpclb-1.39.0.jar
 grpc-netty-1.39.0.jar
 grpc-netty-1.47.0.jar
+grpc-netty-shaded-1.28.0.jar
 grpc-netty-shaded-1.39.0.jar
 grpc-netty-shaded-1.47.0.jar
+grpc-protobuf-1.28.0.jar
 grpc-protobuf-1.39.0.jar
+grpc-protobuf-lite-1.28.0.jar
 grpc-protobuf-lite-1.39.0.jar
 grpc-services-1.39.0.jar
 grpc-spring-boot-starter-4.5.5.jar
+grpc-stub-1.28.0.jar
 grpc-stub-1.39.0.jar
 grpc-stub-1.47.0.jar
 gson-2.8.6.jar
@@ -134,6 +143,7 @@ hbase-shaded-endpoint-2.0.6.jar
 HdrHistogram-2.1.12.jar
 HdrHistogram-2.1.9.jar
 hessian-3.3.6.jar
+hessian-3.3.7.jar
 hg-pd-client-1.5.0.jar
 hg-pd-common-1.5.0.jar
 hg-pd-core-1.5.0.jar
@@ -318,9 +328,11 @@ log4j-jul-2.17.2.jar
 log4j-slf4j-impl-2.15.0.jar
 log4j-slf4j-impl-2.17.0.jar
 log4j-slf4j-impl-2.17.1.jar
+log4j-slf4j-impl-2.18.0.jar
 logging-interceptor-4.10.0.jar
 lombok-1.18.20.jar
 lombok-1.18.24.jar
+lombok-1.18.8.jar
 lookout-api-1.4.1.jar
 lucene-analyzers-common-8.11.2.jar
 lucene-analyzers-smartcn-8.11.2.jar
@@ -388,6 +400,7 @@ osgi-resource-locator-1.0.3.jar
 parboiled-core-1.2.0.jar
 parboiled-scala_2.12-1.2.0.jar
 parser-9.0-9.0.20190305.jar
+perfmark-api-0.19.0.jar
 perfmark-api-0.23.0.jar
 perfmark-api-0.25.0.jar
 picocli-4.3.2.jar
@@ -401,10 +414,12 @@ powermock-module-junit4-2.0.0-RC.3.jar
 powermock-module-junit4-common-2.0.0-RC.3.jar
 powermock-module-junit4-rule-2.0.0-RC.3.jar
 powermock-reflect-2.0.0-RC.3.jar
+protobuf-java-3.11.0.jar
 protobuf-java-3.17.2.jar
 protobuf-java-3.21.7.jar
 protobuf-java-3.5.1.jar
 protobuf-java-util-3.17.2.jar
+proto-google-common-protos-1.17.0.jar
 proto-google-common-protos-2.0.1.jar
 protostuff-api-1.6.0.jar
 protostuff-collectionschema-1.6.0.jar
@@ -440,6 +455,7 @@ sjk-stacktrace-0.22.jar
 slf4j-api-1.7.21.jar
 slf4j-api-1.7.25.jar
 slf4j-api-1.7.32.jar
+snakeyaml-1.18.jar
 snakeyaml-1.26.jar
 snakeyaml-1.27.jar
 snakeyaml-1.28.jar
diff --git a/pom.xml b/pom.xml
index 44be456375..d73753cff4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -87,7 +87,7 @@
 
     <properties>
         <revision>1.5.0</revision>
-        <hugegraph-commons.version>1.3.0</hugegraph-commons.version>
+        <hugegraph-commons.version>1.5.0</hugegraph-commons.version>
         <release.name>hugegraph</release.name>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <maven.compiler.source>11</maven.compiler.source>
@@ -99,6 +99,7 @@
         <module>hugegraph-server</module>
         <module>hugegraph-pd</module>
         <module>hugegraph-store</module>
+        <module>hugegraph-commons</module>
         <module>install-dist</module>
     </modules>
 
@@ -151,6 +152,7 @@
                             <exclude>**/*.conf</exclude>
                             <exclude>**/*.map</exclude>
                             <exclude>**/*.properties</exclude>
+                            <exclude>**/*.template</exclude>
                             <exclude>**/bin/hugegraph.service</exclude>
                             <exclude>**/swagger-ui/**/*</exclude>
                             <exclude>scripts/dev/reviewers</exclude>
@@ -272,6 +274,7 @@
                         <!-- You can exclude further files from processing: -->
                         <exclude>**/*.txt</exclude>
                         <exclude>**/.flattened-pom.xml</exclude>
+                        <exclude>**/apache-hugegraph-*/**/*</exclude>
                     </excludes>
                     <!-- All files are included by default:
                     <includes>