Repository: matrixorigin/matrixone
Pull request #4042 (2022-07-16 13:09:44)

tanslate installMO/ssb-test/mysql-compatibility/create-database/prima…
…ry-key/insert/load-data/select/cast to CN

**What type of PR is this?**

- [ ] API-change
- [ ] BUG
- [ ] Improvement
- [x] Documentation
- [ ] Feature
- [ ] Test and CI
- [ ] Code Refactoring

**Which issue(s) this PR fixes:**

issue #

**What this PR does / why we need it:**

Not Available

**Special notes for your reviewer:**

Not Available

**Additional documentation (e.g. design docs, usage docs, etc.):**

Not Available



Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cf27404ff..fa7470082 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,7 +1,6 @@
 # Define workflow name.
 name: MatrixOne CI
 
-# Controls when the workflow will run.
 on:
   pull_request:
     types: [ opened, synchronize, reopened ]
@@ -38,11 +37,35 @@ jobs:
             exit 1
           fi
           
-      - name: Static Code Analysis
+      - name: Prepare Dependency
         run: |
           cd $GITHUB_WORKSPACE && make clean && make config && make build
           make install-static-check-tools
-          make static-check
+          
+      - name: Run golangci-lint for pkg
+        id: sca-1
+        continue-on-error: true
+        run: |
+          cd $GITHUB_WORKSPACE
+          CGO_CFLAGS="-I${GITHUB_WORKSPACE}/cgo" CGO_LDFLAGS="-L${GITHUB_WORKSPACE}/cgo -lmo" golangci-lint run -E misspell -E exportloopref -E rowserrcheck -E depguard -D unconvert   -E prealloc -E gofmt -E stylecheck --new-from-rev=HEAD~ ./pkg/... --timeout=3m
+
+      - name: Run golangci-lint for cmd
+        id: sca-2
+        continue-on-error: true
+        run: |
+          cd $GITHUB_WORKSPACE
+          CGO_CFLAGS="-I${GITHUB_WORKSPACE}/cgo" CGO_LDFLAGS="-L${GITHUB_WORKSPACE}/cgo -lmo" golangci-lint run -E misspell -E exportloopref -E rowserrcheck -E depguard -D unconvert   -E prealloc -E gofmt -E stylecheck --new-from-rev=HEAD~ ./cmd/... --timeout=3m
+          
+      - name: Run more staticcheck checks
+        id: sca-3
+        continue-on-error: true
+        run: |
+          cd $GITHUB_WORKSPACE
+          CGO_CFLAGS="-I${GITHUB_WORKSPACE}/cgo" CGO_LDFLAGS="-L${GITHUB_WORKSPACE}/cgo -lmo" staticcheck -checks SA9001,S1009,S1023,S1002,S1025,ST1017,ST1019,S1019,S1004,SA1030,S1011,S1008,SA1024,SA4003,S1039,S1028,SA6005 ./...
+      
+      - name: Check on failures
+        if: steps.sca-3.outcome != 'success' || steps.sca-2.outcome != 'success' || steps.sca-1.outcome != 'success'
+        run: exit 1
 
   ut-linux-x86:
     runs-on: ubuntu-latest
@@ -463,28 +486,10 @@ jobs:
           cd $GITHUB_WORKSPACE && make clean && make config && make build
           make install-static-check-tools
           
-      - name: Run golangci-lint for pkg
-        id: sca-1
-        continue-on-error: true
-        run: |
-          cd $GITHUB_WORKSPACE
-          golangci-lint run -E misspell -E exportloopref -E rowserrcheck -E depguard -D unconvert   -E prealloc -E gofmt -E stylecheck ./pkg/...
-
-      - name: Run golangci-lint for cmd
-        id: sca-2
-        continue-on-error: true
+      - name: Static Code Analysis
         run: |
           cd $GITHUB_WORKSPACE
-          golangci-lint run -E misspell -E exportloopref -E rowserrcheck -E depguard -D unconvert   -E prealloc -E gofmt -E stylecheck ./cmd/...
+          make static-check
           
-      - name: Run more staticcheck checks
-        id: sca-3
-        continue-on-error: true
-        run: |
-          cd $GITHUB_WORKSPACE
-          staticcheck -checks QF1001,QF1002,QF1003,QF1004,QF1005,QF1006,QF1007,QF1008,QF1009,QF1010,QF1011,QF1012,S1000,S1001,S1002,S1003,S1004,S1005,S1006,S1007,S1008,S1009,S1010,S1011,S1012,S1016,S1017,S1018,S1019,S1020,S1021,S1023,S1024,S1025,S1028,S1029,S1030,S1031,S1032,S1033,S1034,S1035,S1036,S1037,S1038,S1039,S1040,SA1000,SA1001,SA1002,SA1003,SA1004,SA1005,SA1006,SA1007,SA1008,SA1010,SA1011,SA1012,SA1013,SA1014,SA1015,SA1016,SA1017,SA1018,SA1019,SA1020,SA1021,SA1023,SA1024,SA1025,SA1026,SA1027,SA1028,SA1029,SA1030,SA2000,SA2001,SA2002,SA2003,SA3000,SA3001,SA4000,SA4001,SA4003,SA4004,SA4005,SA4006,SA4008,SA4009,SA4010,SA4011,SA4012,SA4013,SA4014,SA4015,SA4016,SA4017,SA4018,SA4019,SA4020,SA4021,SA4022,SA4023,SA4024,SA4025,SA4026,SA4027,SA4028,SA4029,SA4030,SA4031,SA5000,SA5001,SA5002,SA5003,SA5004,SA5005,SA5007,SA5008,SA5009,SA5010,SA5011,SA5012,SA6000,SA6001,SA6002,SA6003,SA6005,SA9001,SA9002,SA9003,SA9004,SA9005,SA9006,SA9007,SA9008,ST1001,ST1005,ST1006,ST1008,ST1011,ST1012,ST1013,ST1015,ST1016,ST1017,ST1018,ST1019,ST1020,ST1021,ST1022,ST1023 ./...
       
-      - name: Check on failures
-        if: steps.sca-3.outcome != 'success' || steps.sca-2.outcome != 'success' || steps.sca-1.outcome != 'success'
-        run: exit 1
           
diff --git a/.github/workflows/robot.yml b/.github/workflows/robot.yml
index 9dc3333f0..0dac11772 100644
--- a/.github/workflows/robot.yml
+++ b/.github/workflows/robot.yml
@@ -58,10 +58,8 @@ jobs:
         run: |
           cd $GITHUB_WORKSPACE/matrixone
           make install-static-check-tools
-          go vet -vettool=$(which molint) ./... &>lint.out
-          go-licenses check ./... &>>lint.out
-          golangci-lint run -E misspell -E exportloopref -E rowserrcheck -E depguard -E prealloc -E gofmt -E stylecheck ./... &>>lint.out
-
+          make static-check &>lint.out
+          
       - name: count sca failed files
         run: |
           cd $GITHUB_WORKSPACE/matrixone
@@ -85,7 +83,7 @@ jobs:
           cd $GITHUB_WORKSPACE/matrixone
           test_scope=$(go list ./... | grep -v 'driver\|engine/aoe\|engine/memEngine\|pkg/catalog')
           echo "ut start"
-          go test -v -tags matrixone_test -p 1 -covermode=count -coverprofile=${{ env.raw_ut_coverage }} -coverpkg=./pkg/... ${test_scope} | tee ${{ env.ut_report }}
+          CGO_CFLAGS="-I${GITHUB_WORKSPACE}/matrixone/cgo" CGO_LDFLAGS="-L${GITHUB_WORKSPACE}/matrixone/cgo -lmo" go test -v -tags matrixone_test -p 1 -covermode=count -coverprofile=${{ env.raw_ut_coverage }} -coverpkg=./pkg/... ${test_scope} | tee ${{ env.ut_report }}
           echo "ut finished"
           cat ${{ env.raw_ut_coverage }} | grep -v ${{ env.ut_excluded_pkg }} > ${{ env.ut_coverage }}
           echo "ut_coverage finished"
@@ -114,7 +112,7 @@ jobs:
         run: |
           cd $GITHUB_WORKSPACE/matrixone
           if  [ -d  "./store"  ]; then rm -rf ./store; fi
-          go test -c -tags server_test -covermode=count -coverpkg=./pkg/... ./cmd/db-server -o server_test
+          CGO_CFLAGS="-I${GITHUB_WORKSPACE}/matrixone/cgo" CGO_LDFLAGS="-L${GITHUB_WORKSPACE}/matrixone/cgo -lmo" go test -c -tags server_test -covermode=count -coverpkg=./pkg/... ./cmd/db-server -o server_test
           ./server_test -test.coverprofile=${{ env.raw_bvt_coverage }} &>log &
 
       - name: Start BVT Test
diff --git a/.github/workflows/selected_bvt.yml b/.github/workflows/selected_bvt.yml
deleted file mode 100644
index 0e78dfcdb..000000000
--- a/.github/workflows/selected_bvt.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-# Define workflow name.
-# This workflow is used to run with specific branch of bvt,
-# pls make sure that the name pr is equals to the target branch's name.
-name: Run Selected BVT
-
-# Controls when the workflow will run.
-on:
-  # Triggers the workflow on push or pull request events but only for the main branch.
-  pull_request:
-    types: [ labeled, synchronize, reopened, edited ]
-    branches: main
-
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel.
-jobs:
-  build:
-    if: contains(github.event.pull_request.labels.*.name, 'good first issue')
-    runs-on: ubuntu-latest
-    name: Build on CentOS/x64
-
-    steps:
-      # Checks-out your repository under $GITHUB_WORKSPACE, so the job can access it.
-      - uses: actions/checkout@v2
-        with:
-          fetch-depth: '3'
-
-      - name: Set up Go
-        uses: actions/setup-go@v2
-        with:
-          go-version: 1.18
-
-      - name: Build Configure
-        run: |
-          cd $GITHUB_WORKSPACE && make clean && make config
-
-      - name: Build Binary
-        run: |
-          make build
-
-      - name: Build Verification Testing
-        run: |
-          export branch=$(echo "${{ github.event.pull_request.title }}" | awk -F " " '{print $NF}')
-          make bvt BVT_BRANCH="$branch"
-
-      - uses: actions/upload-artifact@v2
-        if: ${{ always() }}
-        with:
-          name: gfi_test_reports
-          path: |
-            ${{ github.workspace }}/coverage.html
-          retention-days: 7
diff --git a/Makefile b/Makefile
index bc827a131..4ec04f02f 100644
--- a/Makefile
+++ b/Makefile
@@ -134,9 +134,9 @@ EXTRA_LINTERS=-E exportloopref -E rowserrcheck -E depguard -D unconvert \
 
 .PHONY: static-check
 static-check: generate cgo
-	@CGO_CFLAGS="-I$(ROOT_DIR)/cgo" CGO_LDFLAGS="-L$(ROOT_DIR)/cgo -lmo" staticcheck -checks SA9001,S1009,S1023,S1002,S1025,ST1017,ST1019,S1019,S1004,SA1030,S1011,S1008,SA1024,SA4003,S1039,S1028,SA6005 ./...
+	@CGO_CFLAGS="-I$(ROOT_DIR)/cgo" CGO_LDFLAGS="-L$(ROOT_DIR)/cgo -lmo" staticcheck -checks QF1001,QF1002,QF1003,QF1004,QF1005,QF1006,QF1007,QF1008,QF1009,QF1010,QF1011,QF1012,S1000,S1001,S1002,S1003,S1004,S1005,S1006,S1007,S1008,S1009,S1010,S1011,S1012,S1016,S1017,S1018,S1019,S1020,S1021,S1023,S1024,S1025,S1028,S1029,S1030,S1031,S1032,S1033,S1034,S1035,S1036,S1037,S1038,S1039,S1040,SA1000,SA1001,SA1002,SA1003,SA1004,SA1005,SA1006,SA1007,SA1008,SA1010,SA1011,SA1012,SA1013,SA1014,SA1015,SA1016,SA1017,SA1018,SA1019,SA1020,SA1021,SA1023,SA1024,SA1025,SA1026,SA1027,SA1028,SA1029,SA1030,SA2000,SA2001,SA2002,SA2003,SA3000,SA3001,SA4000,SA4001,SA4003,SA4004,SA4005,SA4006,SA4008,SA4009,SA4010,SA4011,SA4012,SA4013,SA4014,SA4015,SA4016,SA4017,SA4018,SA4019,SA4020,SA4021,SA4022,SA4023,SA4024,SA4025,SA4026,SA4027,SA4028,SA4029,SA4030,SA4031,SA5000,SA5001,SA5002,SA5003,SA5004,SA5005,SA5007,SA5008,SA5009,SA5010,SA5011,SA5012,SA6000,SA6001,SA6002,SA6003,SA6005,SA9001,SA9002,SA9003,SA9004,SA9005,SA9006,SA9007,SA9008,ST1001,ST1005,ST1006,ST1008,ST1011,ST1012,ST1013,ST1015,ST1016,ST1017,ST1018,ST1019,ST1020,ST1021,ST1022,ST1023 ./...
 	@CGO_CFLAGS="-I$(ROOT_DIR)/cgo" CGO_LDFLAGS="-L$(ROOT_DIR)/cgo -lmo" go vet -vettool=$(which molint) ./...
 	@CGO_CFLAGS="-I$(ROOT_DIR)/cgo" CGO_LDFLAGS="-L$(ROOT_DIR)/cgo -lmo" go-licenses check ./...
 	@for p in $(DIRS); do \
-    CGO_CFLAGS="-I$(ROOT_DIR)/cgo" CGO_LDFLAGS="-L$(ROOT_DIR)/cgo -lmo" golangci-lint run $(EXTRA_LINTERS) --new-from-rev=HEAD~ $$p ; \
+    CGO_CFLAGS="-I$(ROOT_DIR)/cgo" CGO_LDFLAGS="-L$(ROOT_DIR)/cgo -lmo" golangci-lint run $(EXTRA_LINTERS) $$p ; \
   done;
diff --git a/docs/cn/MatrixOne/Get-Started/install-standalone-matrixone.md b/docs/cn/MatrixOne/Get-Started/install-standalone-matrixone.md
index 41707a3ae..f7deb5f8b 100644
--- a/docs/cn/MatrixOne/Get-Started/install-standalone-matrixone.md
+++ b/docs/cn/MatrixOne/Get-Started/install-standalone-matrixone.md
@@ -1,6 +1,12 @@
 # **安装单机版 MatrixOne**
 
