Repository: alibaba/fescar
Pull request #389 (2019-02-13 02:48:09)

issue #295 reload sessions and locks when restart
<!-- Please make sure you have read and understood the contributing guidelines -->

### Ⅰ. Describe what this PR did

issue #295 reload sessions and locks when restart

### Ⅱ. Does this pull request fix one issue?
<!-- If that, add "fixes #xxx" below in the next line, for example, fixes #97. -->

issue #295 reload sessions and locks when restart

### Ⅲ. Why don't you add test cases (unit test/integration test)? 

NA

### Ⅳ. Describe how to verify it

Kill the working server, restart server, check transactions to be finished.

### Ⅴ. Special notes for reviews



codecov-io: # [Codecov](https://codecov.io/gh/alibaba/fescar/pull/389?src=pr&el=h1) Report
> Merging [#389](https://codecov.io/gh/alibaba/fescar/pull/389?src=pr&el=desc) into [develop](https://codecov.io/gh/alibaba/fescar/commit/4499fc8f5ccb448d4c733af33be16cdb0fa95bbc?src=pr&el=desc) will **increase** coverage by `1.28%`.
> The diff coverage is `73.91%`.

[![Impacted file tree graph](https://codecov.io/gh/alibaba/fescar/pull/389/graphs/tree.svg?width=650&token=Hy9a6MCc4p&height=150&src=pr)](https://codecov.io/gh/alibaba/fescar/pull/389?src=pr&el=tree)

```diff
@@              Coverage Diff              @@
##             develop     #389      +/-   ##
=============================================
+ Coverage       29.3%   30.59%   +1.28%     
- Complexity       572      615      +43     
=============================================
  Files            165      166       +1     
  Lines           6589     6727     +138     
  Branches         786      806      +20     
=============================================
+ Hits            1931     2058     +127     
- Misses          4454     4457       +3     
- Partials         204      212       +8
```


| [Impacted Files](https://codecov.io/gh/alibaba/fescar/pull/389?src=pr&el=tree) | Coverage Δ | Complexity Δ | |
|---|---|---|---|
| [...alibaba/fescar/core/service/ConfigurationKeys.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-Y29yZS9zcmMvbWFpbi9qYXZhL2NvbS9hbGliYWJhL2Zlc2Nhci9jb3JlL3NlcnZpY2UvQ29uZmlndXJhdGlvbktleXMuamF2YQ==) | `0% <ø> (ø)` | `0 <0> (ø)` | :arrow_down: |
| [...rotocol/transaction/AbstractBranchEndResponse.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-Y29yZS9zcmMvbWFpbi9qYXZhL2NvbS9hbGliYWJhL2Zlc2Nhci9jb3JlL3Byb3RvY29sL3RyYW5zYWN0aW9uL0Fic3RyYWN0QnJhbmNoRW5kUmVzcG9uc2UuamF2YQ==) | `52% <0%> (ø)` | `3 <0> (ø)` | :arrow_down: |
| [...scar/server/store/FileTransactionStoreManager.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-c2VydmVyL3NyYy9tYWluL2phdmEvY29tL2FsaWJhYmEvZmVzY2FyL3NlcnZlci9zdG9yZS9GaWxlVHJhbnNhY3Rpb25TdG9yZU1hbmFnZXIuamF2YQ==) | `53.47% <100%> (+1.06%)` | `14 <0> (+3)` | :arrow_up: |
| [...rotocol/transaction/AbstractGlobalEndResponse.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-Y29yZS9zcmMvbWFpbi9qYXZhL2NvbS9hbGliYWJhL2Zlc2Nhci9jb3JlL3Byb3RvY29sL3RyYW5zYWN0aW9uL0Fic3RyYWN0R2xvYmFsRW5kUmVzcG9uc2UuamF2YQ==) | `100% <100%> (ø)` | `6 <0> (ø)` | :arrow_down: |
| [...aba/fescar/server/lock/DefaultLockManagerImpl.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-c2VydmVyL3NyYy9tYWluL2phdmEvY29tL2FsaWJhYmEvZmVzY2FyL3NlcnZlci9sb2NrL0RlZmF1bHRMb2NrTWFuYWdlckltcGwuamF2YQ==) | `84% <100%> (+5.91%)` | `17 <1> (+3)` | :arrow_up: |
| [...m/alibaba/fescar/server/session/BranchSession.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-c2VydmVyL3NyYy9tYWluL2phdmEvY29tL2FsaWJhYmEvZmVzY2FyL3NlcnZlci9zZXNzaW9uL0JyYW5jaFNlc3Npb24uamF2YQ==) | `86.95% <100%> (+2.39%)` | `34 <0> (+2)` | :arrow_up: |
| [...core/protocol/transaction/BranchReportRequest.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-Y29yZS9zcmMvbWFpbi9qYXZhL2NvbS9hbGliYWJhL2Zlc2Nhci9jb3JlL3Byb3RvY29sL3RyYW5zYWN0aW9uL0JyYW5jaFJlcG9ydFJlcXVlc3QuamF2YQ==) | `81.94% <100%> (ø)` | `14 <0> (ø)` | :arrow_down: |
| [...m/alibaba/fescar/server/session/GlobalSession.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-c2VydmVyL3NyYy9tYWluL2phdmEvY29tL2FsaWJhYmEvZmVzY2FyL3NlcnZlci9zZXNzaW9uL0dsb2JhbFNlc3Npb24uamF2YQ==) | `84.82% <100%> (+0.32%)` | `40 <6> (ø)` | :arrow_down: |
| [...alibaba/fescar/server/coordinator/DefaultCore.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-c2VydmVyL3NyYy9tYWluL2phdmEvY29tL2FsaWJhYmEvZmVzY2FyL3NlcnZlci9jb29yZGluYXRvci9EZWZhdWx0Q29yZS5qYXZh) | `27.46% <62.5%> (-3.4%)` | `11 <0> (-1)` | |
| [...fescar/server/session/FileBasedSessionManager.java](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree#diff-c2VydmVyL3NyYy9tYWluL2phdmEvY29tL2FsaWJhYmEvZmVzY2FyL3NlcnZlci9zZXNzaW9uL0ZpbGVCYXNlZFNlc3Npb25NYW5hZ2VyLmphdmE=) | `64.55% <63.15%> (-35.45%)` | `16 <15> (+15)` | |
| ... and [11 more](https://codecov.io/gh/alibaba/fescar/pull/389/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/alibaba/fescar/pull/389?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/alibaba/fescar/pull/389?src=pr&el=footer). Last update [4499fc8...b3d9e7d](https://codecov.io/gh/alibaba/fescar/pull/389?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/core/src/main/java/com/alibaba/fescar/core/model/BranchStatus.java b/core/src/main/java/com/alibaba/fescar/core/model/BranchStatus.java
index 6bab21bf6..7713d3a1a 100644
--- a/core/src/main/java/com/alibaba/fescar/core/model/BranchStatus.java
+++ b/core/src/main/java/com/alibaba/fescar/core/model/BranchStatus.java
@@ -30,97 +30,107 @@ public enum BranchStatus {
      * Unknown branch status.
      */
     // Unknown
-    Unknown,
+    Unknown(0),
 
     /**
      * The Registered.
      */
     // Registered to TC.
-    Registered,
+    Registered(1),
 
     /**
      * The Phase one done.
      */
     // Branch logic is successfully done at phase one.
-    PhaseOne_Done,
+    PhaseOne_Done(2),
 
     /**
      * The Phase one failed.
      */
     // Branch logic is failed at phase one.
-    PhaseOne_Failed,
+    PhaseOne_Failed(3),
 
     /**
      * The Phase one timeout.
      */
     // Branch logic is NOT reported for a timeout.
-    PhaseOne_Timeout,
+    PhaseOne_Timeout(4),
 
     /**
      * The Phase two committed.
      */
     // Commit logic is successfully done at phase two.
-    PhaseTwo_Committed,
+    PhaseTwo_Committed(5),
 
     /**
      * The Phase two commit failed retryable.
      */
     // Commit logic is failed but retryable.
-    PhaseTwo_CommitFailed_Retryable,
+    PhaseTwo_CommitFailed_Retryable(6),
 
     /**
      * The Phase two commit failed unretryable.
      */
     // Commit logic is failed and NOT retryable.
-    PhaseTwo_CommitFailed_Unretryable,
+    PhaseTwo_CommitFailed_Unretryable(7),
 
     /**
      * The Phase two rollbacked.
      */
     // Rollback logic is successfully done at phase two.
-    PhaseTwo_Rollbacked,
+    PhaseTwo_Rollbacked(8),
 
     /**
      * The Phase two rollback failed retryable.
      */
     // Rollback logic is failed but retryable.
-    PhaseTwo_RollbackFailed_Retryable,
+    PhaseTwo_RollbackFailed_Retryable(9),
 
     /**
      * The Phase two rollback failed unretryable.
      */
     // Rollback logic is failed but NOT retryable.
-    PhaseTwo_RollbackFailed_Unretryable;
+    PhaseTwo_RollbackFailed_Unretryable(10);
+
+    private int code;
+
+    BranchStatus(int code) {
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
 
     private static final Map<Integer, BranchStatus> MAP = new HashMap<>(values().length);
 
     static {
         for (BranchStatus status : values()) {
-            MAP.put(status.ordinal(), status);
+            MAP.put(status.getCode(), status);
         }
     }
 
     /**
      * Get branch status.
      *
-     * @param ordinal the ordinal
+     * @param code the code
      * @return the branch status
      */
-    public static BranchStatus get(byte ordinal) {
-        return get((int) ordinal);
+    public static BranchStatus get(byte code) {
+        return get((int) code);
     }
 
     /**
      * Get branch status.
      *
-     * @param ordinal the ordinal
+     * @param code the code
      * @return the branch status
      */
-    public static BranchStatus get(int ordinal) {
-        BranchStatus status = MAP.get(ordinal);
+    public static BranchStatus get(int code) {
+        BranchStatus status = MAP.get(code);
 
         if (null == status) {
-            throw new ShouldNeverHappenException("Unknown BranchStatus[" + ordinal + "]");
+            throw new ShouldNeverHappenException("Unknown BranchStatus[" + code + "]");
         }
 
         return status;
diff --git a/core/src/main/java/com/alibaba/fescar/core/model/GlobalStatus.java b/core/src/main/java/com/alibaba/fescar/core/model/GlobalStatus.java
index 4ea1ea424..1efeec1eb 100644
--- a/core/src/main/java/com/alibaba/fescar/core/model/GlobalStatus.java
+++ b/core/src/main/java/com/alibaba/fescar/core/model/GlobalStatus.java
@@ -28,121 +28,136 @@ public enum GlobalStatus {
      * Un known global status.
      */
     // Unknown
-    UnKnown,
+    UnKnown(0),
 
     /**
      * The Begin.
      */
     // PHASE 1: can accept new branch registering.
-    Begin,
+    Begin(1),
 
     /**
      * PHASE 2: Running Status: may be changed any time.
      */
     // Committing.
-    Committing,
+    Committing(2),
 
     /**
      * The Commit retrying.
      */
     // Retrying commit after a recoverable failure.
-    CommitRetrying,
+    CommitRetrying(3),
 
     /**
      * Rollbacking global status.
      */
     // Rollbacking
-    Rollbacking,
+    Rollbacking(4),
 
     /**
      * The Rollback retrying.
      */
     // Retrying rollback after a recoverable failure.
-    RollbackRetrying,
+    RollbackRetrying(5),
 
     /**
      * The Timeout rollbacking.
      */
     // Rollbacking since timeout
-    TimeoutRollbacking,
+    TimeoutRollbacking(6),
 
     /**
      * The Timeout rollback retrying.
      */
     // Retrying rollback (since timeout) after a recoverable failure.
-    TimeoutRollbackRetrying,
+    TimeoutRollbackRetrying(7),
+
+    /**
+     * All branches can be async committed. The committing is NOT done yet, but it can be seen as committed for TM/RM client.
+     */
+    AsyncCommitting(8),
 
     /**
      * PHASE 2: Final Status: will NOT change any more.
      */
     // Finally: global transaction is successfully committed.
-    Committed,
+    Committed(9),
 
     /**
      * The Commit failed.
      */
     // Finally: failed to commit
-    CommitFailed,
+    CommitFailed(10),
 
     /**
      * The Rollbacked.
      */
     // Finally: global transaction is successfully rollbacked.
-    Rollbacked,
+    Rollbacked(11),
 
     /**
      * The Rollback failed.
      */
     // Finally: failed to rollback
-    RollbackFailed,
+    RollbackFailed(12),
 
     /**
      * The Timeout rollbacked.
      */
     // Finally: global transaction is successfully rollbacked since timeout.
-    TimeoutRollbacked,
+    TimeoutRollbacked(13),
 
     /**
      * The Timeout rollback failed.
      */
     // Finally: failed to rollback since timeout
-    TimeoutRollbackFailed,
+    TimeoutRollbackFailed(14),
 
     /**
      * The Finished.
      */
     // Not managed in session MAP any more
-    Finished;
+    Finished(15);
+
+    private int code;
+
+    GlobalStatus(int code) {
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
 
     private static final Map<Integer, GlobalStatus> MAP = new HashMap<>(values().length);
 
     static {
         for (GlobalStatus status : values()) {
-            MAP.put(status.ordinal(), status);
+            MAP.put(status.code, status);
         }
     }
 
     /**
      * Get global status.
      *
-     * @param ordinal the ordinal
+     * @param code the code
      * @return the global status
      */
-    public static GlobalStatus get(byte ordinal) {
-        return get((int) ordinal);
+    public static GlobalStatus get(byte code) {
+        return get((int) code);
     }
 
     /**
      * Get global status.
      *
-     * @param ordinal the ordinal
+     * @param code the code
      * @return the global status
      */
-    public static GlobalStatus get(int ordinal) {
-        GlobalStatus status = MAP.get(ordinal);
+    public static GlobalStatus get(int code) {
+        GlobalStatus status = MAP.get(code);
 
         if (null == status) {
-            throw new IllegalArgumentException("Unknown GlobalStatus[" + ordinal + "]");
+            throw new IllegalArgumentException("Unknown GlobalStatus[" + code + "]");
         }
 
         return status;
diff --git a/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractBranchEndResponse.java b/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractBranchEndResponse.java
index 7f350ece3..9a4cf87c0 100644
--- a/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractBranchEndResponse.java
+++ b/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractBranchEndResponse.java
@@ -53,7 +53,7 @@ public abstract class AbstractBranchEndResponse extends AbstractTransactionRespo
     @Override
     protected void doEncode() {
         super.doEncode();
-        byteBuffer.put((byte) branchStatus.ordinal());
+        byteBuffer.put((byte) branchStatus.getCode());
     }
 
     @Override
diff --git a/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractGlobalEndResponse.java b/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractGlobalEndResponse.java
index 6c1b8fbd3..dd90ab291 100644
--- a/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractGlobalEndResponse.java
+++ b/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/AbstractGlobalEndResponse.java
@@ -51,7 +51,7 @@ public abstract class AbstractGlobalEndResponse extends AbstractTransactionRespo
     @Override
     protected void doEncode() {
         super.doEncode();
-        byteBuffer.put((byte) globalStatus.ordinal());
+        byteBuffer.put((byte) globalStatus.getCode());
     }
 
     @Override
diff --git a/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/BranchReportRequest.java b/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/BranchReportRequest.java
index b763b0ec0..bcc56a9e5 100644
--- a/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/BranchReportRequest.java
+++ b/core/src/main/java/com/alibaba/fescar/core/protocol/transaction/BranchReportRequest.java
@@ -147,7 +147,7 @@ public class BranchReportRequest extends AbstractTransactionRequestToTC implemen
         // 2. Branch Id
         byteBuffer.putLong(this.branchId);
         // 3. Branch Status
-        byteBuffer.put((byte) this.status.ordinal());
+        byteBuffer.put((byte) this.status.getCode());
         // 4. Resource Id
         if (this.resourceId != null) {
             byte[] bs = resourceId.getBytes(UTF8);
diff --git a/core/src/main/java/com/alibaba/fescar/core/service/ConfigurationKeys.java b/core/src/main/java/com/alibaba/fescar/core/service/ConfigurationKeys.java
index 9bf0d3dbb..3bd67d29b 100644
--- a/core/src/main/java/com/alibaba/fescar/core/service/ConfigurationKeys.java
+++ b/core/src/main/java/com/alibaba/fescar/core/service/ConfigurationKeys.java
@@ -60,4 +60,9 @@ public class ConfigurationKeys {
      * The constant CLIENT_LOCK_RETRY_INTERNAL.
      */
     public static final String CLIENT_LOCK_RETRY_INTERNAL = CLIENT_PREFIX + "lock.retry.internal";
+
+    /**
+     * The constant SERVICE_SESSION_RELOAD_READ_SIZE
+     */
+    public static final String SERVICE_SESSION_RELOAD_READ_SIZE = SERVICE_PREFIX + "session.reload.read_size";
 }
diff --git a/server/src/main/java/com/alibaba/fescar/server/coordinator/DefaultCore.java b/server/src/main/java/com/alibaba/fescar/server/coordinator/DefaultCore.java
index 194ee43c8..486cf2f82 100644
--- a/server/src/main/java/com/alibaba/fescar/server/coordinator/DefaultCore.java
+++ b/server/src/main/java/com/alibaba/fescar/server/coordinator/DefaultCore.java
@@ -23,11 +23,11 @@ import com.alibaba.fescar.core.model.BranchStatus;
 import com.alibaba.fescar.core.model.BranchType;
 import com.alibaba.fescar.core.model.GlobalStatus;
 import com.alibaba.fescar.core.model.ResourceManagerInbound;
-import com.alibaba.fescar.server.UUIDGenerator;
 import com.alibaba.fescar.server.lock.LockManager;
 import com.alibaba.fescar.server.lock.LockManagerFactory;
 import com.alibaba.fescar.server.session.BranchSession;
 import com.alibaba.fescar.server.session.GlobalSession;
+import com.alibaba.fescar.server.session.SessionHelper;
 import com.alibaba.fescar.server.session.SessionHolder;
 
 import org.slf4j.Logger;
@@ -59,15 +59,7 @@ public class DefaultCore implements Core {
     public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String lockKeys) throws TransactionException {
         GlobalSession globalSession = assertGlobalSession(XID.getTransactionId(xid), GlobalStatus.Begin);
 
-        BranchSession branchSession = new BranchSession();
-        branchSession.setTransactionId(XID.getTransactionId(xid));
-        branchSession.setBranchId(UUIDGenerator.generateUUID());
-        branchSession.setApplicationId(globalSession.getApplicationId());
-        branchSession.setTxServiceGroup(globalSession.getTransactionServiceGroup());
-        branchSession.setBranchType(branchType);
-        branchSession.setResourceId(resourceId);
-        branchSession.setLockKey(lockKeys);
-        branchSession.setClientId(clientId);
+        BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId, lockKeys, clientId);
 
         if (!branchSession.lock()) {
             throw new TransactionException(LockKeyConflict);
@@ -140,6 +132,7 @@ public class DefaultCore implements Core {
         globalSession.closeAndClean(); // Highlight: Firstly, close the session, then no more branch can be registered.
 
         if (status == GlobalStatus.Begin) {
+            globalSession.changeStatus(GlobalStatus.Committing);
             if (globalSession.canBeCommittedAsync()) {
                 asyncCommit(globalSession);
             } else {
@@ -170,8 +163,7 @@ public class DefaultCore implements Core {
                             LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession);
                             continue;
                         } else {
-                            globalSession.changeStatus(GlobalStatus.CommitFailed);
-                            globalSession.end();
+                            SessionHelper.endCommitFailed(globalSession);
                             LOGGER.error("Finally, failed to commit global[{}] since branch[{}] commit failed",
                                 globalSession.getTransactionId(), branchSession.getBranchId());
                             return;
@@ -211,14 +203,14 @@ public class DefaultCore implements Core {
             LOGGER.info("Global[{}] committing is NOT done.", globalSession.getTransactionId());
             return;
         }
-        globalSession.changeStatus(GlobalStatus.Committed);
-        globalSession.end();
+        SessionHelper.endCommitted(globalSession);
         LOGGER.info("Global[{}] committing is successfully done.", globalSession.getTransactionId());
     }
 
     private void asyncCommit(GlobalSession globalSession) throws TransactionException {
         globalSession.addSessionLifecycleListener(SessionHolder.getAsyncCommittingSessionManager());
         SessionHolder.getAsyncCommittingSessionManager().addGlobalSession(globalSession);
+        globalSession.changeStatus(GlobalStatus.AsyncCommitting);
     }
 
     private void queueToRetryCommit(GlobalSession globalSession) throws TransactionException {
@@ -273,8 +265,7 @@ public class DefaultCore implements Core {
                         LOGGER.error("Successfully rolled back branch " + branchSession);
                         continue;
                     case PhaseTwo_RollbackFailed_Unretryable:
-                        changeToRollbackFailedStatus(globalSession);
-                        globalSession.end();
+                        SessionHelper.endRollbackFailed(globalSession);
                         LOGGER.error("Failed to rollback global[" + globalSession.getTransactionId() + "] since branch[" + branchSession.getBranchId() + "] rollback failed");
                         return;
                     default:
@@ -300,28 +291,9 @@ public class DefaultCore implements Core {
 
         }
         if (globalSession.hasBranch()) {
-            changeToRollbackFailedStatus(globalSession);
+            SessionHelper.endRollbackFailed(globalSession);
         } else {
-            changeToRollbackedStatus(globalSession);
-        }
-        globalSession.end();
-    }
-
-    private void changeToRollbackedStatus(GlobalSession globalSession) throws TransactionException {
-        GlobalStatus currentStatus = globalSession.getStatus();
-        if (currentStatus.name().startsWith("Timeout")) {
-            globalSession.changeStatus(GlobalStatus.TimeoutRollbacked);
-        } else {
-            globalSession.changeStatus(GlobalStatus.Rollbacked);
-        }
-    }
-
-    private void changeToRollbackFailedStatus(GlobalSession globalSession) throws TransactionException {
-        GlobalStatus currentStatus = globalSession.getStatus();
-        if (currentStatus.name().startsWith("Timeout")) {
-            globalSession.changeStatus(GlobalStatus.TimeoutRollbackFailed);
-        } else {
-            globalSession.changeStatus(GlobalStatus.RollbackFailed);
+            SessionHelper.endRollbacked(globalSession);
         }
     }
 
diff --git a/server/src/main/java/com/alibaba/fescar/server/lock/DefaultLockManagerImpl.java b/server/src/main/java/com/alibaba/fescar/server/lock/DefaultLockManagerImpl.java
index cd636b888..9a603d7b5 100644
--- a/server/src/main/java/com/alibaba/fescar/server/lock/DefaultLockManagerImpl.java
+++ b/server/src/main/java/com/alibaba/fescar/server/lock/DefaultLockManagerImpl.java
@@ -142,4 +142,9 @@ public class DefaultLockManagerImpl implements LockManager {
         }
         return true;
     }
+
+    @Override
+    public void cleanAllLocks() throws TransactionException {
+        LOCK_MAP.clear();
+    }
 }
diff --git a/server/src/main/java/com/alibaba/fescar/server/lock/LockManager.java b/server/src/main/java/com/alibaba/fescar/server/lock/LockManager.java
index 982748516..4e6ed8093 100644
--- a/server/src/main/java/com/alibaba/fescar/server/lock/LockManager.java
+++ b/server/src/main/java/com/alibaba/fescar/server/lock/LockManager.java
@@ -43,4 +43,10 @@ public interface LockManager {
      * @throws TransactionException the transaction exception
      */
     boolean isLockable(long transactionId, String resourceId, String lockKey) throws TransactionException;
+
+    /**
+     * Clean all locks.
+     * @throws TransactionException the transaction exception
+     */
+    void cleanAllLocks() throws TransactionException;
 }
diff --git a/server/src/main/java/com/alibaba/fescar/server/session/BranchSession.java b/server/src/main/java/com/alibaba/fescar/server/session/BranchSession.java
index 03ead8e4a..4231cbeb6 100644
--- a/server/src/main/java/com/alibaba/fescar/server/session/BranchSession.java
+++ b/server/src/main/java/com/alibaba/fescar/server/session/BranchSession.java
@@ -352,6 +352,7 @@ public class BranchSession implements Lockable, Comparable<BranchSession>, Sessi
         } else {
             byteBuffer.putInt(0);
         }
+        byteBuffer.put((byte)status.getCode());
         byteBuffer.flip();
         byte[] result = new byte[byteBuffer.limit()];
         byteBuffer.get(result);
@@ -399,6 +400,7 @@ public class BranchSession implements Lockable, Comparable<BranchSession>, Sessi
             byteBuffer.get(byApplicationData);
             this.applicationData = new String(byApplicationData);
         }
+        this.status = BranchStatus.get(byteBuffer.get());
 
     }
 
diff --git a/server/src/main/java/com/alibaba/fescar/server/session/FileBasedSessionManager.java b/server/src/main/java/com/alibaba/fescar/server/session/FileBasedSessionManager.java
index d45dd17d0..6f52834ef 100644
--- a/server/src/main/java/com/alibaba/fescar/server/session/FileBasedSessionManager.java
+++ b/server/src/main/java/com/alibaba/fescar/server/session/FileBasedSessionManager.java
@@ -17,13 +17,27 @@
 package com.alibaba.fescar.server.session;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
+import com.alibaba.fescar.common.exception.ShouldNeverHappenException;
+import com.alibaba.fescar.config.ConfigurationFactory;
+import com.alibaba.fescar.core.exception.TransactionException;
+import com.alibaba.fescar.core.model.GlobalStatus;
+import com.alibaba.fescar.core.service.ConfigurationKeys;
 import com.alibaba.fescar.server.store.FileTransactionStoreManager;
+import com.alibaba.fescar.server.store.SessionStorable;
+import com.alibaba.fescar.server.store.TransactionStoreManager;
+import com.alibaba.fescar.server.store.TransactionWriteStore;
 
 /**
  * The type File based session manager.
  */
-public class FileBasedSessionManager extends AbstractSessionManager {
+public class FileBasedSessionManager extends AbstractSessionManager implements Reloadable {
+
+    private static int READ_SIZE = ConfigurationFactory.getInstance().getInt(ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE, 100);
 
     /**
      * Instantiates a new File based session manager.
@@ -36,4 +50,134 @@ public class FileBasedSessionManager extends AbstractSessionManager {
         super(name);
         transactionStoreManager = new FileTransactionStoreManager(sessionStoreFilePath + name, this);
     }
+
+    public void reload() {
+        restoreSessions();
+        washSessions();
+    }
+
+    private void restoreSessions() {
+        restoreSessions(true);
+        restoreSessions(false);
+    }
+
+    private void washSessions() {
+        if (sessionMap.size() > 0) {
+            Iterator<Map.Entry<Long, GlobalSession>> iterator = sessionMap.entrySet().iterator();
+            while (iterator.hasNext()) {
+                GlobalSession globalSession = iterator.next().getValue();
+
+                GlobalStatus globalStatus = globalSession.getStatus();
+                switch (globalStatus) {
+                    case UnKnown:
+                    case Committed:
+                    case CommitFailed:
+                    case Rollbacked:
+                    case RollbackFailed:
+                    case TimeoutRollbacked:
+                    case TimeoutRollbackFailed:
+                    case Finished:
+                        // Remove all sessions finished
+                        iterator.remove();
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+
+    private void restoreSessions(boolean isHistory) {
+        while (transactionStoreManager.hasRemaining(isHistory)) {
+            List<TransactionWriteStore> stores = transactionStoreManager.readWriteStoreFromFile(READ_SIZE, isHistory);
+            restore(stores);
+        }
+    }
+
+    private void restore(List<TransactionWriteStore> stores) {
+        for (TransactionWriteStore store : stores) {
+            restore(store);
+        }
+
+    }
+
+    private void restore(TransactionWriteStore store) {
+        TransactionStoreManager.LogOperation logOperation = store.getOperate();
+        SessionStorable sessionStorable = store.getSessionRequest();
+        switch (logOperation) {
+            case GLOBAL_ADD: {
+                GlobalSession globalSession = (GlobalSession)sessionStorable;
+                sessionMap.put(globalSession.getTransactionId(), globalSession);
+                break;
+            }
+            case GLOBAL_UPDATE: {
+                GlobalSession globalSession = (GlobalSession)sessionStorable;
+                long tid = globalSession.getTransactionId();
+                GlobalSession found = sessionMap.get(tid);
+                if (found == null) {
+                    throw new ShouldNeverHappenException("GlobalSession To Be Updated Does Not Exists [" + tid + "]");
+                }
+                found.setStatus(globalSession.getStatus());
+                break;
+            }
+            case GLOBAL_REMOVE:{
+                GlobalSession globalSession = (GlobalSession)sessionStorable;
+                long tid = globalSession.getTransactionId();
+                if (sessionMap.remove(tid) == null) {
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("GlobalSession To Be Removed Does Not Exists [" + tid + "]");
+                    }
+                }
+                break;
+            }
+            case BRANCH_ADD: {
+                BranchSession branchSession = (BranchSession)sessionStorable;
+                long tid = branchSession.getTransactionId();
+                GlobalSession found = sessionMap.get(tid);
+                if (found == null) {
+                    throw new ShouldNeverHappenException("GlobalSession To Be Updated (Add Branch) Does Not Exists [" + tid + "]");
+                }
+                found.add(branchSession);
+                break;
+            }
+            case BRANCH_UPDATE: {
+                BranchSession branchSession = (BranchSession)sessionStorable;
+                long tid = branchSession.getTransactionId();
+                long bid = branchSession.getBranchId();
+                GlobalSession found = sessionMap.get(tid);
+                if (found == null) {
+                    throw new ShouldNeverHappenException("GlobalSession To Be Updated (Update Branch) Does Not Exists [" + bid + "/" + tid + "]");
+                }
+                BranchSession theBranch = found.getBranch(bid);
+                if (theBranch == null) {
+                    throw new ShouldNeverHappenException("BranchSession To Be Updated Does Not Exists [" + bid + "/" + tid + "]");
+                }
+                theBranch.setStatus(branchSession.getStatus());
+                break;
+            }
+            case BRANCH_REMOVE: {
+                BranchSession branchSession = (BranchSession)sessionStorable;
+                long tid = branchSession.getTransactionId();
+                long bid = branchSession.getBranchId();
+                GlobalSession found = sessionMap.get(tid);
+                if (found == null) {
+                    throw new ShouldNeverHappenException("GlobalSession To Be Updated (Remove Branch) Does Not Exists [" + bid + "/" + tid + "]");
+                }
+                BranchSession theBranch = found.getBranch(bid);
+                if (theBranch == null) {
+                    throw new ShouldNeverHappenException("BranchSession To Be Updated Does Not Exists [" + bid + "/" + tid + "]");
+                }
+                if (!found.remove(branchSession)) {
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("BranchSession To Be Removed Does Not Exists [" + bid + "/" + tid + "]");
+                    }
+                }
+                break;
+            }
+
+            default:
+                throw new ShouldNeverHappenException("Unknown Operation: " + logOperation);
+
+        }
+    }
 }
diff --git a/server/src/main/java/com/alibaba/fescar/server/session/GlobalSession.java b/server/src/main/java/com/alibaba/fescar/server/session/GlobalSession.java
index 1f5bdaa45..061541164 100644
--- a/server/src/main/java/com/alibaba/fescar/server/session/GlobalSession.java
+++ b/server/src/main/java/com/alibaba/fescar/server/session/GlobalSession.java
@@ -107,20 +107,20 @@ public class GlobalSession implements SessionLifecycle, SessionStorable {
 
     @Override
     public void changeStatus(GlobalStatus status) throws TransactionException {
+        this.status = status;
         for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
             lifecycleListener.onStatusChange(this, status);
         }
-        this.status = status;
 
     }
 
     @Override
     public void changeBranchStatus(BranchSession branchSession, BranchStatus status)
         throws TransactionException {
+        branchSession.setStatus(status);
         for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
             lifecycleListener.onBranchStatusChange(this, branchSession, status);
         }
-        branchSession.setStatus(status);
     }
 
     @Override
@@ -139,6 +139,9 @@ public class GlobalSession implements SessionLifecycle, SessionStorable {
 
     @Override
     public void end() throws TransactionException {
+        // Clean locks first
+        clean();
+
         for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
             lifecycleListener.onEnd(this);
         }
@@ -387,6 +390,7 @@ public class GlobalSession implements SessionLifecycle, SessionStorable {
             byteBuffer.putShort((short)0);
         }
         byteBuffer.putLong(beginTime);
+        byteBuffer.put((byte)status.getCode());
         byteBuffer.flip();
         byte[] result = new byte[byteBuffer.limit()];
         byteBuffer.get(result);
@@ -417,6 +421,7 @@ public class GlobalSession implements SessionLifecycle, SessionStorable {
             this.transactionName = new String(byTxName);
         }
         this.beginTime = byteBuffer.getLong();
+        this.status = GlobalStatus.get(byteBuffer.get());
     }
 
     /**
diff --git a/server/src/main/java/com/alibaba/fescar/server/session/Reloadable.java b/server/src/main/java/com/alibaba/fescar/server/session/Reloadable.java
new file mode 100644
index 000000000..ada14c309
--- /dev/null
+++ b/server/src/main/java/com/alibaba/fescar/server/session/Reloadable.java
@@ -0,0 +1,12 @@
+package com.alibaba.fescar.server.session;
+
+/**
+ * Service contains states which can be reloaded.
+ */
+public interface Reloadable {
+
+    /**
+     * Reload states.
+     */
+    void reload();
+}
diff --git a/server/src/main/java/com/alibaba/fescar/server/session/SessionHelper.java b/server/src/main/java/com/alibaba/fescar/server/session/SessionHelper.java
new file mode 100644
index 000000000..107670e20
--- /dev/null
+++ b/server/src/main/java/com/alibaba/fescar/server/session/SessionHelper.java
@@ -0,0 +1,57 @@
+package com.alibaba.fescar.server.session;
+
+import com.alibaba.fescar.common.XID;
+import com.alibaba.fescar.core.exception.TransactionException;
+import com.alibaba.fescar.core.model.BranchType;
+import com.alibaba.fescar.core.model.GlobalStatus;
+import com.alibaba.fescar.server.UUIDGenerator;
+
+public class SessionHelper {
+
+    private SessionHelper() {}
+
+    public static BranchSession newBranchByGlobal(GlobalSession globalSession, BranchType branchType, String resourceId, String lockKeys, String clientId) {
+        BranchSession branchSession = new BranchSession();
+
+        branchSession.setTransactionId(globalSession.getTransactionId());
+        branchSession.setBranchId(UUIDGenerator.generateUUID());
+        branchSession.setApplicationId(globalSession.getApplicationId());
+        branchSession.setTxServiceGroup(globalSession.getTransactionServiceGroup());
+        branchSession.setBranchType(branchType);
+        branchSession.setResourceId(resourceId);
+        branchSession.setLockKey(lockKeys);
+        branchSession.setClientId(clientId);
+
+        return branchSession;
+    }
+
+    public static void endCommitted(GlobalSession globalSession) throws TransactionException {
+        globalSession.changeStatus(GlobalStatus.Committed);
+        globalSession.end();
+    }
+
+    public static void endCommitFailed(GlobalSession globalSession) throws TransactionException {
+        globalSession.changeStatus(GlobalStatus.CommitFailed);
+        globalSession.end();
+    }
+
+    public static void endRollbacked(GlobalSession globalSession) throws TransactionException {
+        GlobalStatus currentStatus = globalSession.getStatus();
+        if (currentStatus.name().startsWith("Timeout")) {
+            globalSession.changeStatus(GlobalStatus.TimeoutRollbacked);
+        } else {
+            globalSession.changeStatus(GlobalStatus.Rollbacked);
+        }
+        globalSession.end();
+    }
+
+    public static void endRollbackFailed(GlobalSession globalSession) throws TransactionException {
+        GlobalStatus currentStatus = globalSession.getStatus();
+        if (currentStatus.name().startsWith("Timeout")) {
+            globalSession.changeStatus(GlobalStatus.TimeoutRollbackFailed);
+        } else {
+            globalSession.changeStatus(GlobalStatus.RollbackFailed);
+        }
+        globalSession.end();
+    }
+}
diff --git a/server/src/main/java/com/alibaba/fescar/server/session/SessionHolder.java b/server/src/main/java/com/alibaba/fescar/server/session/SessionHolder.java
index 17c01b5fa..9c376a58f 100644
--- a/server/src/main/java/com/alibaba/fescar/server/session/SessionHolder.java
+++ b/server/src/main/java/com/alibaba/fescar/server/session/SessionHolder.java
@@ -17,26 +17,32 @@
 package com.alibaba.fescar.server.session;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
 
 import com.alibaba.fescar.common.exception.ShouldNeverHappenException;
 import com.alibaba.fescar.core.exception.TransactionException;
+import com.alibaba.fescar.core.model.GlobalStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The type Session holder.
  */
 public class SessionHolder {
 
-    private static final String ROOT_SESSION_MANAGER_NAME = "root.data";
-    private static final String ASYNC_COMMITTING_SESSION_MANAGER_NAME = "async.commit.data";
-    private static final String RETRY_COMMITTING_SESSION_MANAGER_NAME = "retry.commit.data";
-    private static final String RETRY_ROLLBACKING_SESSION_MANAGER_NAME = "retry.rollback.data";
+    private static final Logger LOGGER = LoggerFactory.getLogger(SessionHolder.class);
 
-    private static SessionManager ROOT_SESSION_MANAGER;
+    public static final String ROOT_SESSION_MANAGER_NAME = "root.data";
+    public static final String ASYNC_COMMITTING_SESSION_MANAGER_NAME = "async.commit.data";
+    public static final String RETRY_COMMITTING_SESSION_MANAGER_NAME = "retry.commit.data";
+    public static final String RETRY_ROLLBACKING_SESSION_MANAGER_NAME = "retry.rollback.data";
 
+    private static SessionManager ROOT_SESSION_MANAGER;
     private static SessionManager ASYNC_COMMITTING_SESSION_MANAGER;
-
     private static SessionManager RETRY_COMMITTING_SESSION_MANAGER;
-
     private static SessionManager RETRY_ROLLBACKING_SESSION_MANAGER;
 
     /**
@@ -62,6 +68,81 @@ public class SessionHolder {
 
         }
 
+        if (ROOT_SESSION_MANAGER instanceof Reloadable) {
+            ((Reloadable)ROOT_SESSION_MANAGER).reload();
+
+            Collection<GlobalSession> reloadedSessions = ROOT_SESSION_MANAGER.allSessions();
+            if (reloadedSessions != null && !reloadedSessions.isEmpty()) {
+                reloadedSessions.forEach(globalSession -> {
+                    GlobalStatus globalStatus = globalSession.getStatus();
+                    switch (globalStatus) {
+                        case UnKnown:
+                        case Committed:
+                        case CommitFailed:
+                        case Rollbacked:
+                        case RollbackFailed:
+                        case TimeoutRollbacked:
+                        case TimeoutRollbackFailed:
+                        case Finished:
+                            throw new ShouldNeverHappenException("Reloaded Session should NOT be " + globalStatus);
+                        case AsyncCommitting:
+                            try {
+                                globalSession.addSessionLifecycleListener(getAsyncCommittingSessionManager());
+                                getAsyncCommittingSessionManager().addGlobalSession(globalSession);
+                            } catch (TransactionException e) {
+                                throw new ShouldNeverHappenException(e);
+                            }
+                            break;
+                        default: {
+                            ArrayList<BranchSession> branchSessions = globalSession.getSortedBranches();
+                            // Lock
+                            branchSessions.forEach(branchSession -> {
+                                try {
+                                    branchSession.lock();
+                                } catch (TransactionException e) {
+                                    throw new ShouldNeverHappenException(e);
+                                }
+                            });
+
+                            switch (globalStatus) {
+                                case Committing:
+                                case CommitRetrying:
+                                    try {
+                                        globalSession.addSessionLifecycleListener(
+                                            getRetryCommittingSessionManager());
+                                        getRetryCommittingSessionManager().addGlobalSession(globalSession);
+                                    } catch (TransactionException e) {
+                                        throw new ShouldNeverHappenException(e);
+                                    }
+                                    break;
+                                case Rollbacking:
+                                case RollbackRetrying:
+                                case TimeoutRollbacking:
+                                case TimeoutRollbackRetrying:
+                                    try {
+                                        globalSession.addSessionLifecycleListener(
+                                            getRetryRollbackingSessionManager());
+                                        getRetryRollbackingSessionManager().addGlobalSession(globalSession);
+                                    } catch (TransactionException e) {
+                                        throw new ShouldNeverHappenException(e);
+                                    }
+                                    break;
+                                case Begin:
+                                    globalSession.setActive(true);
+                                    break;
+                                default:
+                                    throw new ShouldNeverHappenException("NOT properly handled " + globalStatus);
+                            }
+
+                            break;
+
+                        }
+                    }
+
+                });
+            }
+        }
+
     }
 
     /**
diff --git a/server/src/main/java/com/alibaba/fescar/server/store/FileTransactionStoreManager.java b/server/src/main/java/com/alibaba/fescar/server/store/FileTransactionStoreManager.java
index ebf68e135..ad54ee67c 100644
--- a/server/src/main/java/com/alibaba/fescar/server/store/FileTransactionStoreManager.java
+++ b/server/src/main/java/com/alibaba/fescar/server/store/FileTransactionStoreManager.java
@@ -70,8 +70,8 @@ public class FileTransactionStoreManager implements TransactionStoreManager {
     private File currDataFile;
     private RandomAccessFile currRaf;
     private FileChannel currFileChannel;
-    private static long recoverCurrOffset = 0;
-    private static long recoverHisOffset = 0;
+    private long recoverCurrOffset = 0;
+    private long recoverHisOffset = 0;
     private SessionManager sessionManager;
     private String currFullFileName;
     private String hisFullFileName;


Test patch:
diff --git a/core/src/test/java/com/alibaba/fescar/core/message/GlobalCommitResponseTest.java b/core/src/test/java/com/alibaba/fescar/core/message/GlobalCommitResponseTest.java
index 81e1305dc..65e738e53 100644
--- a/core/src/test/java/com/alibaba/fescar/core/message/GlobalCommitResponseTest.java
+++ b/core/src/test/java/com/alibaba/fescar/core/message/GlobalCommitResponseTest.java
@@ -72,7 +72,7 @@ public class GlobalCommitResponseTest {
         String encodeResultStr = Arrays.toString(encodeResult);
         System.out.println(encodeResultStr);
 
-        Assert.assertEquals("[1, 0, 8]", encodeResultStr);
+        Assert.assertEquals("[1, 0, 9]", encodeResultStr);
     }
 
     /**
diff --git a/server/src/test/java/com/alibaba/fescar/server/coordinator/DefaultCoreTest.java b/server/src/test/java/com/alibaba/fescar/server/coordinator/DefaultCoreTest.java
index b4d887962..121f10f1b 100644
--- a/server/src/test/java/com/alibaba/fescar/server/coordinator/DefaultCoreTest.java
+++ b/server/src/test/java/com/alibaba/fescar/server/coordinator/DefaultCoreTest.java
@@ -15,8 +15,6 @@
  */
 package com.alibaba.fescar.server.coordinator;
 
-import java.util.Collection;
-
 import com.alibaba.fescar.common.XID;
 import com.alibaba.fescar.core.model.BranchStatus;
 import com.alibaba.fescar.core.model.BranchType;
@@ -24,13 +22,14 @@ import com.alibaba.fescar.core.model.GlobalStatus;
 import com.alibaba.fescar.server.session.BranchSession;
 import com.alibaba.fescar.server.session.GlobalSession;
 import com.alibaba.fescar.server.session.SessionHolder;
-
 import org.testng.Assert;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+import java.util.Collection;
+
 /**
  * The type Default core test.
  *
@@ -124,7 +123,7 @@ public class DefaultCoreTest {
     @Test(dataProvider = "xidProvider")
     public void commitTest(String xid) throws Exception {
         GlobalStatus globalStatus = core.commit(xid);
-        Assert.assertEquals(globalStatus, GlobalStatus.Begin);
+        Assert.assertNotEquals(globalStatus, GlobalStatus.Begin);
     }
 
     /**
diff --git a/server/src/test/java/com/alibaba/fescar/server/store/FileTransactionStoreManagerTest.java b/server/src/test/java/com/alibaba/fescar/server/store/FileTransactionStoreManagerTest.java
deleted file mode 100644
index 3c768a3bd..000000000
--- a/server/src/test/java/com/alibaba/fescar/server/store/FileTransactionStoreManagerTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *  Copyright 1999-2018 Alibaba Group Holding Ltd.
- *
- *  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 com.alibaba.fescar.server.store;
-
-import java.util.List;
-
-import com.alibaba.fescar.server.session.FileBasedSessionManager;
-import com.alibaba.fescar.server.session.GlobalSession;
-import com.alibaba.fescar.server.session.SessionManager;
-
-import org.junit.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-/**
- * The type File transaction store manager test.
- *
- * @author tianming.xm @gmail.com
- * @since 2019 /1/25
- */
-public class FileTransactionStoreManagerTest {
-    private FileTransactionStoreManager fileTransactionStoreManager;
-
-    /**
-     * Sets up.
-     *
-     * @throws Exception the exception
-     */
-    @BeforeClass
-    public void setUp() throws Exception {
-        SessionManager sessionManager = new FileBasedSessionManager("default", "root.data");
-        fileTransactionStoreManager = new FileTransactionStoreManager("root.data", sessionManager);
-    }
-
-    /**
-     * Tear down.
-     */
-    @AfterClass
-    public void tearDown() {
-        fileTransactionStoreManager.shutdown();
-    }
-
-    /**
-     * Write session test.
-     *
-     * @param globalSession the global session
-     */
-    @Test(dataProvider = "sessionProvider")
-    public void writeSessionTest(GlobalSession globalSession) {
-        boolean result = fileTransactionStoreManager.writeSession(TransactionStoreManager.LogOperation.GLOBAL_ADD,
-            globalSession);
-        Assert.assertTrue(result);
-    }
-
-    /**
-     * Read write store from file test.
-     *
-     * @param globalSession the global session
-     */
-    @Test(dataProvider = "sessionProvider")
-    public void readWriteStoreFromFileTest(GlobalSession globalSession) {
-        fileTransactionStoreManager.writeSession(TransactionStoreManager.LogOperation.GLOBAL_ADD, globalSession);
-        List<TransactionWriteStore> stores = fileTransactionStoreManager.readWriteStoreFromFile(100, false);
-        Assert.assertNotNull(stores);
-        Assert.assertTrue(stores.size() > 0);
-    }
-
-    /**
-     * Session provider object [ ] [ ].
-     *
-     * @return the object [ ] [ ]
-     */
-    @DataProvider
-    public static Object[][] sessionProvider() {
-        GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
-        return new Object[][] {{globalSession}};
-    }
-
-}
diff --git a/server/src/test/java/com/alibaba/fescar/server/store/SessionStoreTest.java b/server/src/test/java/com/alibaba/fescar/server/store/SessionStoreTest.java
new file mode 100644
index 000000000..d05146fbb
--- /dev/null
+++ b/server/src/test/java/com/alibaba/fescar/server/store/SessionStoreTest.java
@@ -0,0 +1,248 @@
+package com.alibaba.fescar.server.store;
+
+import com.alibaba.fescar.core.model.BranchStatus;
+import com.alibaba.fescar.core.model.BranchType;
+import com.alibaba.fescar.core.model.GlobalStatus;
+import com.alibaba.fescar.server.lock.LockManager;
+import com.alibaba.fescar.server.lock.LockManagerFactory;
+import com.alibaba.fescar.server.session.BranchSession;
+import com.alibaba.fescar.server.session.GlobalSession;
+import com.alibaba.fescar.server.session.SessionHelper;
+import com.alibaba.fescar.server.session.SessionHolder;
+import org.junit.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+public class SessionStoreTest {
+
+    public static final String RESOURCE_ID = "mysql:xxx";
+
+    @BeforeMethod
+    public void clean() throws Exception {
+        File rootDataFile = new File("./" + SessionHolder.ROOT_SESSION_MANAGER_NAME);
+        File rootDataFileHis = new File("./" + SessionHolder.ROOT_SESSION_MANAGER_NAME + ".1");
+
+        if (rootDataFile.exists()) {
+            rootDataFile.delete();
+            System.currentTimeMillis();
+        }
+        if (rootDataFileHis.exists()) {
+            rootDataFileHis.delete();
+        }
+        LockManagerFactory.get().cleanAllLocks();
+    }
+
+    @Test
+    public void testRestoredFromFile() throws Exception {
+        SessionHolder.init(".");
+        GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
+
+        globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
+        globalSession.begin();
+
+        BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID, "ta:1,2;tb:3", "xxx");
+        branchSession1.lock();
+        globalSession.addBranch(branchSession1);
+
+        LockManager lockManager = LockManagerFactory.get();
+
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
+
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:4"));
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:5"));
+
+        lockManager.cleanAllLocks();
+
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
+
+        // Re-init SessionHolder: restore sessions from file
+        SessionHolder.init(".");
+
+        long tid = globalSession.getTransactionId();
+        GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
+        Assert.assertNotNull(reloadSession);
+        Assert.assertFalse(globalSession == reloadSession);
+        Assert.assertEquals(globalSession.getApplicationId(), reloadSession.getApplicationId());
+
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
+        Assert.assertTrue(lockManager.isLockable(globalSession.getTransactionId(), RESOURCE_ID, "tb:3"));
+
+    }
+
+    //@Test
+    public void testRestoredFromFile2() throws Exception {
+        SessionHolder.init(".");
+        GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
+
+        globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
+        globalSession.begin();
+
+        // Re-init SessionHolder: restore sessions from file
+        SessionHolder.init(".");
+    }
+
+    @Test
+    public void testRestoredFromFileAsyncCommitting() throws Exception {
+        SessionHolder.init(".");
+        GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
+
+        globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
+        globalSession.begin();
+
+        BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID, "ta:1", "xxx");
+        Assert.assertTrue(branchSession1.lock());
+        globalSession.addBranch(branchSession1);
+
+        LockManager lockManager = LockManagerFactory.get();
+
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        globalSession.changeStatus(GlobalStatus.AsyncCommitting);
+
+        lockManager.cleanAllLocks();
+
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        // Re-init SessionHolder: restore sessions from file
+        SessionHolder.init(".");
+
+        long tid = globalSession.getTransactionId();
+        GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
+        Assert.assertEquals(reloadSession.getStatus(), GlobalStatus.AsyncCommitting);
+
+        GlobalSession sessionInAsyncCommittingQueue = SessionHolder.getAsyncCommittingSessionManager().findGlobalSession(tid);
+        Assert.assertTrue(reloadSession == sessionInAsyncCommittingQueue);
+
+        // No locking for session in AsyncCommitting status
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+    }
+
+    @Test
+    public void testRestoredFromFileCommitRetry() throws Exception {
+        SessionHolder.init(".");
+        GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
+
+        globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
+        globalSession.begin();
+
+        BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID, "ta:1", "xxx");
+        branchSession1.lock();
+        globalSession.addBranch(branchSession1);
+
+        LockManager lockManager = LockManagerFactory.get();
+
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        globalSession.changeStatus(GlobalStatus.Committing);
+        globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Retryable);
+        globalSession.changeStatus(GlobalStatus.CommitRetrying);
+
+        lockManager.cleanAllLocks();
+
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        // Re-init SessionHolder: restore sessions from file
+        SessionHolder.init(".");
+
+        long tid = globalSession.getTransactionId();
+        GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
+        Assert.assertEquals(reloadSession.getStatus(), GlobalStatus.CommitRetrying);
+
+        GlobalSession sessionInRetryCommittingQueue = SessionHolder.getRetryCommittingSessionManager().findGlobalSession(tid);
+        Assert.assertTrue(reloadSession == sessionInRetryCommittingQueue);
+        BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId());
+        Assert.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_CommitFailed_Retryable);
+
+        // Lock is held by session in CommitRetrying status
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+    }
+
+    @Test
+    public void testRestoredFromFileRollbackRetry() throws Exception {
+        SessionHolder.init(".");
+        GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
+
+        globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
+        globalSession.begin();
+
+        BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID, "ta:1", "xxx");
+        branchSession1.lock();
+        globalSession.addBranch(branchSession1);
+
+        LockManager lockManager = LockManagerFactory.get();
+
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        globalSession.changeStatus(GlobalStatus.Rollbacking);
+        globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_RollbackFailed_Retryable);
+        globalSession.changeStatus(GlobalStatus.RollbackRetrying);
+
+        lockManager.cleanAllLocks();
+
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        // Re-init SessionHolder: restore sessions from file
+        SessionHolder.init(".");
+
+        long tid = globalSession.getTransactionId();
+        GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
+        Assert.assertEquals(reloadSession.getStatus(), GlobalStatus.RollbackRetrying);
+
+        GlobalSession sessionInRetryRollbackingQueue = SessionHolder.getRetryRollbackingSessionManager().findGlobalSession(tid);
+        Assert.assertTrue(reloadSession == sessionInRetryRollbackingQueue);
+        BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId());
+        Assert.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_RollbackFailed_Retryable);
+
+        // Lock is held by session in RollbackRetrying status
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+    }
+
+    @Test
+    public void testRestoredFromFileRollbackFailed() throws Exception {
+        SessionHolder.init(".");
+        GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
+
+        globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
+        globalSession.begin();
+
+        BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID, "ta:1", "xxx");
+        branchSession1.lock();
+        globalSession.addBranch(branchSession1);
+
+        LockManager lockManager = LockManagerFactory.get();
+
+        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        globalSession.changeStatus(GlobalStatus.Rollbacking);
+        globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Unretryable);
+        SessionHelper.endRollbackFailed(globalSession);
+
+        // Lock is released.
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        lockManager.cleanAllLocks();
+
+        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+
+        // Re-init SessionHolder: restore sessions from file
+        SessionHolder.init(".");
+
+        long tid = globalSession.getTransactionId();
+        GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
+        Assert.assertNull(reloadSession);
+
+    }
+}