-作为一款开源数据库，MatrixOne 目前支持主流的 Linux 和 MacOS 系统。你可以直接从[源代码](#使用源代码搭建)搭建单机版本的 MatrixOne，也可以使用[Docker](#使用docker)安装部署。
+作为一款开源数据库，MatrixOne 目前支持主流的 Linux 和 MacOS 系统。你可以通过以下三种方法安装单机版 MatrixOne：
+
+- [方法 1：使用源代码搭建](#方法 1：使用源代码搭建)
+- [方法 2：下载二进制包](#方法 2：下载二进制包)
+- [方法 3：使用 Docker](方法 3：使用 Docker)
+
+推荐硬件规格：x86 CPU；4核；32GB 内存，支持 CentOS 7+ 操作系统。
 
 ## **方法 1：使用源代码搭建**
 
@@ -29,6 +35,7 @@ $ cd matrixone
 
 ```
 $ git clone https://github.com/matrixorigin/matrixone.git
+$ git checkout 0.5.0
 $ cd matrixone
 ```
 
@@ -97,10 +104,18 @@ $ docker --version
 
 #### 2. 创建并运行容器
 
-使用以下命令将从 Docker Hub 中拉取最近的 MatrixOne 镜像：
+使用以下命令将从 Docker Hub 中拉取 MatrixOne 镜像，你可以选择最新的镜像，或稳定版本的镜像。
+
+- 最新版本的镜像：
+
+```
+$ docker run -d -p 6001:6001 --name matrixone matrixorigin/matrixone:latest
+```
+
+- 0.5.0 稳定版本的镜像
 
 ```
-$ docker run -d -p 6001:6001 --名称 matrixone matrixorigin/matrixone:latest
+$ docker run -d -p 6001:6001 --name matrixone matrixorigin/matrixone:0.5.0
 ```
 
 运行 Docker Hub 时需要输入用户名和密码，获取用户名和密码可以参考下一步骤 - 连接 MatrixOne 服务
diff --git a/docs/cn/MatrixOne/Overview/mysql-compatibility.md b/docs/cn/MatrixOne/Overview/mysql-compatibility.md
index e2df686db..1fd2e75c2 100644
--- a/docs/cn/MatrixOne/Overview/mysql-compatibility.md
+++ b/docs/cn/MatrixOne/Overview/mysql-compatibility.md
@@ -6,7 +6,7 @@ MatrixOne的SQL语法兼容了MySQL 8.0.23版本。
 |  ----  | ----  |  ----  |
 | DDL  | CREATE DATABASE | 不支持中文命名的表名 |
 |   |   | 支持部分拉丁语  |
-|   |   | CHARSET, COLLATE, ENCRYPTION 目前可以使用但无法生效 |
+|   |   | `CHARSET`，`COLLATE`，`ENCRYPTION` 目前可以使用但无法生效 |
 |   | CREATE TABLE | 不支持临时表  |
 |   |   | 不支持表的分区  |
 |   |   | 不支持 `Create table .. as` 语句 |
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md
index 679e67f97..7c95dd357 100644
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md
+++ b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md
@@ -33,5 +33,6 @@
 ```
 
 ## **限制**
- 
-目前只支持 `UTF-8` 字符集。
\ No newline at end of file
+
+- 目前只支持 `UTF-8` 字符集。
+- `CHARACTER SET`，`COLLATE`，`ENCRYPTION` 目前可以使用但无法生效
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-index.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-index.md
deleted file mode 100644
index b48ef668a..000000000
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-index.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# **CREATE INDEX**
-
-## **语法说明**
-
-`CREATE INDEX` 语句为已有表`table_name`的某列添加新索引。
-
-## **语法结构**
-
-```
-> CREATE INDEX index_name ON table_name (column_name)
-
-```
-
-## **示例**
-
-```
-> CREATE INDEX PIndex ON Persons (LastName);
-
-```
-
-## **限制**
-
-目前索引只能应用于单列。此外，还不支持指定索引类型，`UNIQUE/FULLTEXT` 语句还不支持。
\ No newline at end of file
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/drop-index.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/drop-index.md
deleted file mode 100644
index d91cb437f..000000000
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/drop-index.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# **DROP INDEX**
-
-## **语法说明**
-
-`DROP INDEX` 从表`table_name` 中删除名为`index_name`的索引。
-
-## **语法结构**
-
-```
-> DROP INDEX index_name ON table_name; 
-```
-
-## **示例**
-
-```
-> DROP INDEX PIndex ON Persons;
-
-```
\ No newline at end of file
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/primary-key.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/primary-key.md
index 6d105f551..a406822b3 100644
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/primary-key.md
+++ b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/primary-key.md
@@ -4,7 +4,7 @@
 
 `PRIMARY KEY` 即主键约束，用于唯一标示表中的每条数据。
 主键必须包含 `UNIQUE` 值，不能包含 `NULL` 值。
-一个表只能有一个主键，但一个主键可以包含一个或多个列。
+一个表只能有一个主键，但一个主键可以包含一个列。
 
 ## **在建表时创建主键**
 
@@ -20,21 +20,10 @@
 );
 ```
 
-若要对主键进行命名，并指定多个列为主键，可参考如下语句：  
-
-```
-> CREATE TABLE Persons (
-    ID int NOT NULL,
-    LastName varchar(255) NOT NULL,
-    FirstName varchar(255),
-    Age int,
-    CONSTRAINT PK_Person PRIMARY KEY (ID,LastName)
-);
-```
-
 !!! Note 注意区分
     上述示例中只有一个主键 `PK_Person`, 但其中包含了两列（`ID`与`LastName`）
 
 ## **限制**
 
-目前不支持 `DROP PRIMARY KEY` 语句。
\ No newline at end of file
+- 目前不支持 带有 `ALTER TABLE` 的 `DROP PRIMARY KEY` 语句。  
+- 不支持复合主键（即由多个列组成的主键，为复合主键)
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/insert.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/insert.md
index 089d8136e..e01707736 100644
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/insert.md
+++ b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/insert.md
@@ -24,3 +24,7 @@
 |  123 |   abc   |
 +------+---------+
 ```
+
+## **限制**
+
+目前不支持 `INSERT INTO…VALUES(function)` 语法中的内置函数。
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/load-data.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/load-data.md
index 28258d237..3c9780e74 100644
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/load-data.md
+++ b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/load-data.md
@@ -8,12 +8,8 @@
 
 ```
 > LOAD DATA
-    [LOW_PRIORITY | CONCURRENT] [LOCAL]
     INFILE 'file_name'
-    [REPLACE | IGNORE]
     INTO TABLE tbl_name
-    [PARTITION (partition_name [, partition_name] ...)]
-    [CHARACTER SET charset_name]
     [{FIELDS | COLUMNS}
         [TERMINATED BY 'string']
         [[OPTIONALLY] ENCLOSED BY 'char']
@@ -23,11 +19,6 @@
         [STARTING BY 'string']
         [TERMINATED BY 'string']
     ]
-    [IGNORE number {LINES | ROWS}]
-    [(col_name_or_user_var
-        [, col_name_or_user_var] ...)]
-    [SET col_name={expr | DEFAULT}
-        [, col_name={expr | DEFAULT}] ...]
 ```
 
 * `TERMINATED BY`，`ENCLOSED BY`等分隔符的意义与`SELECT INTO`一致。
@@ -42,3 +33,7 @@
 ```sql
 > LOAD DATA INFILE '/ssb-dbgen-path/lineorder_flat.tbl ' INTO TABLE lineorder_flat;
 ```
+
+## **限制**
+
+当前仅支持 `csv` 格式的文件。
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/operators/cast-functions-and-operators/cast.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/operators/cast-functions-and-operators/cast.md
index 7ae6421d5..a20fe1103 100644
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/operators/cast-functions-and-operators/cast.md
+++ b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/operators/cast-functions-and-operators/cast.md
@@ -24,6 +24,8 @@
 * 数值类型向字符CHAR类型转换
 * 格式为数值的字符类型向数值类型转换（负数需要转换为SIGNED）
 
+详细的数据类型转换规则，请参见[数据类型转换](../../../../Data-Types/data-type-conversion.md)。
+
 ## **示例**
 
 ```sql
diff --git a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/select.md b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/select.md
index 8ae6a644b..dc885baf1 100644
--- a/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/select.md
+++ b/docs/cn/MatrixOne/Reference/SQL-Reference/Data-Manipulation-Statements/select.md
@@ -7,69 +7,20 @@
 ## **语法结构**
 
 ``` sql
-> SELECT
-    [ALL | DISTINCT]
-    select_expr [[AS] alias], ...
+SELECT
+    [ALL | DISTINCT ]
+    select_expr [, select_expr] [[AS] alias] ...
     [INTO variable [, ...]]
-    [ FROM table_references
-    [WHERE expr]
-    [GROUP BY {{col_name | expr | position}, ...
-    | extended_grouping_expr}]
-    [HAVING expr]
-    [ORDER BY {col_name | expr} [ASC | DESC], ...]
-    [LIMIT row_count]
-    [OFFSET row_count]
-    ]
+    [FROM table_references
+    [WHERE where_condition]
+    [GROUP BY {col_name | expr | position}
+      [ASC | DESC]]
+    [HAVING where_condition]
+    [ORDER BY {col_name | expr | position}
+      [ASC | DESC]]
+    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
 ```
 
-### **SELECT INTO**
-
-`SELECT INTO` 语句将查询结果存储在变量或者导出为文件。
-
-* SELECT ... INTO ***var_list*** 可以检索列值并将其存储到变量中。
-* SELECT ... INTO OUTFILE 将检索结果输出为文件，可以使用行/列分隔符来生成特定的格式。
-
-``` sql
-> SELECT <expr_list>
-  INTO OUTFILE 'file_name'
-    [{FIELDS}
-        [TERMINATED BY 'char']
-        [ENCLOSED BY 'char']
-    ]
-    [LINES
-        [TERMINATED BY 'string']
-    ]
-    [HEADER 'bool']
-    [MAX_FILE_SIZE long]
-    [FORCE_QUOTE {'col1','col2',...}]
-```
-
-#### 参数释义
-
-* `<expr_list>` 是你想输出的检索结果，为必选参数。
-* `'file_name'` 为本机上你所导出的文件的文件名，以绝对路径。若存在同名文件，则会导致导出失败。此外，路径中的所有前置文件夹都必须事先创建，该命令不会自动创建所需要的文件夹。
-* `TERMINATED BY` 被用来指定字段分隔符，默认值为逗号 `,`。
-* `ENCLOSED BY` 指定了列字段包括符，默认为双引号 `"`。
-* `LINES TERMINATED BY` 表示行结束符，默认为换行符 `\n`。
-* `HEADER` 用于设置文件中是否包含每一列名称的标题行，当为`TRUE`时，输出包含标题行，反之则不包含。
-* 你可以通过`MAX_FILE_SIZE`限制输出文件的大小（以KB为单位）。
-  例如，当`MAX_FILE_SIZE`=5242880(5GB)时，10GB的表就会被导出为两个文件，文件命名规则为原文件名后缀加上`.序号`。若不设置该值，那么默认输出一个文件。
-* `FORCE_QUOTE`强制对每个指定列中所有非NULL值使用引用，使用双引号作为标识。
-* `NULL` 值将被导出为`\N`。
-* `HAVING` 指定组的条件，通常与 `GROUP BY` 从句一起使用。查询的结果是只包含满足 `HAVING` 条件的组。(如果没有 `GROUP BY`，则所有行自动组成单个聚合组。)
-  `HAVING` 从句与 `WHERE` 从句一样，指定选择条件。 但 `WHERE` 从句指定选择列表中的列的条件，但是无法引用聚合函数。即 `WHERE` 用于过滤数据行，而 `HAVING` 用于过滤分组。
-  `HAVING` 必须只引用 `GROUP BY` 从句中的列或聚合函数中使用的列。
-  如果 `HAVING` 从句指定的是不明确的列，则会出现警告。
-
-!!! info 建议
-    如果不设置`MAX_FILE_SIZE`，当表的数据量很大时会输出一个极大的文件，可能因此发生导出失败的情况；因此我们建议您根据实际情况设置该值。
-
-#### 限制
-
- * 相同目录下若存在同名文件，则会导致导出失败。
- * 目前只支持导出 ***.csv*** 类型的文件。
- * 目前只支持通过绝对路径将文件导出到服务器主机，而不能导出到远程客户端。
-
 ## **示例**
 
 ```sql
@@ -85,19 +36,7 @@
 > SELECT * FROM t1 WHERE spID>2 AND userID <2 || userID >=2 OR userID < 2 LIMIT 3;
 
 > SELECT userID,MAX(score) max_score FROM t1 WHERE userID <2 || userID > 3 GROUP BY userID ORDER BY max_score;
-```
 
-```sql
-select * from t1 into outfile '/Users/tmp/test.csv'
-FIELDS TERMINATED BY ','
-ENCLOSED BY '"'
-LINES TERMINATED BY '\n'
-header 'TRUE'
-MAX_FILE_SIZE 9223372036854775807
-FORCE_QUOTE (a, b)
-```
-
-```sql
 > create table t1 (spID int,userID int,score smallint);
 > insert into t1 values (1,1,1);
 > insert into t1 values (2,2,2);
@@ -115,3 +54,9 @@ FORCE_QUOTE (a, b)
 > select userID,count(score) from t1 where userID>2 group by userID having count(score)>1 order by userID;
 Empty set (0.01 sec)s
 ```
+
+## **限制**
+
+- 在 `GROUP BY` 中暂不支持表别名.
+- 暂不支持 `SELECT...FOR UPDATE` 。
+- 部分支持 `INTO OUTFILE`。
diff --git a/docs/en/MatrixOne/Overview/mysql-compatibility.md b/docs/en/MatrixOne/Overview/mysql-compatibility.md
index 2a18e9bce..1c7812bce 100644
--- a/docs/en/MatrixOne/Overview/mysql-compatibility.md
+++ b/docs/en/MatrixOne/Overview/mysql-compatibility.md
@@ -1,12 +1,12 @@
-# **MySQL Compatibility** 
+# **MySQL Compatibility**
 
-MatrixOne SQL syntax conforms with MySQL 8.0.23 version. 
+MatrixOne SQL syntax conforms with MySQL 8.0.23 version.
 
 |  SQL Type   | SQL Syntax  |  Compability with MySQL8.0.23   |
 |  ----  | ----  |  ----  |
 | DDL  | CREATE DATABASE | A database with Chinese name is not supported. |
 |   |   | Names with Latins support limitedly.  |
-|   |   | CHARSET, COLLATE, ENCRYPTION can be used but don't work. |
+|   |   | `CHARSET`, `COLLATE`, `ENCRYPTION` can be used but don't work. |
 |   | CREATE TABLE | Temporary tables are not supported.  |
 |   |   | Partition tables are not supported.  |
 |   |   | Create table .. as clause is not supported now. |
diff --git a/docs/en/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md b/docs/en/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md
index 75de3ef18..0e9df7a9f 100644
--- a/docs/en/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md
+++ b/docs/en/MatrixOne/Reference/SQL-Reference/Data-Definition-Statements/create-database.md
@@ -34,4 +34,5 @@ Create a database.
 
 ## **Constraints**
 
-Only `UTF-8` CHARACTER SET is supported for now. 
+- Only `UTF-8` CHARACTER SET is supported for now.
+- `CHARACTER SET`, `COLLATE`, `ENCRYPTION` can be used but don't work.
diff --git a/go.mod b/go.mod
index b4915b138..5e49832fc 100644
--- a/go.mod
+++ b/go.mod
@@ -11,6 +11,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/s3 v1.26.11
 	github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a
 	github.com/cespare/xxhash/v2 v2.1.2
+	github.com/docker/go-units v0.4.0
 	github.com/fagongzi/goetty v1.13.0
 	github.com/fagongzi/goetty/v2 v2.0.3-0.20220629100032-f8e8c3c38772
 	github.com/fagongzi/util v0.0.0-20210923134909-bccc37b5040d
diff --git a/go.sum b/go.sum
index 607527cf9..abd09433a 100644
--- a/go.sum
+++ b/go.sum
@@ -149,6 +149,7 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn
 github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc h1:8WFBn63wegobsYAX0YjD+8suexZDga5CctH4CCTx2+8=
 github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
diff --git a/optools/run_bvt.sh b/optools/run_bvt.sh
deleted file mode 100755
index f8504759d..000000000
--- a/optools/run_bvt.sh
+++ /dev/null
@@ -1,250 +0,0 @@
-#!/bin/bash
-
-# Copyright 2021 Matrix Origin
-#
-# 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.
-
-set -o nounset
-set -x
-
-if [[ $# != 3 ]]; then
-	echo "Usage: $0 CaseType BuildOne CaseVersion"
-	echo "	CaseType: Options are BVT | FVT | RT | PT"
-	echo "	BuildOne: Options are True|False"
-	echo "	CaseVersion: Options are branch name of tester"
-	exit 1
-fi
-
-CASE_TYPE=$1
-MAKE_ONE=$2
-BRANCH=$3
-
-source ./utilities.sh
-
-if [[ -z $CASE_TYPE ]] || [[ -z $MAKE_ONE ]]; then
-	echo "The parameter is NULL"
-	exit 1
-fi
-
-if [[ ! $CASE_TYPE =~ ^(BVT|FVT|RT|PT)$ ]]; then
-	echo "CaseType is incorrect"
-	exit 1
-fi
-
-
-if [[ ! $MAKE_ONE =~ ^(True|False)$ ]]; then
-	echo 'MakeOne should be "True or "False"'
-	exit 1
-fi
-
-TESTER_REPO="$G_STAGE/mysql-tester"
-TESTER_COMMIT_ID=""
-ONE_REPO="$G_STAGE/matrixone"
-ONE_COMMIT_ID=""
-
-URL_TESTER_REPO="https://github.com/matrixorigin/mysql-tester.git"
-URL_ONE_REPO="https://github.com/matrixorigin/matrixone.git"
-
-BIN_NAME="mo-server"
-CONFIG_NAME="system_vars_config.toml"
-CUBE="store"
-LOG="$G_TS-$CASE_TYPE.log"
-SRV_LOG="$G_WKSP/$G_TS-$CASE_TYPE-SRV.log"
-SRS_LOG="$G_WKSP/$G_TS-$CASE_TYPE-SRS.log"
-TST_LOG="$G_WKSP/$G_TS-$CASE_TYPE-TST.log"
-declare -a RAW_RESULT
-SUMMARY_RESULT='PASS'
-
-BUILD_WKSP=$(dirname "$PWD") && cd $BUILD_WKSP
-
-if [[ ! -f $TST_LOG ]]; then touch $TST_LOG; fi
-if [[ ! -f $SRS_LOG ]]; then touch $SRS_LOG; fi
-if [[ ! -f $SRV_LOG ]]; then touch $SRV_LOG; fi
-
-function logger() {
-	local level=$1
-	local msg=$2
-	local log=$LOG
-	logger_base "$level" "$msg" "$log"
-}
-
-function node_monitor(){
-	nohup dstat -tcmdngspy 2 >> "$SRS_LOG" 2>&1 &
-}
-
-function stop_service(){
-	if ps -ef | grep -v 'grep' | grep $BIN_NAME > /dev/null; then
-		logger "INF" "Stopping service"
-		pkill $BIN_NAME
-	else
-		logger "WRN" "$BIN_NAME does not start"
-	fi
-}
-
-function start_service(){
-	local config_file="system_vars_config.toml"
-	local check_point="ClusterStatus is ok now"
-	local count=0
-
-	if [[ ! -f $G_STAGE/$BIN_NAME ]] || [[ ! -f $G_STAGE/$config_file ]]; then
-		logger "ERR" "Not found mo-server binary or config file"
-		exit 1
-	fi
-
-	cd $G_STAGE
-	logger "INF" "Start MatrixOne service"
-	nohup ./$BIN_NAME $config_file > $SRV_LOG 2>&1 &
-
-	sleep 2
-	if ps -ef | grep -v 'grep' | grep $BIN_NAME >/dev/null 2>&1; then
-		logger "INF" "Service process is running"
-	else
-		logger "ERR" "Service startup fails"
-		exit 1
-	fi
-
-	while :; do
-		if grep "$check_point" $SRV_LOG > /dev/null 2>&1; then
-			logger "INF" "Found \"$check_point\" in log"
-			break
-		else
-			logger "INF" "Service is starting..."
-		fi
-		sleep 1
-		if [ $count -ge 120 ]; then
-			logger "ERR" "Server startup timed out"
-			exit 1
-		fi
-		((count=count+1))
-	done
-	logger "INF" "MatrixOne service is running"
-}
-
-
-function make_tester(){
-	logger "INF" "Build mysql-tester"
-	cd $G_STAGE && git clone -b "$BRANCH" "$URL_TESTER_REPO"
-	cd $TESTER_REPO && TESTER_COMMIT_ID=$(git rev-parse HEAD)
-	logger "INF" "mysql-tester commit ID: $TESTER_COMMIT_ID"
-	logger "INF" "Build mysql-teser"
-	make
-}
-
-function make_one(){
-	if [[ $MAKE_ONE == 'False' ]]; then
-		logger "INF" "Copying MartixOne binary from $BUILD_WKSP"
-		cp -f $BUILD_WKSP/{$BIN_NAME,$CONFIG_NAME} $G_STAGE
-	else
-		logger "INF" "Making MatrixOne binary"
-		ping -c 5 github.com
-		cd $G_STAGE && git clone $URL_ONE_REPO
-		cd $ONE_REPO && ONE_COMMIT_ID=$(git rev-parse HEAD)
-		logger "INF" "matrixone commit ID: $ONE_COMMIT_ID"
-		patch_one
-		logger "INF" "Build matrixone"
-		make clean && make config && make build
-		[[ $? != 0 ]] && exit $?
-		cp -f {$BIN_NAME,$CONFIG_NAME} $G_STAGE
-	fi
-}
-
-function patch_one(){
-	local current_pwd=$(pwd)
-	cd $G_STAGE
-	if [[ -f patch_one.sh ]]; then
-		logger "INF" "Patch issue fix"
-		./patch_one.sh
-	else
-		logger "INF" "Not found patch"
-	fi
-	cd $current_pwd
-}
-
-function run_bvt(){
-	cd $TESTER_REPO
-	logger "INF" "BVT is in progress ..."
-	logger "INF" "Refer to $TST_LOG for details"
-	local host='127.0.0.1'
-	local port='6001'
-	local user='dump'
-	local pswd='111'
-	echo './mysql-tester -host 127.0.0.1 -port 6001 -user dump -passwd 111' >> $TST_LOG
-	./mysql-tester -host $host -port $port -user $user -passwd $pswd 2>&1 | tee -a $TST_LOG
-	if cat $TST_LOG | egrep "Great, All tests passed" >/dev/null 2>&1; then
-		logger "INF" "Great, All tests passed"
-	else
-		logger "ERR" "Not found assertion from tester"
-		SUMMARY_RESULT='FAIL'
-	fi
-	BVT_CASES=($(cat $TST_LOG | egrep "running tests:\ \[.*\]" | awk -F": " '{print $2}' | sed 's/[]["]//g'))
-	local raw=""
-	for bc in ${BVT_CASES[*]}; do
-		logger "INF" "Check $bc test result"
-		if cat $TST_LOG | egrep "\-{3}\ PASS $bc" > /dev/null 2>&1; then
-			RAW_RESULT+=("$(cat $TST_LOG | egrep "\-{3}\ PASS $bc")")
-		else
-			RAW_RESULT+=("--- FAIL $bc")
-			SUMMARY_RESULT='FAIL'
-		fi
-	done
-	logger "INF" "BVT done"
-}
-
-function clean_up(){
-	if ps -ef | grep -v 'grep' | grep mo-server >/dev/null 2>&1; then
-		logger "INF" "Stop existing mo service"
-		pkill mo-server
-	fi
-	logger "INF" "Delete repositories"
-	if [[ -d $TESTER_REPO ]]; then rm -rf $TESTER_REPO; fi
-	if [[ -d $ONE_REPO ]]; then rm -rf $ONE_REPO; fi
-	logger "INF" "Delete $G_STAGE/$CUBE"
-	if [[ -d $G_STAGE/$CUBE ]]; then rm -rf $G_STAGE/$CUBE; fi
-	logger "INF" "Delete $G_STAGE/$BIN_NAME"
-	if [[ -f $G_STAGE/$BIN_NAME ]]; then rm -f $G_STAGE/$BIN_NAME; fi
-	logger "INF" "Delete $G_STAGE/$CONFIG_NAME"
-	if [[ -f $G_STAGE/$CONFIG_NAME ]]; then rm -f $G_STAGE/$CONFIG_NAME; fi
-}
-
-
-horiz_rule
-echo "#  OS TYPE:	   $G_OSTYPE"
-echo "#  CASE TYPE:    $CASE_TYPE"
-echo "#  BUILD BINARY: $MAKE_ONE"
-echo "#  SRV LOG PATH: $SRV_LOG"
-echo "#  SRS LOG PATH: $SRS_LOG"
-echo "#  TST LOG PATH: $TST_LOG"
-horiz_rule
-
-clean_up
-node_monitor
-make_one
-make_tester
-start_service
-run_bvt
-clean_up
-
-horiz_rule
-echo "# Build Verification Test Summary"
-IFS=$'\n'
-printf "%s\n" ${RAW_RESULT[@]} | sort -k3
-unset IFS
-horiz_rule
-
-if [[ 'PASS' != "$SUMMARY_RESULT" ]]; then
-	logger "ERR" "BVT FAILED !!!"
-	exit 1
-else
-	logger "INF" "BVT SUCCEEDED !!!"
-fi
-exit 0
diff --git a/pkg/hakeeper/bootstrap/bootstrap.go b/pkg/hakeeper/bootstrap/bootstrap.go
index 1cd7bff57..df4ab0489 100644
--- a/pkg/hakeeper/bootstrap/bootstrap.go
+++ b/pkg/hakeeper/bootstrap/bootstrap.go
@@ -135,7 +135,8 @@ func (bm *Manager) bootstrapDN(alloc util.IDAllocator, dn pb.DNState) (commands
 		}
 
 		commands = append(commands, pb.ScheduleCommand{
-			UUID: dnStores[i],
+			UUID:          dnStores[i],
+			Bootstrapping: true,
 			ConfigChange: &pb.ConfigChange{
 				Replica: pb.Replica{
 					UUID:      dnStores[i],
diff --git a/pkg/logservice/errors.go b/pkg/logservice/errors.go
index 31450fcaf..e00847c0e 100644
--- a/pkg/logservice/errors.go
+++ b/pkg/logservice/errors.go
@@ -49,6 +49,7 @@ func getErrorToCodeMapping() []errorToCode {
 		{dragonboat.ErrClosed, pb.SystemClosed, true},
 		{dragonboat.ErrInvalidRange, pb.OutOfRange, true},
 
+		{ErrNotHAKeeper, pb.NotHAKeeper, true},
 		{ErrInvalidTruncateLsn, pb.LsnAlreadyTruncated, true},
 		{ErrNotLeaseHolder, pb.NotLeaseHolder, true},
 	}
@@ -87,6 +88,9 @@ func toError(resp pb.Response) error {
 }
 
 func isTempError(err error) bool {
+	if errors.Is(err, ErrNotHAKeeper) {
+		return true
+	}
 	if dragonboat.IsTempError(err) {
 		return true
 	}
diff --git a/pkg/logservice/hakeeper_client.go b/pkg/logservice/hakeeper_client.go
index 991fc74fb..d17ab5d1c 100644
--- a/pkg/logservice/hakeeper_client.go
+++ b/pkg/logservice/hakeeper_client.go
@@ -19,13 +19,16 @@ import (
 	"sync"
 	"time"
 
+	"github.com/cockroachdb/errors"
+
 	"github.com/matrixorigin/matrixone/pkg/common/moerr"
 	"github.com/matrixorigin/matrixone/pkg/common/morpc"
 	pb "github.com/matrixorigin/matrixone/pkg/pb/logservice"
 )
 
 var (
-	ErrNoHAKeeper = moerr.NewError(moerr.INVALID_STATE, "failed to locate HAKeeper")
+	// ErrNotHAKeeper is returned to indicate that HAKeeper can not be located.
+	ErrNotHAKeeper = moerr.NewError(moerr.INVALID_STATE, "failed to locate HAKeeper")
 )
 
 // CNHAKeeperClient is the HAKeeper client used by a CN store.
@@ -59,6 +62,8 @@ type LogHAKeeperClient interface {
 	SendLogHeartbeat(ctx context.Context, hb pb.LogStoreHeartbeat) (pb.CommandBatch, error)
 }
 
+// TODO: HAKeeper discovery to be implemented
+
 // HAKeeperClientConfig is the config for HAKeeper clients.
 type HAKeeperClientConfig struct {
 	// DiscoveryAddress is the Log Service discovery address provided by k8s.
@@ -67,6 +72,124 @@ type HAKeeperClientConfig struct {
 	ServiceAddresses []string
 }
 
+var _ CNHAKeeperClient = (*managedHAKeeperClient)(nil)
+var _ DNHAKeeperClient = (*managedHAKeeperClient)(nil)
+var _ LogHAKeeperClient = (*managedHAKeeperClient)(nil)
+
+// NewCNHAKeeperClient creates a HAKeeper client to be used by a CN node.
+func NewCNHAKeeperClient(ctx context.Context,
+	cfg HAKeeperClientConfig) (CNHAKeeperClient, error) {
+	return newManagedHAKeeperClient(ctx, cfg)
+}
+
+// NewDNHAKeeperClient creates a HAKeeper client to be used by a DN node.
+func NewDNHAKeeperClient(ctx context.Context,
+	cfg HAKeeperClientConfig) (DNHAKeeperClient, error) {
+	return newManagedHAKeeperClient(ctx, cfg)
+}
+
+// NewLogHAKeeperClient creates a HAKeeper client to be used by a Log Service node.
+func NewLogHAKeeperClient(ctx context.Context,
+	cfg HAKeeperClientConfig) (LogHAKeeperClient, error) {
+	return newManagedHAKeeperClient(ctx, cfg)
+}
+
+func newManagedHAKeeperClient(ctx context.Context,
+	cfg HAKeeperClientConfig) (*managedHAKeeperClient, error) {
+	c, err := newHAKeeperClient(ctx, cfg)
+	if err != nil {
+		return nil, err
+	}
+	return &managedHAKeeperClient{client: c, cfg: cfg}, nil
+}
+
+type managedHAKeeperClient struct {
+	cfg    HAKeeperClientConfig
+	client *hakeeperClient
+}
+
+func (c *managedHAKeeperClient) Close() error {
+	if c.client == nil {
+		return nil
+	}
+	return c.client.close()
+}
+
+func (c *managedHAKeeperClient) GetClusterDetails(ctx context.Context) (pb.ClusterDetails, error) {
+	for {
+		cd, err := c.client.getClusterDetails(ctx)
+		if c.isInternalError(err) {
+			if cerr := c.prepareClient(ctx); cerr != nil {
+				plog.Errorf("failed to prepare HAKeeper client %v", cerr)
+				return pb.ClusterDetails{}, cerr
+			}
+			continue
+		}
+		return cd, err
+	}
+}
+
+func (c *managedHAKeeperClient) SendCNHeartbeat(ctx context.Context,
+	hb pb.CNStoreHeartbeat) error {
+	for {
+		err := c.client.sendCNHeartbeat(ctx, hb)
+		if c.isInternalError(err) {
+			if cerr := c.prepareClient(ctx); cerr != nil {
+				plog.Errorf("failed to prepare HAKeeper client %v", cerr)
+				return cerr
+			}
+			continue
+		}
+		return err
+	}
+}
+
+func (c *managedHAKeeperClient) SendDNHeartbeat(ctx context.Context,
+	hb pb.DNStoreHeartbeat) (pb.CommandBatch, error) {
+	for {
+		cb, err := c.client.sendDNHeartbeat(ctx, hb)
+		if c.isInternalError(err) {
+			if cerr := c.prepareClient(ctx); cerr != nil {
+				plog.Errorf("failed to prepare HAKeeper client %v", cerr)
+				return pb.CommandBatch{}, cerr
+			}
+			continue
+		}
+		return cb, err
+	}
+}
+
+func (c *managedHAKeeperClient) SendLogHeartbeat(ctx context.Context,
+	hb pb.LogStoreHeartbeat) (pb.CommandBatch, error) {
+	for {
+		cb, err := c.client.sendLogHeartbeat(ctx, hb)
+		if c.isInternalError(err) {
+			if cerr := c.prepareClient(ctx); cerr != nil {
+				plog.Errorf("failed to prepare HAKeeper client %v", cerr)
+				return pb.CommandBatch{}, cerr
+			}
+			continue
+		}
+		return cb, err
+	}
+}
+
+func (c *managedHAKeeperClient) isInternalError(err error) bool {
+	return errors.Is(err, ErrNotHAKeeper)
+}
+
+func (c *managedHAKeeperClient) prepareClient(ctx context.Context) error {
+	cc, err := newHAKeeperClient(ctx, c.cfg)
+	if err != nil {
+		return err
+	}
+	if err := c.client.close(); err != nil {
+		plog.Errorf("failed to close the client %v", err)
+	}
+	c.client = cc
+	return nil
+}
+
 type hakeeperClient struct {
 	cfg      HAKeeperClientConfig
 	client   morpc.RPCClient
@@ -99,7 +222,7 @@ func newHAKeeperClient(ctx context.Context,
 		}
 		c.addr = addr
 		c.client = cc
-		isHAKeeper, err := c.checkRemote(ctx)
+		isHAKeeper, err := c.checkIsHAKeeper(ctx)
 		plog.Infof("isHAKeeper: %t, err: %v", isHAKeeper, err)
 		if err == nil && isHAKeeper {
 			return c, nil
@@ -112,35 +235,16 @@ func newHAKeeperClient(ctx context.Context,
 	}
 	if e == nil {
 		// didn't encounter any error
-		return nil, ErrNoHAKeeper
+		return nil, ErrNotHAKeeper
 	}
 	return nil, e
 }
 
-var _ CNHAKeeperClient = (*hakeeperClient)(nil)
-var _ DNHAKeeperClient = (*hakeeperClient)(nil)
-var _ LogHAKeeperClient = (*hakeeperClient)(nil)
-
-func NewCNHAKeeperClient(ctx context.Context,
-	cfg HAKeeperClientConfig) (CNHAKeeperClient, error) {
-	return newHAKeeperClient(ctx, cfg)
-}
-
-func NewDNHAKeeperClient(ctx context.Context,
-	cfg HAKeeperClientConfig) (DNHAKeeperClient, error) {
-	return newHAKeeperClient(ctx, cfg)
-}
-
-func NewLogHAKeeperClient(ctx context.Context,
-	cfg HAKeeperClientConfig) (LogHAKeeperClient, error) {
-	return newHAKeeperClient(ctx, cfg)
-}
-
-func (c *hakeeperClient) Close() error {
+func (c *hakeeperClient) close() error {
 	return c.client.Close()
 }
 
-func (c *hakeeperClient) GetClusterDetails(ctx context.Context) (pb.ClusterDetails, error) {
+func (c *hakeeperClient) getClusterDetails(ctx context.Context) (pb.ClusterDetails, error) {
 	req := pb.Request{
 		Method: pb.GET_CLUSTER_DETAILS,
 	}
@@ -151,7 +255,7 @@ func (c *hakeeperClient) GetClusterDetails(ctx context.Context) (pb.ClusterDetai
 	return resp.ClusterDetails, nil
 }
 
-func (c *hakeeperClient) SendCNHeartbeat(ctx context.Context, hb pb.CNStoreHeartbeat) error {
+func (c *hakeeperClient) sendCNHeartbeat(ctx context.Context, hb pb.CNStoreHeartbeat) error {
 	req := pb.Request{
 		Method:      pb.CN_HEARTBEAT,
 		CNHeartbeat: hb,
@@ -160,7 +264,7 @@ func (c *hakeeperClient) SendCNHeartbeat(ctx context.Context, hb pb.CNStoreHeart
 	return err
 }
 
-func (c *hakeeperClient) SendDNHeartbeat(ctx context.Context,
+func (c *hakeeperClient) sendDNHeartbeat(ctx context.Context,
 	hb pb.DNStoreHeartbeat) (pb.CommandBatch, error) {
 	req := pb.Request{
 		Method:      pb.DN_HEARTBEAT,
@@ -169,7 +273,7 @@ func (c *hakeeperClient) SendDNHeartbeat(ctx context.Context,
 	return c.sendHeartbeat(ctx, req)
 }
 
-func (c *hakeeperClient) SendLogHeartbeat(ctx context.Context,
+func (c *hakeeperClient) sendLogHeartbeat(ctx context.Context,
 	hb pb.LogStoreHeartbeat) (pb.CommandBatch, error) {
 	req := pb.Request{
 		Method:       pb.LOG_HEARTBEAT,
@@ -194,7 +298,7 @@ func (c *hakeeperClient) sendHeartbeat(ctx context.Context,
 	return resp.CommandBatch, nil
 }
 
-func (c *hakeeperClient) checkRemote(ctx context.Context) (bool, error) {
+func (c *hakeeperClient) checkIsHAKeeper(ctx context.Context) (bool, error) {
 	req := pb.Request{
 		Method: pb.CHECK_HAKEEPER,
 	}
diff --git a/pkg/logservice/store.go b/pkg/logservice/store.go
index ac51a722f..684ce6d20 100644
--- a/pkg/logservice/store.go
+++ b/pkg/logservice/store.go
@@ -348,6 +348,16 @@ func (l *store) tsoUpdate(ctx context.Context, count uint64) (uint64, error) {
 	return result.Value, nil
 }
 
+func handleNotHAKeeperError(err error) error {
+	if err == nil {
+		return err
+	}
+	if errors.Is(err, dragonboat.ErrShardNotFound) {
+		return ErrNotHAKeeper
+	}
+	return err
+}
+
 func (l *store) addLogStoreHeartbeat(ctx context.Context,
 	hb pb.LogStoreHeartbeat) error {
 	data := MustMarshal(&hb)
@@ -355,7 +365,7 @@ func (l *store) addLogStoreHeartbeat(ctx context.Context,
 	session := l.nh.GetNoOPSession(hakeeper.DefaultHAKeeperShardID)
 	if _, err := l.propose(ctx, session, cmd); err != nil {
 		plog.Errorf("propose failed, %v", err)
-		return err
+		return handleNotHAKeeperError(err)
 	}
 	return nil
 }
@@ -367,7 +377,7 @@ func (l *store) addCNStoreHeartbeat(ctx context.Context,
 	session := l.nh.GetNoOPSession(hakeeper.DefaultHAKeeperShardID)
 	if _, err := l.propose(ctx, session, cmd); err != nil {
 		plog.Errorf("propose failed, %v", err)
-		return err
+		return handleNotHAKeeperError(err)
 	}
 	return nil
 }
@@ -379,7 +389,7 @@ func (l *store) addDNStoreHeartbeat(ctx context.Context,
 	session := l.nh.GetNoOPSession(hakeeper.DefaultHAKeeperShardID)
 	if _, err := l.propose(ctx, session, cmd); err != nil {
 		plog.Errorf("propose failed, %v", err)
-		return err
+		return handleNotHAKeeperError(err)
 	}
 	return nil
 }
@@ -389,8 +399,7 @@ func (l *store) getCommandBatch(ctx context.Context,
 	v, err := l.read(ctx,
 		hakeeper.DefaultHAKeeperShardID, &hakeeper.ScheduleCommandQuery{UUID: uuid})
 	if err != nil {
-		// FIXME: handle not HAKeeper error
-		return pb.CommandBatch{}, err
+		return pb.CommandBatch{}, handleNotHAKeeperError(err)
 	}
 	return *(v.(*pb.CommandBatch)), nil
 }
@@ -399,8 +408,7 @@ func (l *store) getClusterDetails(ctx context.Context) (pb.ClusterDetails, error
 	v, err := l.read(ctx,
 		hakeeper.DefaultHAKeeperShardID, &hakeeper.ClusterDetailsQuery{})
 	if err != nil {
-		// FIXME: handle not HAKeeper error
-		return pb.ClusterDetails{}, err
+		return pb.ClusterDetails{}, handleNotHAKeeperError(err)
 	}
 	return *(v.(*pb.ClusterDetails)), nil
 }
@@ -410,7 +418,7 @@ func (l *store) addScheduleCommands(ctx context.Context,
 	cmd := hakeeper.GetUpdateCommandsCmd(term, cmds)
 	session := l.nh.GetNoOPSession(hakeeper.DefaultHAKeeperShardID)
 	if _, err := l.propose(ctx, session, cmd); err != nil {
-		return err
+		return handleNotHAKeeperError(err)
 	}
 	return nil
 }
diff --git a/pkg/pb/logservice/logservice.pb.go b/pkg/pb/logservice/logservice.pb.go
index b3cfb7a4b..0da790dae 100644
--- a/pkg/pb/logservice/logservice.pb.go
+++ b/pkg/pb/logservice/logservice.pb.go
@@ -158,6 +158,7 @@ const (
 	LsnAlreadyTruncated ErrorCode = 100
 	OutOfRange          ErrorCode = 101
 	NotLeaseHolder      ErrorCode = 102
+	NotHAKeeper         ErrorCode = 103
 	OtherSystemError    ErrorCode = 1000
 )
 
@@ -175,6 +176,7 @@ var ErrorCode_name = map[int32]string{
 	100:  "LsnAlreadyTruncated",
 	101:  "OutOfRange",
 	102:  "NotLeaseHolder",
+	103:  "NotHAKeeper",
 	1000: "OtherSystemError",
 }
 
@@ -192,6 +194,7 @@ var ErrorCode_value = map[string]int32{
 	"LsnAlreadyTruncated": 100,
 	"OutOfRange":          101,
 	"NotLeaseHolder":      102,
+	"NotHAKeeper":         103,
 	"OtherSystemError":    1000,
 }
 
@@ -2634,152 +2637,153 @@ func init() {
 func init() { proto.RegisterFile("logservice.proto", fileDescriptor_fd1040c5381ab5a7) }
 
 var fileDescriptor_fd1040c5381ab5a7 = []byte{
-	// 2319 bytes of a gzipped FileDescriptorProto
+	// 2326 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0x5f, 0x6f, 0x1b, 0xc7,
-	0x11, 0xd7, 0x91, 0x14, 0x45, 0x0e, 0x25, 0xfa, 0xb4, 0xb2, 0x6c, 0x46, 0x49, 0x6d, 0xf7, 0x9a,
-	0x1a, 0xae, 0x9a, 0x48, 0x80, 0x8c, 0x14, 0x4d, 0xab, 0xc4, 0xa0, 0x78, 0x8c, 0xc5, 0x58, 0xa6,
-	0x8c, 0x23, 0x55, 0x04, 0x05, 0x02, 0xf5, 0xc4, 0x5b, 0x91, 0x57, 0x91, 0x77, 0xec, 0xdd, 0x51,
-	0xb5, 0xf2, 0xd4, 0x3e, 0xa4, 0x40, 0x81, 0xbe, 0xf4, 0x2d, 0x28, 0xfa, 0x31, 0xf2, 0x09, 0x8a,
-	0x3e, 0xe4, 0xd1, 0x40, 0xd1, 0xd7, 0xa0, 0xf1, 0x53, 0xdf, 0xfa, 0x15, 0x8a, 0xd9, 0x3f, 0x77,
-	0xbb, 0x24, 0x25, 0xdb, 0xa9, 0xf3, 0xd0, 0xb7, 0xdb, 0xd9, 0x99, 0xd9, 0xd9, 0x99, 0xdf, 0xcc,
-	0xec, 0xee, 0x81, 0x39, 0x0c, 0xfb, 0x31, 0x8d, 0xce, 0xfd, 0x1e, 0xdd, 0x1a, 0x47, 0x61, 0x12,
-	0x12, 0xc8, 0x28, 0x1b, 0xef, 0xf6, 0xfd, 0x64, 0x30, 0x39, 0xd9, 0xea, 0x85, 0xa3, 0xed, 0x7e,
-	0xd8, 0x0f, 0xb7, 0x19, 0xcb, 0xc9, 0xe4, 0x94, 0x8d, 0xd8, 0x80, 0x7d, 0x71, 0xd1, 0x8d, 0xea,
-	0x88, 0x26, 0xae, 0xe7, 0x26, 0x2e, 0x1f, 0x5b, 0x9f, 0x40, 0xb1, 0xd1, 0x6e, 0x87, 0x1e, 0x25,
-	0x04, 0x0a, 0x47, 0x47, 0x2d, 0xbb, 0x66, 0xdc, 0x31, 0xee, 0x95, 0x1d, 0xf6, 0x4d, 0xee, 0x42,
-	0xb5, 0xc3, 0xd7, 0xa9, 0x7b, 0x5e, 0x44, 0xe3, 0xb8, 0x96, 0x63, 0xb3, 0x53, 0x54, 0x94, 0xed,
-	0xfa, 0xbd, 0xb3, 0x5a, 0xfe, 0x8e, 0x71, 0xaf, 0xe0, 0xb0, 0x6f, 0xd4, 0x6c, 0x7f, 0x37, 0x9a,
-	0xff, 0x63, 0xc0, 0xf2, 0x41, 0xd8, 0xef, 0x0c, 0xdc, 0xc8, 0x6b, 0x05, 0xa7, 0x21, 0xa9, 0xc1,
-	0x12, 0x1f, 0xf0, 0x35, 0x0a, 0x8e, 0x1c, 0x92, 0x3d, 0x28, 0x39, 0x74, 0x3c, 0xf4, 0x7b, 0x2e,
-	0x2e, 0x90, 0xbf, 0x57, 0xd9, 0xb9, 0xbb, 0xa5, 0xb8, 0x53, 0xd5, 0xb2, 0x25, 0x19, 0x9b, 0x41,
-	0x12, 0x5d, 0x38, 0xa9, 0x1c, 0xb9, 0x0e, 0x8b, 0xcd, 0x71, 0xd8, 0x1b, 0x08, 0x1b, 0xf8, 0x80,
-	0x6c, 0x40, 0xe9, 0x80, 0xba, 0x1e, 0x8d, 0x5a, 0x76, 0xad, 0xc0, 0x26, 0xd2, 0x31, 0x33, 0x9a,
-	0x46, 0xa3, 0xda, 0xa2, 0x30, 0x9a, 0x46, 0xa3, 0x8d, 0x9f, 0xc3, 0x8a, 0xb6, 0x00, 0x31, 0x21,
-	0x7f, 0x46, 0x2f, 0x84, 0xc1, 0xf8, 0x89, 0x0b, 0x9d, 0xbb, 0xc3, 0x09, 0x15, 0xae, 0xe0, 0x83,
-	0x9f, 0xe5, 0x7e, 0x6a, 0x58, 0xe7, 0x50, 0x3d, 0x08, 0xfb, 0x42, 0x9e, 0x6d, 0xf9, 0x23, 0xdd,
-	0x05, 0x4c, 0x4d, 0x65, 0xa7, 0x76, 0xd9, 0xe6, 0xf6, 0x4a, 0x5f, 0x7d, 0x7d, 0x7b, 0xe1, 0xd9,
-	0xd7, 0xb7, 0x0d, 0x47, 0x77, 0xdd, 0x5b, 0x50, 0x96, 0x6a, 0x6d, 0xb6, 0x6e, 0xc1, 0xc9, 0x08,
-	0x56, 0x1b, 0xcc, 0x46, 0xbb, 0x93, 0x84, 0x11, 0xdd, 0xa7, 0x6e, 0x94, 0x9c, 0x50, 0x37, 0xf9,
-	0x5f, 0xa2, 0x69, 0xfd, 0xd3, 0x80, 0x55, 0x5c, 0xfe, 0xc5, 0x1a, 0xef, 0x40, 0xc5, 0x71, 0x4f,
-	0x13, 0x5d, 0x9d, 0x4a, 0x9a, 0xb3, 0x66, 0x7e, 0x2e, 0x82, 0xde, 0x86, 0x95, 0x87, 0x61, 0x1c,
-	0xfb, 0x63, 0xc9, 0x56, 0x60, 0x6c, 0x3a, 0x91, 0xec, 0x2a, 0x40, 0x59, 0x64, 0x40, 0xd9, 0x98,
-	0xf2, 0xa5, 0xe2, 0xfd, 0xbd, 0x02, 0x7a, 0x33, 0x83, 0x88, 0xd5, 0x84, 0x8a, 0xdd, 0x7e, 0x19,
-	0x3c, 0x5e, 0xed, 0xee, 0xcf, 0x0d, 0x30, 0xed, 0xd7, 0xe8, 0x6f, 0xf2, 0x1e, 0x14, 0xd9, 0xca,
-	0xe8, 0x1b, 0xdc, 0xd3, 0x4d, 0x75, 0x4f, 0x8a, 0xc5, 0x62, 0x43, 0x82, 0xd9, 0xfa, 0x63, 0x0e,
-	0x4a, 0x4e, 0xe7, 0x71, 0x27, 0x71, 0x13, 0x8a, 0x38, 0xed, 0xc6, 0xa1, 0xc4, 0x69, 0x37, 0x0e,
-	0x11, 0xa7, 0xad, 0xc0, 0xa3, 0x4f, 0xc5, 0x06, 0xf8, 0x00, 0xfd, 0x7c, 0x40, 0xdd, 0x98, 0xee,
-	0x87, 0x43, 0x9e, 0x15, 0x3c, 0x5d, 0x74, 0x22, 0xb1, 0x60, 0xb9, 0x1b, 0x4d, 0x82, 0x9e, 0x9b,
-	0x50, 0xef, 0x20, 0x0e, 0x44, 0xea, 0x68, 0x34, 0xf2, 0x31, 0x2c, 0x73, 0x21, 0x3f, 0x4e, 0xc2,
-	0xe8, 0x42, 0xc4, 0x43, 0x4b, 0x5c, 0x69, 0xdd, 0x96, 0xca, 0xc8, 0x13, 0x57, 0x93, 0xdd, 0x78,
-	0x00, 0xab, 0x33, 0x2c, 0x2f, 0x4a, 0xbd, 0x82, 0x9a, 0x7a, 0x9f, 0x42, 0x99, 0x05, 0xbf, 0x17,
-	0x46, 0x1e, 0x0a, 0xa2, 0xd1, 0x42, 0x10, 0x6d, 0xdd, 0x84, 0x42, 0xf7, 0x62, 0xcc, 0xe5, 0xaa,
-	0x3b, 0x37, 0x34, 0x1b, 0x99, 0x0c, 0xce, 0x3a, 0x8c, 0x07, 0x23, 0x69, 0xbb, 0x89, 0xcb, 0x1c,
-	0xb3, 0xec, 0xb0, 0x6f, 0xeb, 0x0b, 0x03, 0x80, 0xe9, 0xff, 0xcd, 0x84, 0xc6, 0x2c, 0xd8, 0x6d,
-	0x77, 0x44, 0x65, 0xb0, 0xf1, 0x5b, 0x45, 0x53, 0x4e, 0x47, 0x93, 0x30, 0x27, 0x9f, 0x99, 0x53,
-	0x83, 0xa5, 0xc7, 0xee, 0xd3, 0x8e, 0xff, 0x19, 0x15, 0x9e, 0x95, 0x43, 0x44, 0x9e, 0x0c, 0xb8,
-	0x2d, 0x0a, 0x53, 0x46, 0x60, 0xa6, 0xb5, 0x5b, 0x76, 0xad, 0xc8, 0x2b, 0x16, 0x7e, 0x5b, 0x16,
-	0x40, 0x37, 0x0e, 0xa5, 0x65, 0xd7, 0x61, 0xb1, 0x11, 0x4e, 0x82, 0x44, 0x6c, 0x9e, 0x0f, 0xac,
-	0xbf, 0xe5, 0x61, 0x49, 0x72, 0x30, 0x6c, 0xb3, 0xcf, 0x14, 0xf7, 0x19, 0x81, 0x6c, 0x41, 0xf1,
-	0x31, 0x4d, 0x06, 0xa1, 0x37, 0xcf, 0x55, 0x7c, 0x86, 0xb9, 0x4a, 0x70, 0xe1, 0x4e, 0xba, 0xfe,
-	0x88, 0x86, 0x93, 0x84, 0xed, 0x2f, 0xef, 0xc8, 0x21, 0xd9, 0x55, 0x3d, 0xc6, 0xb6, 0x59, 0xd1,
-	0xb5, 0x65, 0xb3, 0x02, 0xd7, 0xaa, 0x87, 0x1f, 0xb2, 0xc2, 0x99, 0xa6, 0x17, 0x73, 0x45, 0x65,
-	0xe7, 0x7b, 0xd3, 0x85, 0x53, 0xcb, 0x41, 0xa1, 0x46, 0x13, 0x24, 0x36, 0x54, 0x1a, 0xed, 0x4c,
-	0x4f, 0x91, 0xe9, 0x79, 0x4b, 0xd5, 0x33, 0x5d, 0x3a, 0x85, 0x1a, 0x55, 0x0c, 0xb5, 0xd8, 0x8a,
-	0x96, 0xa5, 0x59, 0x2d, 0xf6, 0x25, 0x5a, 0x14, 0x31, 0x74, 0x49, 0x16, 0xaa, 0x5a, 0x69, 0xd6,
-	0x25, 0xd9, 0xac, 0x74, 0x49, 0x46, 0xb1, 0x3a, 0x50, 0x61, 0x0e, 0x8a, 0xc7, 0x61, 0x10, 0xd3,
-	0x2b, 0xaa, 0x97, 0xc0, 0x5b, 0x4e, 0xc3, 0xdb, 0x81, 0x1b, 0x27, 0x19, 0x0a, 0xe5, 0xd0, 0xfa,
-	0x26, 0x8f, 0x15, 0x55, 0xa8, 0x7c, 0xbd, 0xd0, 0xb8, 0x0f, 0xe5, 0x66, 0x14, 0x85, 0x51, 0x23,
-	0xf4, 0x28, 0x5b, 0xb6, 0xba, 0xb3, 0xae, 0x8a, 0xa4, 0x93, 0x4e, 0xc6, 0x87, 0x85, 0x87, 0x0d,
-	0x1e, 0xd3, 0x38, 0x76, 0xfb, 0x54, 0x74, 0x01, 0x8d, 0x46, 0x6e, 0x01, 0xb4, 0xe2, 0xfd, 0xfa,
-	0x23, 0x4a, 0xc7, 0x34, 0x62, 0xc8, 0x28, 0x39, 0x0a, 0x85, 0x3c, 0xd0, 0x1c, 0x25, 0x42, 0x7e,
-	0x73, 0x06, 0x7a, 0x7c, 0x5a, 0xc6, 0x49, 0x75, 0xed, 0x1e, 0x2c, 0x37, 0xc2, 0xd1, 0xc8, 0x0d,
-	0xbc, 0x3d, 0x37, 0xe9, 0x0d, 0x44, 0xb8, 0xb5, 0xae, 0xad, 0xce, 0x4b, 0xdc, 0xa9, 0x34, 0x34,
-	0x82, 0xc5, 0x4e, 0x18, 0x51, 0x9a, 0x35, 0x42, 0x99, 0x96, 0x46, 0x28, 0x24, 0xb2, 0x0f, 0xd5,
-	0xc6, 0x70, 0x12, 0x27, 0x34, 0xb2, 0x69, 0xe2, 0xfa, 0xc3, 0xb8, 0x56, 0x66, 0x3a, 0xb4, 0x86,
-	0xa7, 0x73, 0x08, 0x35, 0x53, 0x72, 0xd6, 0xc7, 0xac, 0x9b, 0xf3, 0x3a, 0x97, 0xaa, 0x7f, 0x0f,
-	0x2b, 0x02, 0x52, 0xe2, 0x9a, 0xc1, 0x0a, 0xf7, 0xfa, 0x8c, 0x83, 0x70, 0x56, 0xa8, 0x94, 0xbc,
-	0xd6, 0x0f, 0xb4, 0x6d, 0x61, 0xb9, 0xf9, 0x05, 0x2b, 0xc8, 0xa2, 0xdc, 0xb0, 0x81, 0x75, 0x86,
-	0xba, 0x59, 0xb7, 0x9c, 0xdb, 0x16, 0x2f, 0xaf, 0x94, 0x5a, 0xdf, 0xcd, 0x4f, 0xf5, 0xdd, 0xec,
-	0x84, 0x57, 0x50, 0x4e, 0x78, 0xd6, 0x5f, 0x72, 0x18, 0xad, 0xe0, 0xd4, 0xef, 0x37, 0x06, 0x6e,
-	0xd0, 0xa7, 0xe4, 0x7e, 0xba, 0xba, 0x38, 0x6e, 0xad, 0xe9, 0xe5, 0x9e, 0x4d, 0x65, 0xfb, 0xe2,
-	0x76, 0xee, 0x02, 0x70, 0x71, 0xa5, 0x4d, 0xe8, 0x55, 0x42, 0x59, 0x82, 0xc1, 0x5c, 0xe1, 0x27,
-	0x5d, 0xa8, 0xb6, 0x02, 0x3f, 0xf1, 0xdd, 0xe1, 0x63, 0x3a, 0x3a, 0xa1, 0x91, 0x6c, 0xe4, 0xef,
-	0x5c, 0xa6, 0x61, 0x4b, 0x67, 0xe7, 0x2d, 0x71, 0x4a, 0xc7, 0x46, 0x1d, 0xd6, 0xe6, 0xb0, 0xbd,
-	0xd2, 0x89, 0xf4, 0x47, 0xb0, 0xd2, 0x19, 0x4c, 0x12, 0x2f, 0xfc, 0x6d, 0xc0, 0xca, 0x13, 0xf3,
-	0x3d, 0x7e, 0xa4, 0x21, 0x91, 0x43, 0xeb, 0xf3, 0x1c, 0x5c, 0xeb, 0xf4, 0x06, 0xd4, 0x9b, 0x0c,
-	0xa9, 0x40, 0xf2, 0xdc, 0xe8, 0xbd, 0x0d, 0x2b, 0x7b, 0x61, 0x98, 0xc4, 0x49, 0xe4, 0x8e, 0xc7,
-	0x7e, 0xd0, 0x67, 0x8b, 0x96, 0x1c, 0x9d, 0x48, 0x76, 0xf5, 0xa0, 0xb0, 0x60, 0xce, 0xa4, 0x50,
-	0x36, 0xef, 0xe8, 0x21, 0x7c, 0x1f, 0x2a, 0xe2, 0x88, 0xc4, 0xc2, 0x51, 0x60, 0xe1, 0xd0, 0x92,
-	0x47, 0x99, 0x76, 0x54, 0x5e, 0xf2, 0x60, 0x6a, 0xc7, 0xa2, 0x73, 0xbc, 0xa1, 0x09, 0xab, 0x0c,
-	0x8e, 0xce, 0x6f, 0xb9, 0x7a, 0xf2, 0xa7, 0xb7, 0x04, 0x23, 0xbb, 0x25, 0x90, 0x0f, 0xa0, 0x24,
-	0x78, 0xe4, 0x7d, 0xe5, 0x4d, 0x4d, 0xbf, 0xee, 0x46, 0x79, 0x0e, 0x95, 0x22, 0x56, 0x0b, 0x7b,
-	0x12, 0xf7, 0x3b, 0x9e, 0x43, 0xe5, 0xe5, 0xc9, 0xc8, 0x2e, 0x4f, 0x2f, 0x7d, 0x54, 0xff, 0xab,
-	0x01, 0x4b, 0xa8, 0x0b, 0x8f, 0x80, 0x1f, 0x40, 0x91, 0x29, 0x95, 0x19, 0x7d, 0x7b, 0xba, 0xcb,
-	0xe1, 0x49, 0x8c, 0x73, 0x30, 0x24, 0xa5, 0xc7, 0x49, 0x46, 0xda, 0x70, 0xa0, 0xa2, 0x4c, 0xaa,
-	0x30, 0x2b, 0x73, 0x98, 0xbd, 0xab, 0xc2, 0x6c, 0xaa, 0x98, 0x29, 0xfb, 0x51, 0xf1, 0xf7, 0x3b,
-	0x83, 0x1d, 0xb9, 0x5f, 0xc7, 0x56, 0xbf, 0xed, 0x29, 0x19, 0x3d, 0x64, 0xbf, 0x8c, 0x87, 0xec,
-	0xef, 0xd6, 0x43, 0xf6, 0x7c, 0x0f, 0x3d, 0x9d, 0x2e, 0xf3, 0x64, 0x07, 0xed, 0xc5, 0x1b, 0xb9,
-	0xb4, 0x92, 0xe8, 0x6a, 0x70, 0x4a, 0x96, 0x2f, 0xc1, 0x88, 0x32, 0x0d, 0x21, 0x93, 0x9b, 0x95,
-	0x69, 0x68, 0x32, 0x82, 0xd1, 0xfa, 0x83, 0x01, 0x15, 0xb1, 0x34, 0x8b, 0xcd, 0xfb, 0x50, 0x12,
-	0x5e, 0x94, 0x0b, 0xdf, 0xdc, 0x4a, 0x9f, 0x21, 0xc4, 0x8c, 0xd6, 0x14, 0x52, 0x76, 0xb2, 0xcb,
-	0x4e, 0xdf, 0x42, 0x96, 0x1b, 0x50, 0xcb, 0x64, 0xe5, 0x94, 0x26, 0x9c, 0x09, 0x58, 0x7f, 0x36,
-	0x60, 0x5d, 0x14, 0x3a, 0x61, 0x8f, 0x3c, 0x05, 0xde, 0x85, 0x6a, 0x7b, 0x32, 0x3a, 0x3c, 0xcd,
-	0x94, 0x73, 0xe0, 0x4c, 0x51, 0xb1, 0x26, 0x31, 0x4a, 0x6a, 0x3f, 0xef, 0x2b, 0x3a, 0x91, 0x6c,
-	0x82, 0x29, 0xe5, 0xd2, 0x4b, 0x24, 0x6f, 0x32, 0x33, 0x74, 0xeb, 0x99, 0x78, 0xbc, 0xb8, 0x12,
-	0xb9, 0xff, 0x5f, 0xb7, 0xdf, 0x2f, 0x73, 0x50, 0x62, 0x5b, 0xc2, 0x4c, 0xf8, 0x30, 0x4d, 0x26,
-	0x1e, 0xea, 0x3b, 0x33, 0x27, 0x6b, 0x96, 0x0a, 0x8c, 0x45, 0x4f, 0x05, 0xee, 0xcb, 0x0f, 0xd3,
-	0x4c, 0xca, 0x5d, 0x25, 0x7f, 0x69, 0x2a, 0x75, 0xa0, 0xa2, 0x28, 0x9f, 0xd3, 0xd3, 0xb6, 0xf4,
-	0x54, 0xba, 0xf4, 0xc9, 0x44, 0xc9, 0x25, 0xa6, 0xf4, 0xca, 0xfc, 0x7c, 0x91, 0xd2, 0x79, 0x09,
-	0xfa, 0x7b, 0x3c, 0x5f, 0x0c, 0x68, 0xef, 0x8c, 0x46, 0xdc, 0x75, 0xf3, 0x90, 0xf0, 0x40, 0x4b,
-	0xa5, 0xb9, 0x05, 0x32, 0x9b, 0x4e, 0x2f, 0x18, 0x4a, 0xf2, 0xdd, 0x4f, 0x8b, 0x94, 0x68, 0x95,
-	0x6b, 0x73, 0x4a, 0x53, 0x96, 0xf5, 0xdc, 0x92, 0x9f, 0x64, 0x01, 0x15, 0x17, 0xac, 0xeb, 0xf3,
-	0xc2, 0x20, 0x91, 0x90, 0x06, 0x7f, 0x1b, 0x16, 0xb9, 0xd0, 0x22, 0x6b, 0xac, 0x5a, 0x6f, 0x94,
-	0xa7, 0x68, 0xc6, 0xe0, 0x70, 0x3e, 0xeb, 0xcb, 0x45, 0x30, 0xe5, 0x44, 0xfa, 0xe2, 0x30, 0xcf,
-	0x0f, 0x37, 0xa0, 0xd8, 0xa6, 0x4f, 0x93, 0xf4, 0x64, 0x27, 0x46, 0x69, 0x13, 0xcd, 0x2b, 0x4d,
-	0x34, 0xb5, 0xa2, 0xf0, 0x72, 0x56, 0x10, 0x0f, 0xcc, 0xa9, 0xce, 0x2a, 0xd3, 0x60, 0x67, 0x9e,
-	0x6c, 0xfa, 0xf8, 0x30, 0x2d, 0xa4, 0xe2, 0x71, 0x46, 0x23, 0x69, 0xa9, 0xb5, 0xac, 0xc8, 0xd4,
-	0xff, 0xf8, 0x4a, 0xf5, 0x29, 0x37, 0x3f, 0xc5, 0x65, 0xd2, 0x18, 0x54, 0xd1, 0x76, 0xc5, 0x15,
-	0x62, 0x6d, 0x4e, 0x47, 0xce, 0xca, 0x32, 0xdf, 0xa5, 0x82, 0x84, 0xd2, 0xb7, 0x42, 0x42, 0xf9,
-	0x15, 0x90, 0x30, 0x85, 0x5b, 0x78, 0x55, 0xdc, 0x6e, 0x7c, 0x0a, 0xeb, 0x73, 0xdd, 0xfb, 0x8a,
-	0xc9, 0xa7, 0x9e, 0xb8, 0xd4, 0x8c, 0xde, 0x65, 0x2f, 0xaa, 0x97, 0x54, 0x8a, 0xf2, 0x0b, 0x1e,
-	0x85, 0x36, 0x7f, 0x05, 0x70, 0x34, 0xf6, 0xdc, 0x84, 0x9f, 0x0c, 0x6f, 0xc2, 0x9a, 0xf6, 0xc8,
-	0xc5, 0xa7, 0xcc, 0x05, 0xb2, 0x0e, 0xab, 0xf2, 0x61, 0xeb, 0xa0, 0xd3, 0x16, 0x64, 0x83, 0xac,
-	0xc1, 0xb5, 0xa3, 0x98, 0x46, 0x6c, 0x59, 0x41, 0xcc, 0x91, 0x15, 0x28, 0x77, 0x3b, 0x87, 0x62,
-	0x98, 0xdf, 0xfc, 0x87, 0x01, 0x90, 0x5d, 0x7d, 0x49, 0x15, 0xa0, 0xdb, 0x39, 0x3c, 0x3e, 0x7a,
-	0x62, 0xd7, 0xbb, 0x4d, 0x73, 0x81, 0x00, 0x14, 0xeb, 0x4f, 0x9e, 0x34, 0xdb, 0xb6, 0x69, 0x90,
-	0x12, 0x14, 0x9c, 0x66, 0xdd, 0x36, 0x73, 0x64, 0x19, 0x4a, 0x5d, 0xe7, 0xa8, 0xdd, 0x40, 0x9e,
-	0x3c, 0x31, 0x61, 0xf9, 0x61, 0xb3, 0x7b, 0x9c, 0x52, 0x0a, 0xa4, 0x02, 0x4b, 0x8d, 0xc3, 0x76,
-	0xbb, 0xd9, 0xe8, 0x9a, 0x8b, 0xa8, 0x52, 0x0c, 0x8e, 0x9d, 0x43, 0xb3, 0x48, 0x56, 0x61, 0xe5,
-	0xe0, 0xf0, 0xe1, 0xf1, 0x7e, 0xb3, 0xee, 0x74, 0xf7, 0x9a, 0xf5, 0xae, 0xb9, 0x84, 0x1a, 0x1a,
-	0x6d, 0x85, 0x52, 0x42, 0x8a, 0xad, 0x52, 0xca, 0x84, 0x40, 0xb5, 0xb1, 0xdf, 0x6c, 0x3c, 0x3a,
-	0xde, 0xaf, 0x3f, 0x6a, 0x36, 0x9f, 0x34, 0x1d, 0x13, 0xd0, 0x21, 0xb8, 0x72, 0xe3, 0xe0, 0xa8,
-	0xd3, 0x6d, 0x3a, 0xc7, 0x76, 0xb3, 0x5b, 0x6f, 0x1d, 0x74, 0xcc, 0xca, 0x66, 0x1b, 0x20, 0x7b,
-	0x15, 0x43, 0x0b, 0xd0, 0x0f, 0x9c, 0x62, 0x2e, 0xa0, 0xf9, 0xad, 0x20, 0xa1, 0x51, 0xe0, 0x0e,
-	0x4d, 0x83, 0x5c, 0x83, 0x0a, 0xf3, 0x6a, 0xea, 0xa1, 0x55, 0xf1, 0xc0, 0xe8, 0xd0, 0x5f, 0xd3,
-	0x5e, 0x42, 0x3d, 0x33, 0xbf, 0xf9, 0xa7, 0x9c, 0xf2, 0x14, 0x80, 0xdb, 0x6b, 0x87, 0x6c, 0x68,
-	0x2e, 0xe0, 0x40, 0x3c, 0x18, 0x99, 0x06, 0x6a, 0x6e, 0xb8, 0x41, 0x8f, 0x0e, 0xa9, 0x67, 0xe6,
-	0x70, 0x13, 0xad, 0xe0, 0xdc, 0x1d, 0xfa, 0x1e, 0x8b, 0xbf, 0x99, 0xc7, 0x4d, 0x08, 0x8a, 0x94,
-	0x29, 0x28, 0xb4, 0x27, 0xee, 0xc5, 0x30, 0x74, 0x3d, 0x73, 0x91, 0xdc, 0x00, 0xa2, 0xd3, 0x3a,
-	0xfe, 0x67, 0xd4, 0x2c, 0xa2, 0xfe, 0xd4, 0xaa, 0x25, 0x34, 0x94, 0x29, 0x6e, 0x87, 0x89, 0x43,
-	0x5d, 0xef, 0x82, 0xfb, 0xad, 0x73, 0x11, 0x27, 0x74, 0xd4, 0x18, 0x86, 0x31, 0xf5, 0xcc, 0x32,
-	0x03, 0x4d, 0x1c, 0xd4, 0x87, 0x11, 0x72, 0xa4, 0xcf, 0x9f, 0xa6, 0x87, 0x5e, 0x39, 0x9c, 0x24,
-	0x87, 0xa7, 0x0e, 0x5e, 0x58, 0x4c, 0xac, 0x86, 0xd5, 0x76, 0x98, 0x28, 0x00, 0x33, 0x4f, 0xc9,
-	0x3a, 0x98, 0x87, 0xc9, 0x80, 0x46, 0x5c, 0x27, 0xdf, 0xf2, 0xbf, 0x97, 0x36, 0xff, 0x6e, 0x00,
-	0x91, 0x55, 0x44, 0xc1, 0x27, 0x82, 0xc7, 0xef, 0x9d, 0xa9, 0xb0, 0x54, 0x9e, 0xa0, 0x52, 0x58,
-	0xae, 0xc3, 0xaa, 0x3d, 0x43, 0xce, 0xe1, 0x9e, 0xd5, 0x77, 0x2f, 0x89, 0x50, 0x8c, 0xcf, 0x43,
-	0x9a, 0xa4, 0x68, 0x2f, 0x90, 0x37, 0x66, 0x32, 0x56, 0x4c, 0x2d, 0xe2, 0x1e, 0x3a, 0x34, 0x61,
-	0x95, 0x41, 0xd0, 0x8a, 0xa4, 0x06, 0xd7, 0xf5, 0xb3, 0x99, 0x98, 0x59, 0xda, 0xfc, 0xc2, 0x80,
-	0x15, 0xad, 0x4e, 0x63, 0xc6, 0x48, 0x42, 0x23, 0xa2, 0xcc, 0x51, 0x0b, 0xb8, 0x9e, 0x24, 0x6a,
-	0x57, 0x44, 0xd3, 0x20, 0x3f, 0x84, 0xef, 0xcf, 0x4c, 0xc9, 0x2a, 0xe2, 0xd0, 0x1e, 0xf5, 0xcf,
-	0x19, 0x10, 0xde, 0x84, 0x9b, 0x33, 0x6c, 0x1f, 0xb9, 0x3e, 0xa2, 0x24, 0xaf, 0xae, 0xe9, 0x4c,
-	0x82, 0x00, 0x15, 0x17, 0x36, 0x3f, 0x01, 0x73, 0xfa, 0xbe, 0x8e, 0xee, 0xad, 0x7b, 0x9e, 0x38,
-	0x0d, 0x99, 0x0b, 0x18, 0x7e, 0x87, 0x8e, 0xc2, 0x73, 0x2a, 0x49, 0x06, 0x0b, 0x7f, 0xe2, 0x46,
-	0x89, 0xa4, 0xe4, 0xd0, 0x7b, 0x9d, 0x24, 0x1c, 0x4b, 0x42, 0x7e, 0xf3, 0x1d, 0xed, 0x66, 0x8a,
-	0x4a, 0xb1, 0x3e, 0x71, 0x8a, 0xb9, 0x80, 0xe5, 0xc1, 0x0e, 0xe4, 0xd0, 0xd8, 0x6b, 0x3e, 0xfb,
-	0xe6, 0xd6, 0xc2, 0x57, 0xcf, 0x6f, 0x19, 0xcf, 0x9e, 0xdf, 0x32, 0xfe, 0xf5, 0xfc, 0x96, 0xf1,
-	0xcb, 0xfb, 0xca, 0x7f, 0xc0, 0x91, 0x9b, 0x44, 0xfe, 0xd3, 0x30, 0xf2, 0xfb, 0x7e, 0x20, 0x07,
-	0x01, 0xdd, 0x1e, 0x9f, 0xf5, 0xb7, 0xc7, 0x27, 0xdb, 0x59, 0x75, 0x3c, 0x29, 0xb2, 0x9f, 0x80,
-	0xf7, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xee, 0x59, 0x31, 0x21, 0x63, 0x1c, 0x00, 0x00,
+	0x11, 0xd7, 0x91, 0x14, 0x45, 0x0d, 0x25, 0xfa, 0xb4, 0xb2, 0x6c, 0x46, 0x49, 0x6d, 0xf7, 0x9a,
+	0x1a, 0xae, 0x9a, 0x48, 0x80, 0x8c, 0x14, 0x4d, 0xab, 0xc4, 0xa0, 0x78, 0x8c, 0xc5, 0x58, 0x3e,
+	0x19, 0x47, 0xaa, 0x08, 0x0a, 0x04, 0xea, 0x89, 0xb7, 0xa2, 0xae, 0x22, 0xef, 0xd8, 0xbb, 0xa3,
+	0x6a, 0xe5, 0xa9, 0x7d, 0x48, 0x81, 0x3e, 0xf6, 0x2d, 0x28, 0xda, 0x6f, 0x91, 0x4f, 0x50, 0xf4,
+	0x21, 0x8f, 0x06, 0x8a, 0xbe, 0x06, 0x8d, 0x9f, 0xfa, 0xd6, 0xaf, 0x50, 0xcc, 0xfe, 0xb9, 0xdb,
+	0x25, 0x29, 0xd9, 0x4e, 0x9d, 0x87, 0xbe, 0xdd, 0xce, 0xce, 0xcc, 0xce, 0xce, 0xfc, 0x66, 0x66,
+	0x77, 0x0f, 0xcc, 0x41, 0xd4, 0x4f, 0x68, 0x7c, 0x1e, 0xf4, 0xe8, 0xe6, 0x28, 0x8e, 0xd2, 0x88,
+	0x40, 0x4e, 0x59, 0x7f, 0xb7, 0x1f, 0xa4, 0xa7, 0xe3, 0xe3, 0xcd, 0x5e, 0x34, 0xdc, 0xea, 0x47,
+	0xfd, 0x68, 0x8b, 0xb1, 0x1c, 0x8f, 0x4f, 0xd8, 0x88, 0x0d, 0xd8, 0x17, 0x17, 0x5d, 0xaf, 0x0d,
+	0x69, 0xea, 0xf9, 0x5e, 0xea, 0xf1, 0xb1, 0xf5, 0x09, 0x94, 0x9b, 0x8e, 0x13, 0xf9, 0x94, 0x10,
+	0x28, 0x1d, 0x1e, 0xb6, 0xed, 0xba, 0x71, 0xc7, 0xb8, 0xb7, 0xe8, 0xb2, 0x6f, 0x72, 0x17, 0x6a,
+	0x1d, 0xbe, 0x4e, 0xc3, 0xf7, 0x63, 0x9a, 0x24, 0xf5, 0x02, 0x9b, 0x9d, 0xa0, 0xa2, 0x6c, 0x37,
+	0xe8, 0x9d, 0xd5, 0x8b, 0x77, 0x8c, 0x7b, 0x25, 0x97, 0x7d, 0xa3, 0x66, 0xfb, 0xbb, 0xd1, 0xfc,
+	0x1f, 0x03, 0x96, 0xf6, 0xa3, 0x7e, 0xe7, 0xd4, 0x8b, 0xfd, 0x76, 0x78, 0x12, 0x91, 0x3a, 0x2c,
+	0xf0, 0x01, 0x5f, 0xa3, 0xe4, 0xca, 0x21, 0xd9, 0x85, 0x8a, 0x4b, 0x47, 0x83, 0xa0, 0xe7, 0xe1,
+	0x02, 0xc5, 0x7b, 0xd5, 0xed, 0xbb, 0x9b, 0x8a, 0x3b, 0x55, 0x2d, 0x9b, 0x92, 0xb1, 0x15, 0xa6,
+	0xf1, 0x85, 0x9b, 0xc9, 0x91, 0xeb, 0x30, 0xdf, 0x1a, 0x45, 0xbd, 0x53, 0x61, 0x03, 0x1f, 0x90,
+	0x75, 0xa8, 0xec, 0x53, 0xcf, 0xa7, 0x71, 0xdb, 0xae, 0x97, 0xd8, 0x44, 0x36, 0x66, 0x46, 0xd3,
+	0x78, 0x58, 0x9f, 0x17, 0x46, 0xd3, 0x78, 0xb8, 0xfe, 0x73, 0x58, 0xd6, 0x16, 0x20, 0x26, 0x14,
+	0xcf, 0xe8, 0x85, 0x30, 0x18, 0x3f, 0x71, 0xa1, 0x73, 0x6f, 0x30, 0xa6, 0xc2, 0x15, 0x7c, 0xf0,
+	0xb3, 0xc2, 0x4f, 0x0d, 0xeb, 0x1c, 0x6a, 0xfb, 0x51, 0x5f, 0xc8, 0xb3, 0x2d, 0x7f, 0xa4, 0xbb,
+	0x80, 0xa9, 0xa9, 0x6e, 0xd7, 0x2f, 0xdb, 0xdc, 0x6e, 0xe5, 0xab, 0xaf, 0x6f, 0xcf, 0x3d, 0xfb,
+	0xfa, 0xb6, 0xe1, 0xea, 0xae, 0x7b, 0x0b, 0x16, 0xa5, 0x5a, 0x9b, 0xad, 0x5b, 0x72, 0x73, 0x82,
+	0xe5, 0x80, 0xd9, 0x74, 0x3a, 0x69, 0x14, 0xd3, 0x3d, 0xea, 0xc5, 0xe9, 0x31, 0xf5, 0xd2, 0xff,
+	0x25, 0x9a, 0xd6, 0x3f, 0x0d, 0x58, 0xc1, 0xe5, 0x5f, 0xac, 0xf1, 0x0e, 0x54, 0x5d, 0xef, 0x24,
+	0xd5, 0xd5, 0xa9, 0xa4, 0x19, 0x6b, 0x16, 0x67, 0x22, 0xe8, 0x6d, 0x58, 0x7e, 0x18, 0x25, 0x49,
+	0x30, 0x92, 0x6c, 0x25, 0xc6, 0xa6, 0x13, 0xc9, 0x8e, 0x02, 0x94, 0x79, 0x06, 0x94, 0xf5, 0x09,
+	0x5f, 0x2a, 0xde, 0xdf, 0x2d, 0xa1, 0x37, 0x73, 0x88, 0x58, 0x2d, 0xa8, 0xda, 0xce, 0xcb, 0xe0,
+	0xf1, 0x6a, 0x77, 0x7f, 0x6e, 0x80, 0x69, 0xbf, 0x46, 0x7f, 0x93, 0xf7, 0xa0, 0xcc, 0x56, 0x46,
+	0xdf, 0xe0, 0x9e, 0x6e, 0xaa, 0x7b, 0x52, 0x2c, 0x16, 0x1b, 0x12, 0xcc, 0xd6, 0x1f, 0x0b, 0x50,
+	0x71, 0x3b, 0x8f, 0x3b, 0xa9, 0x97, 0x52, 0xc4, 0x69, 0x37, 0x89, 0x24, 0x4e, 0xbb, 0x49, 0x84,
+	0x38, 0x6d, 0x87, 0x3e, 0x7d, 0x2a, 0x36, 0xc0, 0x07, 0xe8, 0xe7, 0x7d, 0xea, 0x25, 0x74, 0x2f,
+	0x1a, 0xf0, 0xac, 0xe0, 0xe9, 0xa2, 0x13, 0x89, 0x05, 0x4b, 0xdd, 0x78, 0x1c, 0xf6, 0xbc, 0x94,
+	0xfa, 0xfb, 0x49, 0x28, 0x52, 0x47, 0xa3, 0x91, 0x8f, 0x61, 0x89, 0x0b, 0x05, 0x49, 0x1a, 0xc5,
+	0x17, 0x22, 0x1e, 0x5a, 0xe2, 0x4a, 0xeb, 0x36, 0x55, 0x46, 0x9e, 0xb8, 0x9a, 0xec, 0xfa, 0x03,
+	0x58, 0x99, 0x62, 0x79, 0x51, 0xea, 0x95, 0xd4, 0xd4, 0xfb, 0x14, 0x16, 0x59, 0xf0, 0x7b, 0x51,
+	0xec, 0xa3, 0x20, 0x1a, 0x2d, 0x04, 0xd1, 0xd6, 0x0d, 0x28, 0x75, 0x2f, 0x46, 0x5c, 0xae, 0xb6,
+	0x7d, 0x43, 0xb3, 0x91, 0xc9, 0xe0, 0xac, 0xcb, 0x78, 0x30, 0x92, 0xb6, 0x97, 0x7a, 0xcc, 0x31,
+	0x4b, 0x2e, 0xfb, 0xb6, 0xbe, 0x30, 0x00, 0x98, 0xfe, 0xdf, 0x8c, 0x69, 0xc2, 0x82, 0xed, 0x78,
+	0x43, 0x2a, 0x83, 0x8d, 0xdf, 0x2a, 0x9a, 0x0a, 0x3a, 0x9a, 0x84, 0x39, 0xc5, 0xdc, 0x9c, 0x3a,
+	0x2c, 0x3c, 0xf6, 0x9e, 0x76, 0x82, 0xcf, 0xa8, 0xf0, 0xac, 0x1c, 0x22, 0xf2, 0x64, 0xc0, 0x6d,
+	0x51, 0x98, 0x72, 0x02, 0x33, 0xcd, 0x69, 0xdb, 0xf5, 0x32, 0xaf, 0x58, 0xf8, 0x6d, 0x59, 0x00,
+	0xdd, 0x24, 0x92, 0x96, 0x5d, 0x87, 0xf9, 0x66, 0x34, 0x0e, 0x53, 0xb1, 0x79, 0x3e, 0xb0, 0xfe,
+	0x56, 0x84, 0x05, 0xc9, 0xc1, 0xb0, 0xcd, 0x3e, 0x33, 0xdc, 0xe7, 0x04, 0xb2, 0x09, 0xe5, 0xc7,
+	0x34, 0x3d, 0x8d, 0xfc, 0x59, 0xae, 0xe2, 0x33, 0xcc, 0x55, 0x82, 0x0b, 0x77, 0xd2, 0x0d, 0x86,
+	0x34, 0x1a, 0xa7, 0x6c, 0x7f, 0x45, 0x57, 0x0e, 0xc9, 0x8e, 0xea, 0x31, 0xb6, 0xcd, 0xaa, 0xae,
+	0x2d, 0x9f, 0x15, 0xb8, 0x56, 0x3d, 0xfc, 0x90, 0x15, 0xce, 0x2c, 0xbd, 0x98, 0x2b, 0xaa, 0xdb,
+	0xdf, 0x9b, 0x2c, 0x9c, 0x5a, 0x0e, 0x0a, 0x35, 0x9a, 0x20, 0xb1, 0xa1, 0xda, 0x74, 0x72, 0x3d,
+	0x65, 0xa6, 0xe7, 0x2d, 0x55, 0xcf, 0x64, 0xe9, 0x14, 0x6a, 0x54, 0x31, 0xd4, 0x62, 0x2b, 0x5a,
+	0x16, 0xa6, 0xb5, 0xd8, 0x97, 0x68, 0x51, 0xc4, 0xd0, 0x25, 0x79, 0xa8, 0xea, 0x95, 0x69, 0x97,
+	0xe4, 0xb3, 0xd2, 0x25, 0x39, 0xc5, 0xea, 0x40, 0x95, 0x39, 0x28, 0x19, 0x45, 0x61, 0x42, 0xaf,
+	0xa8, 0x5e, 0x02, 0x6f, 0x05, 0x0d, 0x6f, 0xfb, 0x5e, 0x92, 0xe6, 0x28, 0x94, 0x43, 0xeb, 0x9b,
+	0x22, 0x56, 0x54, 0xa1, 0xf2, 0xf5, 0x42, 0xe3, 0x3e, 0x2c, 0xb6, 0xe2, 0x38, 0x8a, 0x9b, 0x91,
+	0x4f, 0xd9, 0xb2, 0xb5, 0xed, 0x35, 0x55, 0x24, 0x9b, 0x74, 0x73, 0x3e, 0x2c, 0x3c, 0x6c, 0xf0,
+	0x98, 0x26, 0x89, 0xd7, 0xa7, 0xa2, 0x0b, 0x68, 0x34, 0x72, 0x0b, 0xa0, 0x9d, 0xec, 0x35, 0x1e,
+	0x51, 0x3a, 0xa2, 0x31, 0x43, 0x46, 0xc5, 0x55, 0x28, 0xe4, 0x81, 0xe6, 0x28, 0x11, 0xf2, 0x9b,
+	0x53, 0xd0, 0xe3, 0xd3, 0x32, 0x4e, 0xaa, 0x6b, 0x77, 0x61, 0xa9, 0x19, 0x0d, 0x87, 0x5e, 0xe8,
+	0xef, 0x7a, 0x69, 0xef, 0x54, 0x84, 0x5b, 0xeb, 0xda, 0xea, 0xbc, 0xc4, 0x9d, 0x4a, 0x43, 0x23,
+	0x58, 0xec, 0x84, 0x11, 0x95, 0x69, 0x23, 0x94, 0x69, 0x69, 0x84, 0x42, 0x22, 0x7b, 0x50, 0x6b,
+	0x0e, 0xc6, 0x49, 0x4a, 0x63, 0x9b, 0xa6, 0x5e, 0x30, 0x48, 0xea, 0x8b, 0x4c, 0x87, 0xd6, 0xf0,
+	0x74, 0x0e, 0xa1, 0x66, 0x42, 0xce, 0xfa, 0x98, 0x75, 0x73, 0x5e, 0xe7, 0x32, 0xf5, 0xef, 0x61,
+	0x45, 0x40, 0x4a, 0x52, 0x37, 0x58, 0xe1, 0x5e, 0x9b, 0x72, 0x10, 0xce, 0x0a, 0x95, 0x92, 0xd7,
+	0xfa, 0x81, 0xb6, 0x2d, 0x2c, 0x37, 0xbf, 0x60, 0x05, 0x59, 0x94, 0x1b, 0x36, 0xb0, 0xce, 0x50,
+	0x37, 0xeb, 0x96, 0x33, 0xdb, 0xe2, 0xe5, 0x95, 0x52, 0xeb, 0xbb, 0xc5, 0x89, 0xbe, 0x9b, 0x9f,
+	0xf0, 0x4a, 0xca, 0x09, 0xcf, 0xfa, 0x73, 0x01, 0xa3, 0x15, 0x9e, 0x04, 0xfd, 0xe6, 0xa9, 0x17,
+	0xf6, 0x29, 0xb9, 0x9f, 0xad, 0x2e, 0x8e, 0x5b, 0xab, 0x7a, 0xb9, 0x67, 0x53, 0xf9, 0xbe, 0xb8,
+	0x9d, 0x3b, 0x00, 0x5c, 0x5c, 0x69, 0x13, 0x7a, 0x95, 0x50, 0x96, 0x60, 0x30, 0x57, 0xf8, 0x49,
+	0x17, 0x6a, 0xed, 0x30, 0x48, 0x03, 0x6f, 0xf0, 0x98, 0x0e, 0x8f, 0x69, 0x2c, 0x1b, 0xf9, 0x3b,
+	0x97, 0x69, 0xd8, 0xd4, 0xd9, 0x79, 0x4b, 0x9c, 0xd0, 0xb1, 0xde, 0x80, 0xd5, 0x19, 0x6c, 0xaf,
+	0x74, 0x22, 0xfd, 0x11, 0x2c, 0x77, 0x4e, 0xc7, 0xa9, 0x1f, 0xfd, 0x36, 0x64, 0xe5, 0x89, 0xf9,
+	0x1e, 0x3f, 0xb2, 0x90, 0xc8, 0xa1, 0xf5, 0x79, 0x01, 0xae, 0x75, 0x7a, 0xa7, 0xd4, 0x1f, 0x0f,
+	0xa8, 0x40, 0xf2, 0xcc, 0xe8, 0xbd, 0x0d, 0xcb, 0xbb, 0x51, 0x94, 0x26, 0x69, 0xec, 0x8d, 0x46,
+	0x41, 0xd8, 0x67, 0x8b, 0x56, 0x5c, 0x9d, 0x48, 0x76, 0xf4, 0xa0, 0xb0, 0x60, 0x4e, 0xa5, 0x50,
+	0x3e, 0xef, 0xea, 0x21, 0x7c, 0x1f, 0xaa, 0xe2, 0x88, 0xc4, 0xc2, 0x51, 0x62, 0xe1, 0xd0, 0x92,
+	0x47, 0x99, 0x76, 0x55, 0x5e, 0xf2, 0x60, 0x62, 0xc7, 0xa2, 0x73, 0xbc, 0xa1, 0x09, 0xab, 0x0c,
+	0xae, 0xce, 0x6f, 0x79, 0x7a, 0xf2, 0x67, 0xb7, 0x04, 0x23, 0xbf, 0x25, 0x90, 0x0f, 0xa0, 0x22,
+	0x78, 0xe4, 0x7d, 0xe5, 0x4d, 0x4d, 0xbf, 0xee, 0x46, 0x79, 0x0e, 0x95, 0x22, 0x56, 0x1b, 0x7b,
+	0x12, 0xf7, 0x3b, 0x9e, 0x43, 0xe5, 0xe5, 0xc9, 0xc8, 0x2f, 0x4f, 0x2f, 0x7d, 0x54, 0xff, 0x8b,
+	0x01, 0x0b, 0xa8, 0x0b, 0x8f, 0x80, 0x1f, 0x40, 0x99, 0x29, 0x95, 0x19, 0x7d, 0x7b, 0xb2, 0xcb,
+	0xe1, 0x49, 0x8c, 0x73, 0x30, 0x24, 0x65, 0xc7, 0x49, 0x46, 0x5a, 0x77, 0xa1, 0xaa, 0x4c, 0xaa,
+	0x30, 0x5b, 0xe4, 0x30, 0x7b, 0x57, 0x85, 0xd9, 0x44, 0x31, 0x53, 0xf6, 0xa3, 0xe2, 0xef, 0x77,
+	0x06, 0x3b, 0x72, 0xbf, 0x8e, 0xad, 0x7e, 0xdb, 0x53, 0x32, 0x7a, 0xc8, 0x7e, 0x19, 0x0f, 0xd9,
+	0xdf, 0xad, 0x87, 0xec, 0xd9, 0x1e, 0x7a, 0x3a, 0x59, 0xe6, 0xc9, 0x36, 0xda, 0x8b, 0x37, 0x72,
+	0x69, 0x25, 0xd1, 0xd5, 0xe0, 0x94, 0x2c, 0x5f, 0x82, 0x11, 0x65, 0x9a, 0x42, 0xa6, 0x30, 0x2d,
+	0xd3, 0xd4, 0x64, 0x04, 0xa3, 0xf5, 0x07, 0x03, 0xaa, 0x62, 0x69, 0x16, 0x9b, 0xf7, 0xa1, 0x22,
+	0xbc, 0x28, 0x17, 0xbe, 0xb9, 0x99, 0x3d, 0x43, 0x88, 0x19, 0xad, 0x29, 0x64, 0xec, 0x64, 0x87,
+	0x9d, 0xbe, 0x85, 0x2c, 0x37, 0xa0, 0x9e, 0xcb, 0xca, 0x29, 0x4d, 0x38, 0x17, 0xb0, 0xfe, 0x64,
+	0xc0, 0x9a, 0x28, 0x74, 0xc2, 0x1e, 0x79, 0x0a, 0xbc, 0x0b, 0x35, 0x67, 0x3c, 0x3c, 0x38, 0xc9,
+	0x95, 0x73, 0xe0, 0x4c, 0x50, 0xb1, 0x26, 0x31, 0x4a, 0x66, 0x3f, 0xef, 0x2b, 0x3a, 0x91, 0x6c,
+	0x80, 0x29, 0xe5, 0xb2, 0x4b, 0x24, 0x6f, 0x32, 0x53, 0x74, 0xeb, 0x99, 0x78, 0xbc, 0xb8, 0x12,
+	0xb9, 0xff, 0x5f, 0xb7, 0xdf, 0x2f, 0x0b, 0x50, 0x61, 0x5b, 0xc2, 0x4c, 0xf8, 0x30, 0x4b, 0x26,
+	0x1e, 0xea, 0x3b, 0x53, 0x27, 0x6b, 0x96, 0x0a, 0x8c, 0x45, 0x4f, 0x05, 0xee, 0xcb, 0x0f, 0xb3,
+	0x4c, 0x2a, 0x5c, 0x25, 0x7f, 0x69, 0x2a, 0x75, 0xa0, 0xaa, 0x28, 0x9f, 0xd1, 0xd3, 0x36, 0xf5,
+	0x54, 0xba, 0xf4, 0xc9, 0x44, 0xc9, 0x25, 0xa6, 0xf4, 0xca, 0xfc, 0x7c, 0x91, 0xd2, 0x59, 0x09,
+	0xfa, 0x7b, 0x3c, 0x5f, 0x9c, 0xd2, 0xde, 0x19, 0x8d, 0xb9, 0xeb, 0x66, 0x21, 0xe1, 0x81, 0x96,
+	0x4a, 0x33, 0x0b, 0x64, 0x3e, 0x9d, 0x5d, 0x30, 0x94, 0xe4, 0xbb, 0x9f, 0x15, 0x29, 0xd1, 0x2a,
+	0x57, 0x67, 0x94, 0xa6, 0x3c, 0xeb, 0xb9, 0x25, 0x3f, 0xc9, 0x03, 0x2a, 0x2e, 0x58, 0xd7, 0x67,
+	0x85, 0x41, 0x22, 0x21, 0x0b, 0xfe, 0x16, 0xcc, 0x73, 0xa1, 0x79, 0xd6, 0x58, 0xb5, 0xde, 0x28,
+	0x4f, 0xd1, 0x8c, 0xc1, 0xe5, 0x7c, 0xd6, 0x97, 0xf3, 0x60, 0xca, 0x89, 0xec, 0xc5, 0x61, 0x96,
+	0x1f, 0x6e, 0x40, 0xd9, 0xa1, 0x4f, 0xd3, 0xec, 0x64, 0x27, 0x46, 0x59, 0x13, 0x2d, 0x2a, 0x4d,
+	0x34, 0xb3, 0xa2, 0xf4, 0x72, 0x56, 0x10, 0x1f, 0xcc, 0x89, 0xce, 0x2a, 0xd3, 0x60, 0x7b, 0x96,
+	0x6c, 0xf6, 0xf8, 0x30, 0x29, 0xa4, 0xe2, 0x71, 0x4a, 0x23, 0x69, 0xab, 0xb5, 0xac, 0xcc, 0xd4,
+	0xff, 0xf8, 0x4a, 0xf5, 0x19, 0x37, 0x3f, 0xc5, 0xe5, 0xd2, 0x18, 0x54, 0xd1, 0x76, 0xc5, 0x15,
+	0x62, 0x75, 0x46, 0x47, 0xce, 0xcb, 0x32, 0xdf, 0xa5, 0x82, 0x84, 0xca, 0xb7, 0x42, 0xc2, 0xe2,
+	0x2b, 0x20, 0x61, 0x02, 0xb7, 0xf0, 0xaa, 0xb8, 0x5d, 0xff, 0x14, 0xd6, 0x66, 0xba, 0xf7, 0x15,
+	0x93, 0x4f, 0x3d, 0x71, 0xa9, 0x19, 0xbd, 0xc3, 0x5e, 0x54, 0x2f, 0xa9, 0x14, 0x8b, 0x2f, 0x78,
+	0x14, 0xda, 0xf8, 0x15, 0xc0, 0xe1, 0xc8, 0xf7, 0x52, 0x7e, 0x32, 0xbc, 0x09, 0xab, 0xda, 0x23,
+	0x17, 0x9f, 0x32, 0xe7, 0xc8, 0x1a, 0xac, 0xc8, 0x87, 0xad, 0xfd, 0x8e, 0x23, 0xc8, 0x06, 0x59,
+	0x85, 0x6b, 0x87, 0x09, 0x8d, 0xd9, 0xb2, 0x82, 0x58, 0x20, 0xcb, 0xb0, 0xd8, 0xed, 0x1c, 0x88,
+	0x61, 0x71, 0xe3, 0x1f, 0x06, 0x40, 0x7e, 0xf5, 0x25, 0x35, 0x80, 0x6e, 0xe7, 0xe0, 0xe8, 0xf0,
+	0x89, 0xdd, 0xe8, 0xb6, 0xcc, 0x39, 0x02, 0x50, 0x6e, 0x3c, 0x79, 0xd2, 0x72, 0x6c, 0xd3, 0x20,
+	0x15, 0x28, 0xb9, 0xad, 0x86, 0x6d, 0x16, 0xc8, 0x12, 0x54, 0xba, 0xee, 0xa1, 0xd3, 0x44, 0x9e,
+	0x22, 0x31, 0x61, 0xe9, 0x61, 0xab, 0x7b, 0x94, 0x51, 0x4a, 0xa4, 0x0a, 0x0b, 0xcd, 0x03, 0xc7,
+	0x69, 0x35, 0xbb, 0xe6, 0x3c, 0xaa, 0x14, 0x83, 0x23, 0xf7, 0xc0, 0x2c, 0x93, 0x15, 0x58, 0xde,
+	0x3f, 0x78, 0x78, 0xb4, 0xd7, 0x6a, 0xb8, 0xdd, 0xdd, 0x56, 0xa3, 0x6b, 0x2e, 0xa0, 0x86, 0xa6,
+	0xa3, 0x50, 0x2a, 0x48, 0xb1, 0x55, 0xca, 0x22, 0x21, 0x50, 0x6b, 0xee, 0xb5, 0x9a, 0x8f, 0x8e,
+	0xf6, 0x1a, 0x8f, 0x5a, 0xad, 0x27, 0x2d, 0xd7, 0x04, 0x74, 0x08, 0xae, 0xdc, 0xdc, 0x3f, 0xec,
+	0x74, 0x5b, 0xee, 0x91, 0xdd, 0xea, 0x36, 0xda, 0xfb, 0x1d, 0xb3, 0xba, 0xe1, 0x00, 0xe4, 0xaf,
+	0x62, 0x68, 0x01, 0xfa, 0x81, 0x53, 0xcc, 0x39, 0x34, 0xbf, 0x1d, 0xa6, 0x34, 0x0e, 0xbd, 0x81,
+	0x69, 0x90, 0x6b, 0x50, 0x65, 0x5e, 0xcd, 0x3c, 0xb4, 0x22, 0x1e, 0x18, 0x5d, 0xfa, 0x6b, 0xda,
+	0x4b, 0xa9, 0x6f, 0x16, 0x37, 0xfe, 0x5a, 0x50, 0x9e, 0x02, 0x70, 0x7b, 0x4e, 0xc4, 0x86, 0xe6,
+	0x1c, 0x0e, 0xc4, 0x83, 0x91, 0x69, 0xa0, 0xe6, 0xa6, 0x17, 0xf6, 0xe8, 0x80, 0xfa, 0x66, 0x01,
+	0x37, 0xd1, 0x0e, 0xcf, 0xbd, 0x41, 0xe0, 0xb3, 0xf8, 0x9b, 0x45, 0xdc, 0x84, 0xa0, 0x48, 0x99,
+	0x92, 0x42, 0x7b, 0xe2, 0x5d, 0x0c, 0x22, 0xcf, 0x37, 0xe7, 0xc9, 0x0d, 0x20, 0x3a, 0xad, 0x13,
+	0x7c, 0x46, 0xcd, 0x32, 0xea, 0xcf, 0xac, 0x5a, 0x40, 0x43, 0x99, 0x62, 0x27, 0x4a, 0x5d, 0xea,
+	0xf9, 0x17, 0xdc, 0x6f, 0x9d, 0x8b, 0x24, 0xa5, 0xc3, 0xe6, 0x20, 0x4a, 0xa8, 0x6f, 0x2e, 0x32,
+	0xd0, 0x24, 0x61, 0x63, 0x10, 0x23, 0x47, 0xf6, 0xfc, 0x69, 0xfa, 0xe8, 0x95, 0x83, 0x71, 0x7a,
+	0x70, 0xe2, 0xe2, 0x85, 0xc5, 0xc4, 0x6a, 0x58, 0x73, 0xa2, 0x54, 0x01, 0x98, 0x79, 0x82, 0xbe,
+	0x71, 0xa2, 0x54, 0x16, 0x0c, 0xb3, 0x4f, 0xd6, 0xc0, 0x3c, 0x48, 0x4f, 0x69, 0xcc, 0x17, 0xe1,
+	0x3e, 0xf8, 0xf7, 0xc2, 0xc6, 0xdf, 0x0d, 0x20, 0x92, 0x4b, 0x01, 0x2c, 0xa2, 0x29, 0xe8, 0x9d,
+	0xa9, 0x38, 0x55, 0xde, 0xa4, 0x32, 0x9c, 0xae, 0xc1, 0x8a, 0x3d, 0x45, 0x2e, 0xa0, 0x13, 0xd4,
+	0x87, 0x30, 0x09, 0x59, 0x34, 0xea, 0x21, 0x4d, 0x33, 0xf8, 0x97, 0xc8, 0x1b, 0x53, 0x29, 0x2c,
+	0xa6, 0xe6, 0x71, 0x53, 0x1d, 0x9a, 0xb2, 0x52, 0x21, 0x68, 0x65, 0x52, 0x87, 0xeb, 0xfa, 0x61,
+	0x4d, 0xcc, 0x2c, 0x6c, 0x7c, 0x61, 0xc0, 0xb2, 0x56, 0xb8, 0x31, 0x85, 0x24, 0xa1, 0x19, 0x53,
+	0xe6, 0xb9, 0x39, 0x5c, 0x4f, 0x12, 0xb5, 0x3b, 0xa3, 0x69, 0x90, 0x1f, 0xc2, 0xf7, 0xa7, 0xa6,
+	0x64, 0x59, 0x71, 0x69, 0x8f, 0x06, 0xe7, 0x0c, 0x19, 0x6f, 0xc2, 0xcd, 0x29, 0xb6, 0x8f, 0xbc,
+	0x00, 0x61, 0x53, 0x54, 0xd7, 0x74, 0xc7, 0x61, 0x88, 0x8a, 0x4b, 0x1b, 0x9f, 0x80, 0x39, 0x79,
+	0x81, 0x47, 0xf7, 0x36, 0x7c, 0x5f, 0x1c, 0x8f, 0xcc, 0x39, 0xc4, 0x83, 0x4b, 0x87, 0xd1, 0x39,
+	0x95, 0x24, 0x83, 0xe1, 0x21, 0xf5, 0xe2, 0x54, 0x52, 0x0a, 0xe8, 0xbd, 0x4e, 0x1a, 0x8d, 0x24,
+	0xa1, 0xb8, 0xf1, 0x8e, 0x76, 0x55, 0x45, 0xa5, 0x58, 0xb0, 0x38, 0xc5, 0x9c, 0xc3, 0x7a, 0x61,
+	0x87, 0x72, 0x68, 0xec, 0xb6, 0x9e, 0x7d, 0x73, 0x6b, 0xee, 0xab, 0xe7, 0xb7, 0x8c, 0x67, 0xcf,
+	0x6f, 0x19, 0xff, 0x7a, 0x7e, 0xcb, 0xf8, 0xe5, 0x7d, 0xe5, 0xc7, 0xe0, 0xd0, 0x4b, 0xe3, 0xe0,
+	0x69, 0x14, 0x07, 0xfd, 0x20, 0x94, 0x83, 0x90, 0x6e, 0x8d, 0xce, 0xfa, 0x5b, 0xa3, 0xe3, 0xad,
+	0xbc, 0x5c, 0x1e, 0x97, 0xd9, 0x5f, 0xc1, 0xfb, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x71, 0x23,
+	0x25, 0xbd, 0x74, 0x1c, 0x00, 0x00,
 }
 
 func (m *CNNode) Marshal() (dAtA []byte, err error) {
diff --git a/pkg/pb/plan/plan.pb.go b/pkg/pb/plan/plan.pb.go
index 44b4a3918..02290f59e 100644
--- a/pkg/pb/plan/plan.pb.go
+++ b/pkg/pb/plan/plan.pb.go
@@ -896,6 +896,7 @@ func (m *Type) GetScale() int32 {
 type Const struct {
 	Isnull bool `protobuf:"varint,1,opt,name=isnull,proto3" json:"isnull,omitempty"`
 	// Types that are valid to be assigned to Value:
+	//
 	//	*Const_Ival
 	//	*Const_Dval
 	//	*Const_Sval
@@ -1660,6 +1661,7 @@ func (m *Function) GetArgs() []*Expr {
 type Expr struct {
 	Typ *Type `protobuf:"bytes,1,opt,name=typ,proto3" json:"typ,omitempty"`
 	// Types that are valid to be assigned to Expr:
+	//
 	//	*Expr_C
 	//	*Expr_P
 	//	*Expr_V
@@ -1909,6 +1911,7 @@ func (m *DefaultExpr) GetIsNull() bool {
 
 type ConstantValue struct {
 	// Types that are valid to be assigned to ConstantValue:
+	//
 	//	*ConstantValue_UnknownV
 	//	*ConstantValue_Int64V
 	//	*ConstantValue_Decimal64V
@@ -2544,6 +2547,7 @@ func (m *TableDef) GetDefs() []*TableDef_DefType {
 
 type TableDef_DefType struct {
 	// Types that are valid to be assigned to Def:
+	//
 	//	*TableDef_DefType_Pk
 	//	*TableDef_DefType_Idx
 	//	*TableDef_DefType_Properties
@@ -3473,9 +3477,10 @@ func (m *Query) GetHeadings() []string {
 }
 
 type TransationControl struct {
-	//TransationControl type
+	// TransationControl type
 	TclType TransationControl_TclType `protobuf:"varint,1,opt,name=tcl_type,json=tclType,proto3,enum=plan.TransationControl_TclType" json:"tcl_type,omitempty"`
 	// Types that are valid to be assigned to Action:
+	//
 	//	*TransationControl_Begin
 	//	*TransationControl_Commit
 	//	*TransationControl_Rollback
@@ -3725,6 +3730,7 @@ func (m *TransationRollback) GetCompletionType() TransationCompletionType {
 
 type Plan struct {
 	// Types that are valid to be assigned to Plan:
+	//
 	//	*Plan_Query
 	//	*Plan_Tcl
 	//	*Plan_Ddl
@@ -3838,9 +3844,10 @@ func (*Plan) XXX_OneofWrappers() []interface{} {
 }
 
 type DataControl struct {
-	//DataDefinition type
+	// DataDefinition type
 	DclType DataControl_DclType `protobuf:"varint,1,opt,name=dcl_type,json=dclType,proto3,enum=plan.DataControl_DclType" json:"dcl_type,omitempty"`
 	// Types that are valid to be assigned to Control:
+	//
 	//	*DataControl_SetVariables
 	//	*DataControl_Prepare
 	//	*DataControl_Execute
@@ -3961,13 +3968,14 @@ func (*DataControl) XXX_OneofWrappers() []interface{} {
 }
 
 type DataDefinition struct {
-	//DataDefinition type
+	// DataDefinition type
 	DdlType DataDefinition_DdlType `protobuf:"varint,1,opt,name=ddl_type,json=ddlType,proto3,enum=plan.DataDefinition_DdlType" json:"ddl_type,omitempty"`
-	//other show statement we will rewrite to a select statement
-	//then we will get a Query
-	//eg: 'show databases' will rewrite to 'select md.datname as `Database` from mo_database md'
+	// other show statement we will rewrite to a select statement
+	// then we will get a Query
+	// eg: 'show databases' will rewrite to 'select md.datname as `Database` from mo_database md'
 	Query *Query `protobuf:"bytes,2,opt,name=query,proto3" json:"query,omitempty"`
 	// Types that are valid to be assigned to Definition:
+	//
 	//	*DataDefinition_CreateDatabase
 	//	*DataDefinition_AlterDatabase
 	//	*DataDefinition_DropDatabase
diff --git a/pkg/pb/txn/txn.pb.go b/pkg/pb/txn/txn.pb.go
index 5f735eca7..7b358d91c 100644
--- a/pkg/pb/txn/txn.pb.go
+++ b/pkg/pb/txn/txn.pb.go
@@ -522,9 +522,9 @@ func (m *CNOpResponse) GetPayload() []byte {
 // to TxnMethod.
 //
 // Request flow of TxnRequest as below:
-// 1. CN -> DN (TxnMethod.Read, TxnMethod.Write, TxnMethod.Commit, TxnMethod.Rollback)
-// 2. DN -> DN (TxnMethod.Prepare, TxnMethod.GetStatus, TxnMethod.CommitDNShard, TxnMethod.RollbackDNShard,
-//             TxnMethod.RemoveMetadata)
+//  1. CN -> DN (TxnMethod.Read, TxnMethod.Write, TxnMethod.Commit, TxnMethod.Rollback)
+//  2. DN -> DN (TxnMethod.Prepare, TxnMethod.GetStatus, TxnMethod.CommitDNShard, TxnMethod.RollbackDNShard,
+//     TxnMethod.RemoveMetadata)
 type TxnRequest struct {
 	// RequestID request id
 	RequestID uint64 `protobuf:"varint,1,opt,name=RequestID,proto3" json:"RequestID,omitempty"`
diff --git a/pkg/util/toml/types.go b/pkg/util/toml/types.go
new file mode 100644
index 000000000..4b83715ef
--- /dev/null
+++ b/pkg/util/toml/types.go
@@ -0,0 +1,51 @@
+// Copyright 2021 - 2022 Matrix Origin
+//
+// 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.
+
+package toml
+
+import (
+	"time"
+
+	"github.com/docker/go-units"
+)
+
+// Duration is a wrapper of time.Duration for TOML
+type Duration struct {
+	time.Duration
+}
+
+// UnmarshalText parses a TOML string into the duration.
+func (d *Duration) UnmarshalText(text []byte) error {
+	var err error
+	d.Duration, err = time.ParseDuration(string(text))
+	return err
+}
+
+// MarshalText returns the duration as a JSON string.
+func (d Duration) MarshalText() ([]byte, error) {
+	return []byte(d.String()), nil
+}
+
+// ByteSize is a retype uint64 for TOML.
+type ByteSize uint64
+
+// UnmarshalText parses a Toml string into the byte size.
+func (b *ByteSize) UnmarshalText(text []byte) error {
+	v, err := units.RAMInBytes(string(text))
+	if err != nil {
+		return err
+	}
+	*b = ByteSize(v)
+	return nil
+}
diff --git a/pkg/vm/engine/tae/dataio/segmentio/log.go b/pkg/vm/engine/tae/dataio/segmentio/log.go
index 84f496d56..b6fc9a733 100644
--- a/pkg/vm/engine/tae/dataio/segmentio/log.go
+++ b/pkg/vm/engine/tae/dataio/segmentio/log.go
@@ -119,6 +119,10 @@ func (l *Log) readInode(cache *bytes.Buffer, file *DriverFile) (n int, err error
 
 func (l *Log) Replay(cache *bytes.Buffer) error {
 	var off int64 = LOG_START
+	stat, err := l.logFile.driver.logFile.Stat()
+	if err != nil {
+		return err
+	}
 	for {
 		pos, hole, err := l.replayData(cache, off)
 		if err != nil {
@@ -127,7 +131,7 @@ func (l *Log) Replay(cache *bytes.Buffer) error {
 			}
 			return err
 		}
-		if off >= LOG_SIZE || hole >= HOLE_SIZE {
+		if off >= LOG_SIZE || off >= stat.Size() || hole >= HOLE_SIZE {
 			return nil
 		}
 		off += int64(pos)
diff --git a/pkg/vm/engine/tae/iface/data/block.go b/pkg/vm/engine/tae/iface/data/block.go
index c9845c0af..361ffea43 100644
--- a/pkg/vm/engine/tae/iface/data/block.go
+++ b/pkg/vm/engine/tae/iface/data/block.go
@@ -39,11 +39,12 @@ type CheckpointUnit interface {
 type BlockAppender interface {
 	GetID() *common.ID
 	GetMeta() any
-	PrepareAppend(rows uint32) (n uint32, err error)
+	PrepareAppend(rows uint32,
+		txn txnif.AsyncTxn) (
+		node txnif.AppendNode, created bool, n uint32, err error)
 	ApplyAppend(bat *containers.Batch,
 		txn txnif.AsyncTxn,
-		anode txnif.AppendNode,
-	) (txnif.AppendNode, int, error)
+	) (int, error)
 	IsAppendable() bool
 	ReplayAppend(bat *containers.Batch) error
 }
diff --git a/pkg/vm/engine/tae/tables/appender.go b/pkg/vm/engine/tae/tables/appender.go
index c4a770f5f..84057ccf3 100644
--- a/pkg/vm/engine/tae/tables/appender.go
+++ b/pkg/vm/engine/tae/tables/appender.go
@@ -20,7 +20,6 @@ import (
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/index"
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model"
-	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tables/updates"
 )
 
 type blockAppender struct {
@@ -48,7 +47,9 @@ func (appender *blockAppender) IsAppendable() bool {
 	return appender.rows+appender.placeholder < appender.node.block.meta.GetSchema().BlockMaxRows
 }
 
-func (appender *blockAppender) PrepareAppend(rows uint32) (n uint32, err error) {
+func (appender *blockAppender) PrepareAppend(
+	rows uint32,
+	txn txnif.AsyncTxn) (node txnif.AppendNode, created bool, n uint32, err error) {
 	left := appender.node.block.meta.GetSchema().BlockMaxRows - appender.rows - appender.placeholder
 	if left == 0 {
 		// n = rows
@@ -60,6 +61,9 @@ func (appender *blockAppender) PrepareAppend(rows uint32) (n uint32, err error)
 		n = rows
 	}
 	appender.placeholder += n
+	appender.node.block.mvcc.Lock()
+	defer appender.node.block.mvcc.Unlock()
+	node, created = appender.node.block.mvcc.AddAppendNodeLocked(txn, appender.placeholder+appender.rows)
 	return
 }
 func (appender *blockAppender) ReplayAppend(bat *containers.Batch) (err error) {
@@ -96,8 +100,7 @@ func (appender *blockAppender) ReplayAppend(bat *containers.Batch) (err error) {
 }
 func (appender *blockAppender) ApplyAppend(
 	bat *containers.Batch,
-	txn txnif.AsyncTxn,
-	anode txnif.AppendNode) (node txnif.AppendNode, from int, err error) {
+	txn txnif.AsyncTxn) (from int, err error) {
 	err = appender.node.DoWithPin(func() (err error) {
 		appender.node.block.mvcc.Lock()
 		defer appender.node.block.mvcc.Unlock()
@@ -127,12 +130,6 @@ func (appender *blockAppender) ApplyAppend(
 			}
 		}
 		appender.node.block.meta.GetSegment().GetTable().AddRows(uint64(bat.Length()))
-		if anode != nil {
-			anode.(*updates.AppendNode).SetMaxRow(appender.node.rows)
-			node = anode
-		} else {
-			node = appender.node.block.mvcc.AddAppendNodeLocked(txn, appender.node.rows)
-		}
 		return
 	})
 	return
diff --git a/pkg/vm/engine/tae/tables/updates/append.go b/pkg/vm/engine/tae/tables/updates/append.go
index 0d30b9b6a..e1db99528 100644
--- a/pkg/vm/engine/tae/tables/updates/append.go
+++ b/pkg/vm/engine/tae/tables/updates/append.go
@@ -83,11 +83,21 @@ func (node *AppendNode) SetLogIndex(idx *wal.Index) {
 func (node *AppendNode) GetID() *common.ID {
 	return node.id
 }
-func (node *AppendNode) GetCommitTS() uint64  { return node.commitTs }
+func (node *AppendNode) GetCommitTS() uint64 {
+	node.RLock()
+	defer node.RUnlock()
+	if node.txn != nil {
+		return node.txn.GetCommitTS()
+	}
+	return node.commitTs
+}
 func (node *AppendNode) GetMaxRow() uint32    { return node.maxRow }
 func (node *AppendNode) SetMaxRow(row uint32) { node.maxRow = row }
 
 func (node *AppendNode) PrepareCommit() error {
+	node.Lock()
+	defer node.Unlock()
+	node.commitTs = node.txn.GetCommitTS()
 	return nil
 }
 
@@ -143,8 +153,13 @@ func (node *AppendNode) ReadFrom(r io.Reader) (n int64, err error) {
 	return
 }
 
-func (node *AppendNode) PrepareRollback() (err error) { return }
-func (node *AppendNode) ApplyRollback() (err error)   { return }
+func (node *AppendNode) PrepareRollback() (err error) {
+	node.mvcc.Lock()
+	defer node.mvcc.Unlock()
+	node.mvcc.DeleteAppendNodeLocked(node)
+	return
+}
+func (node *AppendNode) ApplyRollback() (err error) { return }
 func (node *AppendNode) MakeCommand(id uint32) (cmd txnif.TxnCmd, err error) {
 	cmd = NewAppendCmd(id, node)
 	return
diff --git a/pkg/vm/engine/tae/tables/updates/mvcc.go b/pkg/vm/engine/tae/tables/updates/mvcc.go
index 7012c4571..29b9fd84a 100644
--- a/pkg/vm/engine/tae/tables/updates/mvcc.go
+++ b/pkg/vm/engine/tae/tables/updates/mvcc.go
@@ -207,10 +207,38 @@ func (n *MVCCHandle) TrySetMaxVisible(ts uint64) {
 		n.maxVisible = ts
 	}
 }
-func (n *MVCCHandle) AddAppendNodeLocked(txn txnif.AsyncTxn, maxRow uint32) *AppendNode {
-	an := NewAppendNode(txn, maxRow, n)
-	n.appends = append(n.appends, an)
-	return an
+func (n *MVCCHandle) AddAppendNodeLocked(
+	txn txnif.AsyncTxn,
+	maxRow uint32) (an *AppendNode, created bool) {
+	if len(n.appends) == 0 {
+		an = NewAppendNode(txn, maxRow, n)
+		n.appends = append(n.appends, an)
+		created = true
+	} else {
+		an = n.appends[len(n.appends)-1]
+		an.RLock()
+		nTxn := an.txn
+		an.RUnlock()
+		if nTxn != txn {
+			an = NewAppendNode(txn, maxRow, n)
+			n.appends = append(n.appends, an)
+			created = true
+		} else {
+			created = false
+			an.SetMaxRow(maxRow)
+		}
+	}
+	return
+}
+
+func (n *MVCCHandle) DeleteAppendNodeLocked(node *AppendNode) {
+	for i := len(n.appends) - 1; i >= 0; i-- {
+		if n.appends[i].maxRow == node.maxRow {
+			n.appends = append(n.appends[:i], n.appends[i+1:]...)
+		} else if n.appends[i].maxRow < node.maxRow {
+			break
+		}
+	}
 }
 
 func (n *MVCCHandle) IsVisibleLocked(row uint32, ts uint64) (bool, error) {
diff --git a/pkg/vm/engine/tae/txn/txnimpl/appender.go b/pkg/vm/engine/tae/txn/txnimpl/appender.go
index d22dbfe92..4e8d3aae6 100644
--- a/pkg/vm/engine/tae/txn/txnimpl/appender.go
+++ b/pkg/vm/engine/tae/txn/txnimpl/appender.go
@@ -16,11 +16,13 @@ package txnimpl
 
 import (
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/data"
+	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
 )
 
 type appendCtx struct {
 	driver data.BlockAppender
 	node   InsertNode
+	anode  txnif.AppendNode
 	start  uint32
 	count  uint32
 }
diff --git a/pkg/vm/engine/tae/txn/txnimpl/localseg.go b/pkg/vm/engine/tae/txn/txnimpl/localseg.go
index 9dc8ff6d6..3cd00e60b 100644
--- a/pkg/vm/engine/tae/txn/txnimpl/localseg.go
+++ b/pkg/vm/engine/tae/txn/txnimpl/localseg.go
@@ -13,7 +13,6 @@ import (
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/data"
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle"
-	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model"
 	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
 )
@@ -81,38 +80,18 @@ func (seg *localSegment) registerInsertNode() {
 }
 
 func (seg *localSegment) ApplyAppend() (err error) {
-	var (
-		destOff      int
-		anode        txnif.AppendNode
-		prev         txnif.AppendNode
-		prevAppender data.BlockAppender
-	)
+	var destOff int
 	for _, ctx := range seg.appends {
 		bat, _ := ctx.node.Window(ctx.start, ctx.start+ctx.count)
 		defer bat.Close()
-		if prevAppender != nil && prevAppender.GetID().BlockID == ctx.driver.GetID().BlockID {
-			prev = anode
-		} else {
-			if anode != nil {
-				seg.table.store.IncreateWriteCnt()
-				seg.table.txnEntries = append(seg.table.txnEntries, anode)
-			}
-			prev = nil
-		}
-		prevAppender = ctx.driver
-		if anode, destOff, err = ctx.driver.ApplyAppend(
+		if destOff, err = ctx.driver.ApplyAppend(
 			bat,
-			seg.table.store.txn,
-			prev); err != nil {
+			seg.table.store.txn); err != nil {
 			return
 		}
 		id := ctx.driver.GetID()
 		ctx.node.AddApplyInfo(ctx.start, ctx.count, uint32(destOff), ctx.count, seg.table.entry.GetDB().ID, id)
 	}
-	if anode != nil {
-		seg.table.store.IncreateWriteCnt()
-		seg.table.txnEntries = append(seg.table.txnEntries, anode)
-	}
 	if seg.tableHandle != nil {
 		seg.table.entry.GetTableData().ApplyHandle(seg.tableHandle)
 	}
@@ -154,7 +133,9 @@ func (seg *localSegment) prepareApplyNode(node InsertNode) (err error) {
 			}
 			appender = seg.tableHandle.SetAppender(blk.Fingerprint())
 		}
-		toAppend, err := appender.PrepareAppend(node.RowsWithoutDeletes() - appended)
+		anode, created, toAppend, err := appender.PrepareAppend(
+			node.RowsWithoutDeletes()-appended,
+			seg.table.store.txn)
 		if err != nil {
 			return err
 		}
@@ -162,9 +143,14 @@ func (seg *localSegment) prepareApplyNode(node InsertNode) (err error) {
 		ctx := &appendCtx{
 			driver: appender,
 			node:   node,
+			anode:  anode,
 			start:  node.OffsetWithDeletes(appended),
 			count:  toAppendWithDeletes,
 		}
+		if created {
+			seg.table.store.IncreateWriteCnt()
+			seg.table.txnEntries = append(seg.table.txnEntries, anode)
+		}
 		id := appender.GetID()
 		seg.table.store.warChecker.ReadBlock(seg.table.entry.GetDB().ID, id)
 		seg.appends = append(seg.appends, ctx)
diff --git a/proto/logservice.proto b/proto/logservice.proto
index 066a609b9..5f8f92aa5 100644
--- a/proto/logservice.proto
+++ b/proto/logservice.proto
@@ -182,10 +182,11 @@ enum ErrorCode {
   Rejected              = 7;
   ShardNotReady         = 8;
   SystemClosed          = 9;
-
-  LsnAlreadyTruncated = 100;
+  
+  LsnAlreadyTruncated   = 100;
   OutOfRange            = 101;
   NotLeaseHolder        = 102;
+  NotHAKeeper           = 103;
 
   OtherSystemError      = 1000;
 };


Test patch:
diff --git a/docs/cn/MatrixOne/Get-Started/Tutorial/NYC-test-with-matrixone.md b/docs/cn/MatrixOne/Get-Started/Tutorial/NYC-test-with-matrixone.md
deleted file mode 100644
index 37933e7f1..000000000
--- a/docs/cn/MatrixOne/Get-Started/Tutorial/NYC-test-with-matrixone.md
+++ /dev/null
@@ -1,215 +0,0 @@
-# **完成NYC测试**
-
-**NYC Taxi(纽约出租车)**  数据集收集了纽约市数十亿出租车行程的详细信息，包括接送日期/时间、接送地点、行程距离、详细票价、费率、支付类型和乘客数量。  
-通过本教程，您将了解如何使用MatrixOne来完成对NYC Taxi数据集的查询。
-
-该数据集的详细信息以及下载教程可参见：   
-
-* [https://github.com/toddwschneider/nyc-taxi-data](https://github.com/toddwschneider/nyc-taxi-data)  
-
-* [http://tech.marksblogg.com/billion-nyc-taxi-rides-redshift.html](http://tech.marksblogg.com/billion-nyc-taxi-rides-redshift.html). 
-
-## **准备工作** 
-
-确保你已经安装了[单机版MatrixOne](../install-standalone-matrixone.md)并[连接到MatrixOne服务](../connect-to-matrixone-server.md).
-  
-## **1. 下载并导入数据**
-
-本节教程参考[https://github.com/toddwschneider/nyc-taxi-data](https://github.com/toddwschneider/nyc-taxi-data)，您可以从此处了解关于数据集下载和导入的详细信息。  
-该数据集共有17亿行数据，占用450 GB的空间，请确保有足够的空间来存放数据。
-
-* <font size=4>**安装PostgreSQL与PostGIS**</font>  
-
-在Mac上，两者均可通过[Homebrew](https://brew.sh)安装。
-
-* <font size=4>**下载原始数据**</font>
-
-```
-./download_raw_data.sh && ./remove_bad_rows.sh
-```
-
-`remove_bad_rows.sh`脚本修复了两个特定的文件，其中数据极少但是列字段很多。
-
-* <font size=4>**初始化数据库**</font>
-
-```
-./initialize_database.sh
-```
-
-* <font size=4>**导入数据**</font>
-
-```
-./import_trip_data.sh 
-./import_fhv_trip_data.sh
-```
-
-* <font size=4>**可选操作：下载并导入2014年Uber数据**</font>
-
-FiveThirtyEight Uber数据集包含了2014年4月至9月的Uber出行记录。Uber和其他FHV (Lyft、Juno、Via等)的数据自2015年1月以来就被存储在TLC中。
-
-```
-./download_raw_2014_uber_data.sh 
-./import_2014_uber_trip_data.sh
-```
-
-## **2. 从PostgreSQL导出数据**
-
-```
-COPY
-(
-    SELECT trips.id,
-           trips.vendor_id,
-           trips.pickup_datetime,
-           trips.dropoff_datetime,
-           trips.store_and_fwd_flag,
-           trips.rate_code_id,
-           trips.pickup_longitude,
-           trips.pickup_latitude,
-           trips.dropoff_longitude,
-           trips.dropoff_latitude,
-           trips.passenger_count,
-           trips.trip_distance,
-           trips.fare_amount,
-           trips.extra,
-           trips.mta_tax,
-           trips.tip_amount,
-           trips.tolls_amount,
-           trips.ehail_fee,
-           trips.improvement_surcharge,
-           trips.total_amount,
-           trips.payment_type,
-           trips.trip_type,
-           trips.pickup_location_id,
-           trips.dropoff_location_id,
-
-           cab_types.type cab_type,
-
-           weather.precipitation rain,
-           weather.snow_depth,
-           weather.snowfall,
-           weather.max_temperature max_temp,
-           weather.min_temperature min_temp,
-           weather.average_wind_speed wind,
-
-           pick_up.gid pickup_nyct2010_gid,
-           pick_up.ctlabel pickup_ctlabel,
-           pick_up.borocode pickup_borocode,
-           pick_up.boroname pickup_boroname,
-           pick_up.ct2010 pickup_ct2010,
-           pick_up.boroct2010 pickup_boroct2010,
-           pick_up.cdeligibil pickup_cdeligibil,
-           pick_up.ntacode pickup_ntacode,
-           pick_up.ntaname pickup_ntaname,
-           pick_up.puma pickup_puma,
-           
-           drop_off.gid dropoff_nyct2010_gid,
-           drop_off.ctlabel dropoff_ctlabel,
-           drop_off.borocode dropoff_borocode,
-           drop_off.boroname dropoff_boroname,
-           drop_off.ct2010 dropoff_ct2010,
-           drop_off.boroct2010 dropoff_boroct2010,
-           drop_off.cdeligibil dropoff_cdeligibil,
-           drop_off.ntacode dropoff_ntacode,
-           drop_off.ntaname dropoff_ntaname,
-           drop_off.puma dropoff_puma
-           
-           FROM trips
-           LEFT JOIN cab_types
-               ON trips.cab_type_id = cab_types.id
-           LEFT JOIN central_park_weather_observations weather
-               ON weather.date = trips.pickup_datetime::date
-           LEFT JOIN nyct2010 pick_up
-               ON pick_up.gid = trips.pickup_nyct2010_gid
-           LEFT JOIN nyct2010 drop_off
-               ON drop_off.gid = trips.dropoff_nyct2010_gid
-) TO '/matrixone/export_data/trips.tsv';
-```
-
-## **3. 在MatrixOne中建表**
-
-```
-CREATE TABLE trips
-(
-    trip_id                 int unsigned,
-    vendor_id               varchar(64),
-    pickup_datetime         bigint unsigned,
-    dropoff_datetime        bigint unsigned,
-    store_and_fwd_flag      char(1),
-    rate_code_id            smallint unsigned,
-    pickup_longitude        double,
-    pickup_latitude         double,
-    dropoff_longitude       double,
-    dropoff_latitude        double,
-    passenger_count         smallint unsigned,
-    trip_distance           double,
-    distance                bigint,
-    fare_amount             float,
-    extra                   float,
-    mta_tax                 float,
-    tip_amount              float,
-    tolls_amount            float,
-    ehail_fee               float,
-    improvement_surcharge   float,
-    total_amount            float,
-    payment_type            varchar(64),
-    trip_type               smallint unsigned,
-    pickup                  varchar(64),
-    dropoff                 varchar(64),
-    cab_type                varchar(64),
-    precipitation           float,
-    snow_depth              float,
-    snowfall                float,
-    max_temperature         smallint,
-    min_temperature         smallint,
-    average_wind_speed      float,
-    pickup_nyct2010_gid     smallint unsigned,
-    pickup_ctlabel          varchar(64),
-    pickup_borocode         smallint unsigned,
-    pickup_boroname         varchar(64),
-    pickup_ct2010           varchar(64),
-    pickup_boroct2010       varchar(64),
-    pickup_cdeligibil       char(1),
-    pickup_ntacode          varchar(64),
-    pickup_ntaname          varchar(64),
-    pickup_puma             varchar(64),
-    dropoff_nyct2010_gid    smallint unsigned,
-    dropoff_ctlabel         varchar(64),
-    dropoff_borocode        smallint unsigned,
-    dropoff_boroname        varchar(64),
-    dropoff_ct2010          varchar(64),
-    dropoff_boroct2010      varchar(64),
-    dropoff_cdeligibil      varchar(64),
-    dropoff_ntacode         varchar(64),
-    dropoff_ntaname         varchar(64),
-    dropoff_puma            varchar(64)
-) ;
-```
-
-## **4. 向表中插入数据**
-
-```
-load data infile '/matrixone/export_data/trips.tsv ' into table trips 
-FIELDS TERMINATED BY ',' 
-LINES TERMINATED BY '\n';
-```
-
-然后便可以使用MatrixOne中的查询语句来查询表中数据。
-
-## **5. Run Queries**
-
-```
-# Q1
-SELECT cab_type, count(*) FROM trips GROUP BY cab_type;
-
-# Q2
-SELECT passenger_count, avg(total_amount) FROM trips GROUP BY passenger_count;
-
-# Q3
-SELECT passenger_count, year(pickup_datetime) as year, count(*) FROM trips GROUP BY passenger_count, year;
-
-# Q4
-SELECT passenger_count, year(pickup_datetime) as year, round(trip_distance) AS  distance, count(*) as count 
-FROM trips 
-GROUP BY passenger_count, year, distance 
-ORDER BY year,count DESC;
-```
diff --git a/docs/cn/MatrixOne/Get-Started/Tutorial/SSB-test-with-matrixone.md b/docs/cn/MatrixOne/Get-Started/Tutorial/SSB-test-with-matrixone.md
index 49e2d51f4..a8bcf7899 100644
--- a/docs/cn/MatrixOne/Get-Started/Tutorial/SSB-test-with-matrixone.md
+++ b/docs/cn/MatrixOne/Get-Started/Tutorial/SSB-test-with-matrixone.md
@@ -1,11 +1,11 @@
 # **完成SSB测试**
 
-SSB星型模式基准测试是OLAP数据库性能测试的常用场景，通过本篇教程，您可以了解到如何在MatrixOne中实现SSB测试。
+SSB 星型模式基准测试是 OLAP 数据库性能测试的常用场景，通过本篇教程，您可以了解到如何在 MatrixOne 中实现 SSB 测试。
 
 ## **准备工作**
 
 确保你已经安装了[单机版MatrixOne](../install-standalone-matrixone.md)并[连接到MatrixOne服务](../connect-to-matrixone-server.md).
-  
+
 ## **1. 编译dbgen**
 
 ```
@@ -26,6 +26,12 @@ $ ./dbgen -s 1 -T s
 $ ./dbgen -s 1 -T d
 ```
 
+我们还准备了 1GB 的数据集供你下载。你可以在下面链接中直接获取数据文件：
+
+```
+https://community-shared-data-1308875761.cos.ap-beijing.myqcloud.com/lineorder_flat.tar.bz2
+```
+
 ## **3. 在MatrixOne中建表**
 
 ```
@@ -154,12 +160,6 @@ CREATE TABLE lineorder_flat(
 
 ## **4. 导入数据**
 
-将`system_vars_config.toml`参数增大，例如10GB，然后重新启动MatrixOne服务。
-
-```
-max-entry-bytes = "10GB"
-```
-
 使用如下命令将数据导入相关表：
 
 ```
diff --git a/docs/cn/MatrixOne/Overview/NYC-Test-Performance.md b/docs/cn/MatrixOne/Overview/NYC-Test-Performance.md
deleted file mode 100644
index c77b28aa5..000000000
--- a/docs/cn/MatrixOne/Overview/NYC-Test-Performance.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# **NYC性能测试结果**
-
-## **概述**
-
-在MatrixOne v0.2.0版本，我们在单机上遵照[相关流程](../Get-Started/Tutorial/NYC-test-with-matrixone.md)实现了**纽约出租车数据测试**，并将测试结果与其他产品相比较，体现了MatrixOne在查询处理时间上的优异性。  
-
-!!! note  <font size=4>说明</font>
-    <font size=3>以下测试结果根据 MatrixOne v0.2.0 版本测试得出，均取三次最好结果的平均值，以秒为单位。</font>  
-
-## **单机测试**
-
-!!! info 测试配置
-    测试所用服务器配置如下：  
-    AMD EPYC™ Rome CPU 2.6GHz/3.3GHz，16核，32GiB内存。
-
-|  查询编号 | MatrixOne 0.2.0   |  ClickHouse v21.11.4.14 | Starrocks v1.19.3<br>(仅有3000万行独立数据)
-|  :----:  | :----:  |  :----:  |:----:
-| Q1 | 8.37|5.99 |2.58
-| Q2 | 2.67|4.13 |2.18
-| Q3 | 3.48|4.56 |3.43
-| Q4 | 5.34|7.09 |4.19
-| 总和| 19.86|21.77|12.38
-
-![柱状图](https://github.com/matrixorigin/artwork/blob/main/docs/overview/NYC_standalone.png?raw=true)
-
-## **限制**
-
-在测试中对MatrixOne v0.2.0的查询语句进行了一些限制：
-
-* 不使用 `WHERE`过滤语句
-* 暂不支持表分区，因此不使用`PARTITION`相关命令
-
-## **相关信息**
-
-本节内容展示了使用MatrixOne进行纽约出租车数据测试的结果。若想获取更多相关信息，请见：
-
-* [完成SSB测试](../Get-Started/Tutorial/SSB-test-with-matrixone.md)  
-* [SSB测试报告](SSB-Test-Performance.md)
diff --git a/docs/cn/MatrixOne/Overview/SSB-Test-Performance.md b/docs/cn/MatrixOne/Overview/SSB-Test-Performance.md
deleted file mode 100644
index 3c591475d..000000000
--- a/docs/cn/MatrixOne/Overview/SSB-Test-Performance.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# **SSB测试性能报告**
-
-## **概述**
-
-在此，我们给出了使用MatrixOne在不同的硬件和查询条件下进行SSB测试的性能结果。  
-可参见[完成SSB测试](../Get-Started/Tutorial/SSB-test-with-matrixone.md)来复现整个测试结果，如果未能实现类似结果，可能需要检查硬件、负载或或测试流程是否存在问题，可以在GitHub上提出[issue](https://github.com/matrixorigin/matrixone/issues/new/choose)来报告具体问题。  
-在v0.2.0中，MatrixOne在单表、多表查询方面均有优异的表现，我们将MatrixOne的性能测试结果与其他数据库产品进行了比较。通过柱状图，可以看出MatrixOne在查询处理时间上有明显的优势。
-
-推荐测试使用的服务器规格型号：x86 CPU，16核，64GB内存，CentOS 7+操作系统。
-
-!!! note  <font size=4>说明</font>
-    <font size=3>以下测试结果根据 MatrixOne v0.2.0 版本测试得出，均取三次最好结果的平均值，以秒为单位</font>  
-
-为了展示单表查询能力，将五张表合成为一张宽表：`lineorder_flat`。
-
-## **单机单表**
-
-使用单机搭载MatrixOne执行对宽表`lineorder_flat`的查询，并与相同配置下的其他数据库进行比较。
-`lineorder_flat`共有6亿行数据，共占据220 GB空间。  
-
-!!! info 测试配置
-    测试所用服务器配置如下：  
-    AMD EPYC™ Rome CPU 2.6GHz/3.3GHz，16核，32GiB内存。
-
-|  查询编号  | MatrixOne v0.2.0  |  ClickHouse v21.11.4.14
-|  :----:  | :----:  |  :----:  
-| Q2  | 2.71 |3.82 	
-| Q3.1 | 4.23|5.01
-| Q3.2  | 11.05|21.34
-| Q4.1  | 2.94|3.1
-| Q4.2  | 4.27|5.32
-| Q4.3  | 16.91|26.32
-| 总和  | 42.11|64.91
-
-![柱状图](https://github.com/matrixorigin/artwork/blob/main/docs/overview/SSB_standalone_single.png?raw=true)
-
-## **单机多表**
-
-仍然使用单机环境，现对原始SSB测试数据集中的多个数据表进行查询，数据共有6亿行，主表占据67GB空间。
-
-|  查询编号  | MatrixOne v0.2.0   |  ClickHouse v21.11.4.14| Starrocks v1.19.3
-|  :----:  | :----:  |  :----:  |:----:
-| Q2  | 13.6|28.05 |15.83
-| Q3.1 | 12.94|27.81 |16.98
-| Q3.2  | 23.56|54.84 |29.25
-| Q4.1  | 13.96|27.2 |16.77
-| Q4.2  | 19.72|41.82|21.54
-| Q4.3  | 46.07|85.99|35.95
-| 总和  | 129.85|265.71|136.37
-
-![柱状图](https://github.com/matrixorigin/artwork/blob/main/docs/overview/SSB_standalone_multi.png?raw=true)
-
-## **集群多表**
-
-使用由三个节点组成的集群进行多表查询，其中每一个节点都按照单机进行安装部署。由测试结果可知，集群的查询时间明显短于单机查询，证明了MatrixOne的总体性能随着集群中节点个数增加而提高。
-
-|  查询编号  | MatrixOne v0.2.0  |  Starrocks v1.19.3
-|  :----:  | :----:  |  :----:  
-| Q2 | 4.94 |6.08 	
-| Q3.1 | 5.85|6.27
-| Q3.2  | 9.67|9.79
-| Q4.1  | 6.05|6.87
-| Q4.2  | 6.87|9.51
-| Q4.3  | 20.1|15.55
-| 总和  | 53.48|54.07
-
-![柱状图](https://github.com/matrixorigin/artwork/blob/main/docs/overview/SSB_cluster_multi.png?raw=true)
-
-## **限制**
-
-MatrixOne v0.2.0并没有完成所有SSB查询语句，原因如下：
-
-* 不使用包含`WHERE`过滤语句的查询命令
-* 暂不支持表分区，因此不使用`PARTITION`相关命令
-
-## **相关信息**
-
-本节内容展示了使用MatrixOne进行SSB测试的结果。若想获取更多相关信息，请见：  
-
-* [完成NYC测试](../Get-Started/Tutorial/NYC-test-with-matrixone.md)  
-* [NYC测试结果](NYC-Test-Performance.md)
diff --git a/pkg/logservice/errors_test.go b/pkg/logservice/errors_test.go
index 73ef72fce..f4d73884b 100644
--- a/pkg/logservice/errors_test.go
+++ b/pkg/logservice/errors_test.go
@@ -67,6 +67,8 @@ func TestIsTempError(t *testing.T) {
 		{dragonboat.ErrInvalidTarget, false},
 		{dragonboat.ErrInvalidRange, false},
 
+		{ErrNotHAKeeper, true},
+
 		{ErrDeadlineNotSet, false},
 		{ErrInvalidDeadline, false},
 		{ErrInvalidTruncateLsn, false},
diff --git a/pkg/logservice/hakeeper_checker_test.go b/pkg/logservice/hakeeper_checker_test.go
index 6e9c82a12..2ca728811 100644
--- a/pkg/logservice/hakeeper_checker_test.go
+++ b/pkg/logservice/hakeeper_checker_test.go
@@ -181,7 +181,7 @@ func runHAKeeperClusterTest(t *testing.T, fn func(*testing.T, []*Service)) {
 	service1, err := NewService(cfg1)
 	require.NoError(t, err)
 	defer func() {
-		//assert.NoError(t, service1.Close())
+		assert.NoError(t, service1.Close())
 	}()
 	service2, err := NewService(cfg2)
 	require.NoError(t, err)
@@ -209,7 +209,7 @@ func runHAKeeperClusterTest(t *testing.T, fn func(*testing.T, []*Service)) {
 	fn(t, []*Service{service1, service2, service3, service4})
 }
 
-func TestHAKeeperClusterCanBootstrapAndRepairLogShard(t *testing.T) {
+func TestHAKeeperCanBootstrapAndRepairShards(t *testing.T) {
 	if os.Getenv("LONG_TEST") == "" {
 		// this test will fail on go1.18 when -race is enabled, as it always
 		// timeout. go1.19 has a much faster -race implementation and it works fine
@@ -238,6 +238,15 @@ func TestHAKeeperClusterCanBootstrapAndRepairLogShard(t *testing.T) {
 		}
 		sendHeartbeat(services[:3])
 
+		// fake a DN store
+		dnMsg := pb.DNStoreHeartbeat{
+			UUID:   uuid.New().String(),
+			Shards: make([]pb.DNShardInfo, 0),
+		}
+		ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
+		defer cancel()
+		require.NoError(t, services[0].store.addDNStoreHeartbeat(ctx, dnMsg))
+
 		// find out the leader HAKeeper store as we need the term value
 		var term uint64
 		var leaderStore *store
@@ -266,8 +275,6 @@ func TestHAKeeperClusterCanBootstrapAndRepairLogShard(t *testing.T) {
 		assert.False(t, leaderStore.bootstrapMgr.CheckBootstrap(state.LogState))
 
 		// get and apply all bootstrap schedule commands
-		ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
-		defer cancel()
 		for _, s := range services[:3] {
 			cb, err := s.store.getCommandBatch(ctx, s.store.id())
 			require.NoError(t, err)
@@ -296,13 +303,35 @@ func TestHAKeeperClusterCanBootstrapAndRepairLogShard(t *testing.T) {
 			}
 		}
 
+		// get the DN bootstrap command, it contains DN shard and replica ID
+		cb, err := leaderStore.getCommandBatch(ctx, dnMsg.UUID)
+		require.NoError(t, err)
+		require.Equal(t, 1, len(cb.Commands))
+		cmd := cb.Commands[0]
+		assert.True(t, cmd.Bootstrapping)
+		assert.Equal(t, pb.DnService, cmd.ServiceType)
+		dnShardInfo := pb.DNShardInfo{
+			ShardID:   cmd.ConfigChange.Replica.ShardID,
+			ReplicaID: cmd.ConfigChange.Replica.ReplicaID,
+		}
+		dnMsg.Shards = append(dnMsg.Shards, dnShardInfo)
+		// as if DN is running
+		require.NoError(t, services[0].store.addDNStoreHeartbeat(ctx, dnMsg))
+		// fake a free DN store
+		dnMsg2 := pb.DNStoreHeartbeat{
+			UUID:   uuid.New().String(),
+			Shards: make([]pb.DNShardInfo, 0),
+		}
+		require.NoError(t, services[0].store.addDNStoreHeartbeat(ctx, dnMsg2))
+
 		// stop store 1
 		require.NoError(t, services[0].Close())
 		// no service.Close can be repeatedly called
 		services[0].store = nil
 		services = services[1:]
 
-		// wait for HAKeeper to repair the cluster
+		// wait for HAKeeper to repair the Log & HAKeeper shards
+		dnRepaired := false
 		for i := 0; i < 5000; i++ {
 			m := services[0].store.getHeartbeatMessage()
 			assert.NoError(t, services[0].store.addLogStoreHeartbeat(ctx, m))
@@ -310,6 +339,7 @@ func TestHAKeeperClusterCanBootstrapAndRepairLogShard(t *testing.T) {
 			assert.NoError(t, services[1].store.addLogStoreHeartbeat(ctx, m))
 			m = services[2].store.getHeartbeatMessage()
 			assert.NoError(t, services[0].store.addLogStoreHeartbeat(ctx, m))
+			require.NoError(t, services[0].store.addDNStoreHeartbeat(ctx, dnMsg2))
 
 			for _, s := range services {
 				if hasShard(s.store, 0) {
@@ -317,6 +347,18 @@ func TestHAKeeperClusterCanBootstrapAndRepairLogShard(t *testing.T) {
 					s.store.hakeeperCheck()
 				}
 
+				cb, err = services[0].store.getCommandBatch(ctx, dnMsg2.UUID)
+				require.NoError(t, err)
+				if len(cb.Commands) > 0 {
+					cmd := cb.Commands[0]
+					if cmd.ServiceType == pb.DnService {
+						if cmd.ConfigChange.Replica.ShardID == dnShardInfo.ShardID &&
+							cmd.ConfigChange.Replica.ReplicaID > dnShardInfo.ReplicaID {
+							dnRepaired = true
+						}
+					}
+				}
+
 				cb, err := services[0].store.getCommandBatch(ctx, s.store.id())
 				for _, cmd := range cb.Commands {
 					plog.Infof("store returned schedule command: %s", cmd.LogString())
@@ -325,14 +367,15 @@ func TestHAKeeperClusterCanBootstrapAndRepairLogShard(t *testing.T) {
 				s.handleCommands(cb.Commands)
 			}
 
-			notReady := false
+			logRepaired := true
 			for _, s := range services {
 				if !hasShard(s.store, 0) || !hasShard(s.store, 1) {
-					notReady = true
+					logRepaired = false
 					break
 				}
 			}
-			if notReady {
+			plog.Infof("dnRepairted %t, logRepaired %t", dnRepaired, logRepaired)
+			if !logRepaired || !dnRepaired {
 				time.Sleep(time.Millisecond)
 			} else {
 				plog.Infof("repair completed, i: %d", i)
@@ -392,7 +435,6 @@ func testBootstrap(t *testing.T, fail bool) {
 			UUID:   uuid.New().String(),
 			Shards: make([]pb.DNShardInfo, 0),
 		}
-		dnMsg.Shards = append(dnMsg.Shards, pb.DNShardInfo{ShardID: 2, ReplicaID: 3})
 		assert.NoError(t, store.addDNStoreHeartbeat(ctx, dnMsg))
 
 		_, term, err := store.isLeaderHAKeeper()
@@ -419,9 +461,17 @@ func testBootstrap(t *testing.T, fail bool) {
 			require.NoError(t, err)
 			assert.Equal(t, pb.HAKeeperBootstrapFailed, state.State)
 		} else {
-			cb, err := store.getCommandBatch(ctx, store.id())
+			cb, err := store.getCommandBatch(ctx, dnMsg.UUID)
+			require.NoError(t, err)
+			require.Equal(t, 1, len(cb.Commands))
+			assert.True(t, cb.Commands[0].Bootstrapping)
+			assert.Equal(t, pb.DnService, cb.Commands[0].ServiceType)
+			assert.True(t, cb.Commands[0].ConfigChange.Replica.ReplicaID > 0)
+
+			cb, err = store.getCommandBatch(ctx, store.id())
 			require.NoError(t, err)
 			require.Equal(t, 1, len(cb.Commands))
+			assert.True(t, cb.Commands[0].Bootstrapping)
 			service := &Service{store: store}
 			service.handleStartReplica(cb.Commands[0])
 
diff --git a/pkg/logservice/hakeeper_client_test.go b/pkg/logservice/hakeeper_client_test.go
index 9d718be29..138603740 100644
--- a/pkg/logservice/hakeeper_client_test.go
+++ b/pkg/logservice/hakeeper_client_test.go
@@ -16,9 +16,13 @@ package logservice
 
 import (
 	"context"
+	"sync"
 	"testing"
 	"time"
 
+	"github.com/lni/dragonboat/v4"
+	"github.com/lni/goutils/leaktest"
+	"github.com/lni/vfs"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
@@ -53,11 +57,11 @@ func TestHAKeeperClientCanNotConnectToNonHAKeeperNode(t *testing.T) {
 		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 		defer cancel()
 		_, err := NewCNHAKeeperClient(ctx, cfg)
-		require.Equal(t, ErrNoHAKeeper, err)
+		require.Equal(t, ErrNotHAKeeper, err)
 		_, err = NewDNHAKeeperClient(ctx, cfg)
-		assert.Equal(t, ErrNoHAKeeper, err)
+		assert.Equal(t, ErrNotHAKeeper, err)
 		_, err = NewLogHAKeeperClient(ctx, cfg)
-		assert.Equal(t, ErrNoHAKeeper, err)
+		assert.Equal(t, ErrNotHAKeeper, err)
 	}
 	runServiceTest(t, false, true, fn)
 }
@@ -176,3 +180,119 @@ func TestHAKeeperClientSendLogHeartbeat(t *testing.T) {
 	}
 	runServiceTest(t, true, true, fn)
 }
+
+func testNotHAKeeperErrorIsHandled(t *testing.T, fn func(*testing.T, *managedHAKeeperClient)) {
+	defer leaktest.AfterTest(t)()
+	cfg1 := Config{
+		FS:                    vfs.NewStrictMem(),
+		DeploymentID:          1,
+		RTTMillisecond:        5,
+		DataDir:               "data-1",
+		ServiceAddress:        "127.0.0.1:9002",
+		RaftAddress:           "127.0.0.1:9000",
+		GossipAddress:         "127.0.0.1:9001",
+		GossipSeedAddresses:   []string{"127.0.0.1:9011"},
+		DisableHAKeeperTicker: true,
+	}
+	cfg2 := Config{
+		FS:                    vfs.NewStrictMem(),
+		DeploymentID:          1,
+		RTTMillisecond:        5,
+		DataDir:               "data-2",
+		ServiceAddress:        "127.0.0.1:9012",
+		RaftAddress:           "127.0.0.1:9010",
+		GossipAddress:         "127.0.0.1:9011",
+		GossipSeedAddresses:   []string{"127.0.0.1:9001"},
+		DisableHAKeeperTicker: true,
+	}
+	service1, err := NewService(cfg1)
+	require.NoError(t, err)
+	defer func() {
+		assert.NoError(t, service1.Close())
+	}()
+	service2, err := NewService(cfg2)
+	require.NoError(t, err)
+	defer func() {
+		assert.NoError(t, service2.Close())
+	}()
+	// service2 is HAKeeper
+	peers := make(map[uint64]dragonboat.Target)
+	peers[1] = service2.ID()
+	assert.NoError(t, service2.store.startHAKeeperReplica(1, peers, false))
+	// manually construct a HAKeeper client that is connected to service1
+	pool := &sync.Pool{}
+	pool.New = func() interface{} {
+		return &RPCRequest{pool: pool}
+	}
+	respPool := &sync.Pool{}
+	respPool.New = func() interface{} {
+		return &RPCResponse{pool: respPool}
+	}
+	cfg := HAKeeperClientConfig{
+		ServiceAddresses: []string{cfg1.ServiceAddress, cfg2.ServiceAddress},
+	}
+	c := &hakeeperClient{
+		cfg:      cfg,
+		pool:     pool,
+		respPool: respPool,
+	}
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	cc, err := getRPCClient(ctx, cfg1.ServiceAddress, c.respPool)
+	require.NoError(t, err)
+	c.addr = cfg1.ServiceAddress
+	c.client = cc
+	client := &managedHAKeeperClient{client: c, cfg: cfg}
+	defer func() {
+		require.NoError(t, client.Close())
+	}()
+	fn(t, client)
+}
+
+func TestGetClusterDetailsWhenNotConnectedToHAKeeper(t *testing.T) {
+	fn := func(t *testing.T, c *managedHAKeeperClient) {
+		oldc := c.client
+		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+		defer cancel()
+		_, err := c.GetClusterDetails(ctx)
+		require.NoError(t, err)
+		require.True(t, oldc != c.client)
+	}
+	testNotHAKeeperErrorIsHandled(t, fn)
+}
+
+func TestSendCNHeartbeatWhenNotConnectedToHAKeeper(t *testing.T) {
+	fn := func(t *testing.T, c *managedHAKeeperClient) {
+		oldc := c.client
+		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+		defer cancel()
+		err := c.SendCNHeartbeat(ctx, pb.CNStoreHeartbeat{})
+		require.NoError(t, err)
+		require.True(t, oldc != c.client)
+	}
+	testNotHAKeeperErrorIsHandled(t, fn)
+}
+
+func TestSendDNHeartbeatWhenNotConnectedToHAKeeper(t *testing.T) {
+	fn := func(t *testing.T, c *managedHAKeeperClient) {
+		oldc := c.client
+		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+		defer cancel()
+		_, err := c.SendDNHeartbeat(ctx, pb.DNStoreHeartbeat{})
+		require.NoError(t, err)
+		require.True(t, oldc != c.client)
+	}
+	testNotHAKeeperErrorIsHandled(t, fn)
+}
+
+func TestSendLogHeartbeatWhenNotConnectedToHAKeeper(t *testing.T) {
+	fn := func(t *testing.T, c *managedHAKeeperClient) {
+		oldc := c.client
+		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+		defer cancel()
+		_, err := c.SendLogHeartbeat(ctx, pb.LogStoreHeartbeat{})
+		require.NoError(t, err)
+		require.True(t, oldc != c.client)
+	}
+	testNotHAKeeperErrorIsHandled(t, fn)
+}
diff --git a/pkg/txn/service/service_cn_handler_test.go b/pkg/txn/service/service_cn_handler_test.go
index bc876b630..99a4cf7ff 100644
--- a/pkg/txn/service/service_cn_handler_test.go
+++ b/pkg/txn/service/service_cn_handler_test.go
@@ -639,7 +639,14 @@ func checkResponses(t *testing.T, response []txn.TxnResponse, expectErrors ...*t
 }
 
 func checkData(t *testing.T, wTxn txn.TxnMeta, s *service, commitTS int64, k byte, committed bool) {
-	assert.Nil(t, s.getTxnContext(wTxn.ID))
+	for {
+		v := s.getTxnContext(wTxn.ID)
+		if v != nil {
+			time.Sleep(time.Millisecond * 100)
+			continue
+		}
+		break
+	}
 
 	kv := s.storage.(*mem.KVTxnStorage)
 
diff --git a/pkg/util/toml/types_test.go b/pkg/util/toml/types_test.go
new file mode 100644
index 000000000..68ef2ea59
--- /dev/null
+++ b/pkg/util/toml/types_test.go
@@ -0,0 +1,79 @@
+// Copyright 2021 - 2022 Matrix Origin
+//
+// 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.
+
+package toml
+
+import (
+	"testing"
+	"time"
+
+	tp "github.com/BurntSushi/toml"
+	"github.com/stretchr/testify/assert"
+)
+
+type durationValue struct {
+	Zero Duration `toml:"z"`
+	Ms   Duration `toml:"ms"`
+	Sec  Duration `toml:"sec"`
+}
+
+func TestUnmarshalDuration(t *testing.T) {
+	cfg := `
+		ms = "1ms"
+		sec = "1s"
+	`
+	v := &durationValue{}
+	assert.NoError(t, tp.Unmarshal([]byte(cfg), v))
+	assert.Equal(t, time.Millisecond, v.Ms.Duration)
+	assert.Equal(t, time.Second, v.Sec.Duration)
+	assert.Equal(t, time.Duration(0), v.Zero.Duration)
+}
+
+func TestMarshalDuration(t *testing.T) {
+	v := &durationValue{}
+	v.Ms.Duration = time.Millisecond
+	v.Sec.Duration = time.Second
+
+	data, err := v.Zero.MarshalText()
+	assert.NoError(t, err)
+	assert.Equal(t, "0s", string(data))
+
+	data, err = v.Ms.MarshalText()
+	assert.NoError(t, err)
+	assert.Equal(t, "1ms", string(data))
+
+	data, err = v.Sec.MarshalText()
+	assert.NoError(t, err)
+	assert.Equal(t, "1s", string(data))
+}
+
+func TestByteSize(t *testing.T) {
+	var v ByteSize
+
+	assert.NoError(t, v.UnmarshalText([]byte("1K")))
+	assert.Equal(t, 1024, int(v))
+
+	assert.NoError(t, v.UnmarshalText([]byte("1k")))
+	assert.Equal(t, 1024, int(v))
+
+	assert.NoError(t, v.UnmarshalText([]byte("1KB")))
+	assert.Equal(t, 1024, int(v))
+
+	assert.NoError(t, v.UnmarshalText([]byte("1Kb")))
+	assert.Equal(t, 1024, int(v))
+
+	assert.NoError(t, v.UnmarshalText([]byte("1kB")))
+	assert.Equal(t, 1024, int(v))
+
+}
diff --git a/pkg/vm/engine/tae/dataio/segmentio/driver_test.go b/pkg/vm/engine/tae/dataio/segmentio/driver_test.go
index 5d4f35b55..60fc5657d 100644
--- a/pkg/vm/engine/tae/dataio/segmentio/driver_test.go
+++ b/pkg/vm/engine/tae/dataio/segmentio/driver_test.go
@@ -454,6 +454,50 @@ func TestSegment_Replay2(t *testing.T) {
 	checkSegment(t, &seg, &seg1)
 }
 
+func TestSegment_Replay4(t *testing.T) {
+	dir := testutils.InitTestEnv(ModuleName, t)
+	name := path.Join(dir, "init.driver")
+	seg := Driver{}
+	err := seg.Init(name)
+	assert.Nil(t, err)
+	seg.Mount()
+	var file *DriverFile
+	for i := 0; i < INODE_NUM/2-1; i++ {
+		file = seg.NewBlockFile(fmt.Sprintf("test_%d.blk", i))
+		file.snode.algo = compress.None
+		err = seg.Append(file, []byte(fmt.Sprintf("this is tests %d", i)))
+		assert.Nil(t, err)
+	}
+	logStat, err := seg.logFile.Stat()
+	assert.Nil(t, err)
+	if logStat.Size() < int64(LOG_SIZE/2+LOG_START-2*INODE_SIZE) {
+		assert.Nil(t, logStat.Size())
+	}
+	seg1 := Driver{}
+	err = seg1.Open(name)
+	assert.Nil(t, err)
+	seg1.Mount()
+	cache := bytes.NewBuffer(make([]byte, 2*1024*1024))
+	err = seg1.Replay(cache)
+	assert.Nil(t, err)
+	assert.Equal(t, INODE_NUM/2, len(seg1.nodes))
+	checkSegment(t, &seg, &seg1)
+
+	for _, file := range seg1.nodes {
+		if file.name == "logfile" {
+			continue
+		}
+		file.Unref()
+	}
+	assert.Equal(t, 1, len(seg1.nodes))
+	name = path.Join(dir, "init2.driver")
+	seg = Driver{}
+	err = seg.Init(name)
+	assert.Nil(t, err)
+	seg.Mount()
+	checkSegment(t, &seg, &seg1)
+}
+
 func TestSegment_Replay(t *testing.T) {
 	dir := testutils.InitTestEnv(ModuleName, t)
 	name := path.Join(dir, "init.driver")
diff --git a/pkg/vm/engine/tae/db/db_test.go b/pkg/vm/engine/tae/db/db_test.go
index 246527bc9..c3f4a6254 100644
--- a/pkg/vm/engine/tae/db/db_test.go
+++ b/pkg/vm/engine/tae/db/db_test.go
@@ -44,29 +44,29 @@ import (
 
 func TestAppend(t *testing.T) {
 	testutils.EnsureNoLeak(t)
-	db := initDB(t, nil)
-	defer db.Close()
+	tae := newTestEngine(t, nil)
+	defer tae.Close()
 	schema := catalog.MockSchemaAll(14, 3)
 	schema.BlockMaxRows = options.DefaultBlockMaxRows
 	schema.SegmentMaxBlocks = options.DefaultBlocksPerSegment
+	tae.bindSchema(schema)
 	data := catalog.MockBatch(schema, int(schema.BlockMaxRows*2))
 	defer data.Close()
 	bats := data.Split(4)
 	now := time.Now()
-	createRelationAndAppend(t, db, "db", schema, bats[0], true)
+	tae.createRelAndAppend(bats[0], true)
 	t.Log(time.Since(now))
+	tae.checkRowsByScan(bats[0].Length(), false)
 
-	{
-		txn, _ := db.StartTxn(nil)
-		database, err := txn.GetDatabase("db")
-		assert.Nil(t, err)
-		rel, err := database.GetRelationByName(schema.Name)
-		assert.Nil(t, err)
-		appendClosure(t, bats[1], schema.Name, db, nil)()
-		err = rel.Append(bats[2])
-		assert.Nil(t, err)
-		assert.Nil(t, txn.Commit())
-	}
+	txn, rel := tae.getRelation()
+	err := rel.Append(bats[1])
+	assert.NoError(t, err)
+	// FIXME
+	// checkAllColRowsByScan(t, rel, bats[0].Length()+bats[1].Length(), false)
+	err = rel.Append(bats[2])
+	assert.NoError(t, err)
+	assert.NoError(t, txn.Commit())
+	tae.checkRowsByScan(bats[0].Length()+bats[1].Length()+bats[2].Length(), false)
 }
 
 func TestAppend2(t *testing.T) {
diff --git a/pkg/vm/engine/tae/db/replay_test.go b/pkg/vm/engine/tae/db/replay_test.go
index 4b7e2117f..4d0398460 100644
--- a/pkg/vm/engine/tae/db/replay_test.go
+++ b/pkg/vm/engine/tae/db/replay_test.go
@@ -566,10 +566,12 @@ func TestReplay2(t *testing.T) {
 // TODO check rows
 func TestReplay3(t *testing.T) {
 	testutils.EnsureNoLeak(t)
-	tae := initDB(t, nil)
+	tae := newTestEngine(t, nil)
+	defer tae.Close()
 	schema := catalog.MockSchema(2, 1)
 	schema.BlockMaxRows = 1000
 	schema.SegmentMaxBlocks = 2
+	tae.bindSchema(schema)
 	bat := catalog.MockBatch(schema, 1)
 	defer bat.Close()
 	v := bat.Vecs[schema.GetSingleSortKeyIdx()].Get(0)
@@ -591,85 +593,61 @@ func TestReplay3(t *testing.T) {
 		blkID, row, err = tbl.GetByFilter(filter)
 		assert.Nil(t, err)
 		err = tbl.RangeDelete(blkID, row, row, handle.DT_Normal)
-		assert.Nil(t, err)
+		assert.NoError(t, err)
 		err = tbl.Append(bat)
-		assert.Nil(t, err)
+		assert.NoError(t, err)
 	}
-	assert.Nil(t, txn.Commit())
+	assert.NoError(t, txn.Commit())
 
 	for i := 0; i < 10; i++ {
-		txn, err := tae.StartTxn(nil)
-		assert.Nil(t, err)
-		db, err = txn.GetDatabase("db")
-		assert.Nil(t, err)
-		tbl, err = db.GetRelationByName(schema.Name)
+		txn, rel := tae.getRelation()
+		blkID, row, err := rel.GetByFilter(filter)
 		assert.Nil(t, err)
-		blkID, row, err := tbl.GetByFilter(filter)
-		assert.Nil(t, err)
-		err = tbl.Update(blkID, row, 0, int32(33))
+		err = rel.Update(blkID, row, 0, int32(33))
 		assert.Nil(t, err)
 		assert.Nil(t, txn.Commit())
 
-		txn, err = tae.StartTxn(nil)
+		txn, rel = tae.getRelation()
+		blkID, row, err = rel.GetByFilter(filter)
 		assert.Nil(t, err)
-		db, err = txn.GetDatabase("db")
-		assert.Nil(t, err)
-		tbl, err = db.GetRelationByName(schema.Name)
-		assert.Nil(t, err)
-		blkID, row, err = tbl.GetByFilter(filter)
-		assert.Nil(t, err)
-		err = tbl.RangeDelete(blkID, row, row, handle.DT_Normal)
+		err = rel.RangeDelete(blkID, row, row, handle.DT_Normal)
 		assert.Nil(t, err)
 		assert.Nil(t, txn.Commit())
 
-		txn, err = tae.StartTxn(nil)
-		assert.Nil(t, err)
-		db, err = txn.GetDatabase("db")
-		assert.Nil(t, err)
-		tbl, err = db.GetRelationByName(schema.Name)
-		assert.Nil(t, err)
-		err = tbl.Append(bat)
+		txn, rel = tae.getRelation()
+		err = rel.Append(bat)
 		assert.Nil(t, err)
 		assert.Nil(t, txn.Commit())
+		// {
+		// 	txn, rel := tae.getRelation()
+		// 	blk := getOneBlock(rel)
+		// 	t.Log(blk.String())
+		// 	assert.Nil(t, txn.Rollback())
+		// }
 	}
 
-	tae.Close()
-
-	tae2, err := Open(tae.Dir, nil)
-	assert.Nil(t, err)
+	tae.restart()
 
-	txn, err = tae2.StartTxn(nil)
-	assert.Nil(t, err)
-	db, err = txn.GetDatabase("db")
-	assert.Nil(t, err)
-	tbl, err = db.GetRelationByName(schema.Name)
-	assert.Nil(t, err)
-	assert.Equal(t, uint64(1), tbl.GetMeta().(*catalog.TableEntry).GetRows())
-	assert.Nil(t, txn.Commit())
+	txn, rel := tae.getRelation()
+	assert.Equal(t, uint64(1), rel.GetMeta().(*catalog.TableEntry).GetRows())
+	assert.NoError(t, txn.Commit())
 
-	txn, err = tae2.StartTxn(nil)
-	assert.Nil(t, err)
-	db, err = txn.GetDatabase("db")
-	assert.Nil(t, err)
-	tbl, err = db.GetRelationByName(schema.Name)
-	assert.Nil(t, err)
-	blkIterator := tbl.MakeBlockIt()
+	txn, rel = tae.getRelation()
+	blkIterator := rel.MakeBlockIt()
 	for blkIterator.Valid() {
 		blk := blkIterator.GetBlock()
 		blkdata := blk.GetMeta().(*catalog.BlockEntry).GetBlockData()
 		blkdata.Flush()
 		blkIterator.Next()
 	}
-	err = tae2.Catalog.Checkpoint(txn.GetStartTS())
-	assert.Nil(t, err)
-	assert.Nil(t, txn.Commit())
+	err = tae.Catalog.Checkpoint(txn.GetStartTS())
+	assert.NoError(t, err)
+	assert.NoError(t, txn.Commit())
 
 	testutils.WaitExpect(4000, func() bool {
-		return tae2.Wal.GetPenddingCnt() == 0
+		return tae.Wal.GetPenddingCnt() == 0
 	})
-	assert.Equal(t, uint64(0), tae2.Wal.GetPenddingCnt())
-
-	tae2.Close()
+	assert.Equal(t, uint64(0), tae.Wal.GetPenddingCnt())
 }
 
 // append, delete, compact, mergeblocks, ckp
diff --git a/pkg/vm/engine/tae/db/tables_test.go b/pkg/vm/engine/tae/db/tables_test.go
index 15149f68a..e8c6c0e98 100644
--- a/pkg/vm/engine/tae/db/tables_test.go
+++ b/pkg/vm/engine/tae/db/tables_test.go
@@ -61,12 +61,12 @@ func TestTables1(t *testing.T) {
 
 	blkCnt := 3
 	rows := schema.BlockMaxRows * uint32(blkCnt)
-	toAppend, err := appender.PrepareAppend(rows)
+	_, _, toAppend, err := appender.PrepareAppend(rows, nil)
 	assert.Equal(t, schema.BlockMaxRows, toAppend)
 	assert.Nil(t, err)
 	t.Log(toAppend)
 
-	toAppend, err = appender.PrepareAppend(rows - toAppend)
+	_, _, toAppend, err = appender.PrepareAppend(rows-toAppend, nil)
 	assert.Nil(t, err)
 	assert.Equal(t, uint32(0), toAppend)
 
@@ -77,7 +77,7 @@ func TestTables1(t *testing.T) {
 	id = blk.GetMeta().(*catalog.BlockEntry).AsCommonID()
 	appender = handle.SetAppender(id)
 
-	toAppend, err = appender.PrepareAppend(rows - toAppend)
+	_, _, toAppend, err = appender.PrepareAppend(rows-toAppend, nil)
 	assert.Nil(t, err)
 	assert.Equal(t, schema.BlockMaxRows, toAppend)
 
@@ -89,7 +89,7 @@ func TestTables1(t *testing.T) {
 
 	id = blk.GetMeta().(*catalog.BlockEntry).AsCommonID()
 	appender = handle.SetAppender(id)
-	toAppend, err = appender.PrepareAppend(rows - 2*toAppend)
+	_, _, toAppend, err = appender.PrepareAppend(rows-2*toAppend, nil)
 	assert.Nil(t, err)
 	assert.Equal(t, schema.BlockMaxRows, toAppend)
 	t.Log(db.Opts.Catalog.SimplePPString(common.PPL1))
diff --git a/pkg/vm/engine/tae/tables/updates/mvcc_test.go b/pkg/vm/engine/tae/tables/updates/mvcc_test.go
index 7cd72c9d2..68b075a98 100644
--- a/pkg/vm/engine/tae/tables/updates/mvcc_test.go
+++ b/pkg/vm/engine/tae/tables/updates/mvcc_test.go
@@ -34,7 +34,7 @@ func TestMutationControllerAppend(t *testing.T) {
 	for i := 0; i < nodeCnt; i++ {
 		txn := mockTxn()
 		txn.CommitTS = ts
-		node := mc.AddAppendNodeLocked(txn, rowsPerNode*(uint32(i)+1))
+		node, _ := mc.AddAppendNodeLocked(txn, rowsPerNode*(uint32(i)+1))
 		err := node.ApplyCommit(nil)
 		assert.Nil(t, err)
 		queries = append(queries, ts+1)