From 9967ca1551dbf383210008eda646b94ce17ca7d0 Mon Sep 17 00:00:00 2001
From: pigxcloud <2270033969@qq.com>
Date: Tue, 21 May 2019 15:31:57 +0800
Subject: [PATCH] seata
---
pigx-upms/pigx-upms-biz/pom.xml | 5 +
pigx-visual/pigx-seata-server/pom.xml | 48 ++
.../server/AbstractTCInboundHandler.java | 240 +++++++
.../src/main/java/io/seata/server/Server.java | 78 +++
.../java/io/seata/server/UUIDGenerator.java | 96 +++
.../io/seata/server/coordinator/Core.java | 55 ++
.../seata/server/coordinator/CoreFactory.java | 46 ++
.../coordinator/DefaultCoordinator.java | 362 +++++++++++
.../seata/server/coordinator/DefaultCore.java | 310 +++++++++
.../server/lock/DefaultLockManagerImpl.java | 186 ++++++
.../io/seata/server/lock/LockManager.java | 63 ++
.../seata/server/lock/LockManagerFactory.java | 46 ++
.../session/AbstractSessionManager.java | 191 ++++++
.../seata/server/session/BranchSession.java | 395 ++++++++++++
.../server/session/DefaultSessionManager.java | 65 ++
.../session/FileBasedSessionManager.java | 232 +++++++
.../seata/server/session/GlobalSession.java | 541 ++++++++++++++++
.../io/seata/server/session/Lockable.java | 42 ++
.../io/seata/server/session/Reloadable.java | 29 +
.../server/session/SessionCondition.java | 55 ++
.../seata/server/session/SessionHelper.java | 121 ++++
.../seata/server/session/SessionHolder.java | 242 +++++++
.../server/session/SessionLifecycle.java | 89 +++
.../session/SessionLifecycleListener.java | 90 +++
.../seata/server/session/SessionManager.java | 109 ++++
.../store/FileTransactionStoreManager.java | 590 ++++++++++++++++++
.../io/seata/server/store/FlushDiskMode.java | 44 ++
.../seata/server/store/SessionStorable.java | 38 ++
.../io/seata/server/store/StoreConfig.java | 56 ++
.../server/store/TransactionStoreManager.java | 118 ++++
.../server/store/TransactionWriteStore.java | 129 ++++
.../src/main/resources/logback.xml | 54 ++
.../src/main/resources/registry.conf | 71 +++
pigx-visual/pom.xml | 1 +
34 files changed, 4837 insertions(+)
create mode 100755 pigx-visual/pigx-seata-server/pom.xml
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManager.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/LockManagerFactory.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/AbstractSessionManager.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/BranchSession.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/DefaultSessionManager.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/FileBasedSessionManager.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/GlobalSession.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Lockable.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/Reloadable.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionCondition.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHelper.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionHolder.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycle.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionLifecycleListener.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/session/SessionManager.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/FlushDiskMode.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/SessionStorable.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/StoreConfig.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionStoreManager.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/java/io/seata/server/store/TransactionWriteStore.java
create mode 100755 pigx-visual/pigx-seata-server/src/main/resources/logback.xml
create mode 100755 pigx-visual/pigx-seata-server/src/main/resources/registry.conf
diff --git a/pigx-upms/pigx-upms-biz/pom.xml b/pigx-upms/pigx-upms-biz/pom.xml
index bee4afd42..009eda897 100644
--- a/pigx-upms/pigx-upms-biz/pom.xml
+++ b/pigx-upms/pigx-upms-biz/pom.xml
@@ -92,6 +92,11 @@
mysql
mysql-connector-java
+
+
+ org.springframework.cloud
+ spring-cloud-starter-alibaba-seata
+
org.springframework.boot
diff --git a/pigx-visual/pigx-seata-server/pom.xml b/pigx-visual/pigx-seata-server/pom.xml
new file mode 100755
index 000000000..1d9c33897
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+
+ com.pig4cloud
+ pigx-visual
+ 3.0.0
+
+
+ 4.0.0
+ pigx-seata-server
+ jar
+ pigx-seata-server
+
+
+
+ io.seata
+ seata-core
+ 0.5.2
+
+
+ io.seata
+ seata-config-all
+ 0.5.2
+
+
+ io.seata
+ seata-discovery-all
+ 0.5.2
+
+
+
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
new file mode 100755
index 000000000..d6655196e
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server;
+
+import io.seata.common.XID;
+import io.seata.core.exception.AbstractExceptionHandler;
+import io.seata.core.exception.TransactionException;
+import io.seata.core.model.GlobalStatus;
+import io.seata.core.protocol.transaction.BranchRegisterRequest;
+import io.seata.core.protocol.transaction.BranchRegisterResponse;
+import io.seata.core.protocol.transaction.BranchReportRequest;
+import io.seata.core.protocol.transaction.BranchReportResponse;
+import io.seata.core.protocol.transaction.GlobalBeginRequest;
+import io.seata.core.protocol.transaction.GlobalBeginResponse;
+import io.seata.core.protocol.transaction.GlobalCommitRequest;
+import io.seata.core.protocol.transaction.GlobalCommitResponse;
+import io.seata.core.protocol.transaction.GlobalLockQueryRequest;
+import io.seata.core.protocol.transaction.GlobalLockQueryResponse;
+import io.seata.core.protocol.transaction.GlobalRollbackRequest;
+import io.seata.core.protocol.transaction.GlobalRollbackResponse;
+import io.seata.core.protocol.transaction.GlobalStatusRequest;
+import io.seata.core.protocol.transaction.GlobalStatusResponse;
+import io.seata.core.protocol.transaction.TCInboundHandler;
+import io.seata.core.rpc.RpcContext;
+import io.seata.server.session.GlobalSession;
+import io.seata.server.session.SessionHolder;
+
+/**
+ * The type Abstract tc inbound handler.
+ *
+ * @author sharajava
+ */
+public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler implements TCInboundHandler {
+
+ @Override
+ public GlobalBeginResponse handle(GlobalBeginRequest request, final RpcContext rpcContext) {
+ GlobalBeginResponse response = new GlobalBeginResponse();
+ exceptionHandleTemplate(new AbstractCallback() {
+ @Override
+ public void execute(GlobalBeginRequest request, GlobalBeginResponse response) throws TransactionException {
+ doGlobalBegin(request, response, rpcContext);
+ }
+ }, request, response);
+ return response;
+ }
+
+ /**
+ * Do global begin.
+ *
+ * @param request the request
+ * @param response the response
+ * @param rpcContext the rpc context
+ * @throws TransactionException the transaction exception
+ */
+ protected abstract void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response,
+ RpcContext rpcContext) throws TransactionException;
+
+ @Override
+ public GlobalCommitResponse handle(GlobalCommitRequest request, final RpcContext rpcContext) {
+ GlobalCommitResponse response = new GlobalCommitResponse();
+ exceptionHandleTemplate(new AbstractCallback() {
+ @Override
+ public void execute(GlobalCommitRequest request, GlobalCommitResponse response)
+ throws TransactionException {
+ doGlobalCommit(request, response, rpcContext);
+ }
+ }, request, response);
+ return response;
+ }
+
+ /**
+ * Do global commit.
+ *
+ * @param request the request
+ * @param response the response
+ * @param rpcContext the rpc context
+ * @throws TransactionException the transaction exception
+ */
+ protected abstract void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response,
+ RpcContext rpcContext) throws TransactionException;
+
+ @Override
+ public GlobalRollbackResponse handle(GlobalRollbackRequest request, final RpcContext rpcContext) {
+ GlobalRollbackResponse response = new GlobalRollbackResponse();
+ exceptionHandleTemplate(new AbstractCallback() {
+ @Override
+ public void execute(GlobalRollbackRequest request, GlobalRollbackResponse response)
+ throws TransactionException {
+ doGlobalRollback(request, response, rpcContext);
+ }
+
+ @Override
+ public void onTransactionException(GlobalRollbackRequest request, GlobalRollbackResponse response,
+ TransactionException tex) {
+ super.onTransactionException(request, response, tex);
+ GlobalSession globalSession = SessionHolder.findGlobalSession(
+ XID.getTransactionId(request.getXid()));
+ if (globalSession != null) {
+ response.setGlobalStatus(globalSession.getStatus());
+ } else {
+ response.setGlobalStatus(GlobalStatus.Finished);
+ }
+ }
+
+ @Override
+ public void onException(GlobalRollbackRequest request, GlobalRollbackResponse response, Exception rex) {
+ super.onException(request, response, rex);
+ GlobalSession globalSession = SessionHolder.findGlobalSession(
+ XID.getTransactionId(request.getXid()));
+ if (globalSession != null) {
+ response.setGlobalStatus(globalSession.getStatus());
+ } else {
+ response.setGlobalStatus(GlobalStatus.Finished);
+ }
+ }
+ }, request, response);
+ return response;
+ }
+
+ /**
+ * Do global rollback.
+ *
+ * @param request the request
+ * @param response the response
+ * @param rpcContext the rpc context
+ * @throws TransactionException the transaction exception
+ */
+ protected abstract void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response,
+ RpcContext rpcContext) throws TransactionException;
+
+ @Override
+ public BranchRegisterResponse handle(BranchRegisterRequest request, final RpcContext rpcContext) {
+ BranchRegisterResponse response = new BranchRegisterResponse();
+ exceptionHandleTemplate(new AbstractCallback() {
+ @Override
+ public void execute(BranchRegisterRequest request, BranchRegisterResponse response)
+ throws TransactionException {
+ doBranchRegister(request, response, rpcContext);
+ }
+ }, request, response);
+ return response;
+ }
+
+ /**
+ * Do branch register.
+ *
+ * @param request the request
+ * @param response the response
+ * @param rpcContext the rpc context
+ * @throws TransactionException the transaction exception
+ */
+ protected abstract void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response,
+ RpcContext rpcContext) throws TransactionException;
+
+ @Override
+ public BranchReportResponse handle(BranchReportRequest request, final RpcContext rpcContext) {
+ BranchReportResponse response = new BranchReportResponse();
+ exceptionHandleTemplate(new AbstractCallback() {
+ @Override
+ public void execute(BranchReportRequest request, BranchReportResponse response)
+ throws TransactionException {
+ doBranchReport(request, response, rpcContext);
+ }
+ }, request, response);
+ return response;
+ }
+
+ /**
+ * Do branch report.
+ *
+ * @param request the request
+ * @param rpcContext the rpc context
+ * @throws TransactionException the transaction exception
+ */
+ protected abstract void doBranchReport(BranchReportRequest request, BranchReportResponse response,
+ RpcContext rpcContext)
+ throws TransactionException;
+
+ @Override
+ public GlobalLockQueryResponse handle(GlobalLockQueryRequest request, final RpcContext rpcContext) {
+ GlobalLockQueryResponse response = new GlobalLockQueryResponse();
+ exceptionHandleTemplate(new AbstractCallback() {
+ @Override
+ public void execute(GlobalLockQueryRequest request, GlobalLockQueryResponse response)
+ throws TransactionException {
+ doLockCheck(request, response, rpcContext);
+ }
+ }, request, response);
+ return response;
+ }
+
+ /**
+ * Do lock check.
+ *
+ * @param request the request
+ * @param response the response
+ * @param rpcContext the rpc context
+ * @throws TransactionException the transaction exception
+ */
+ protected abstract void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response,
+ RpcContext rpcContext) throws TransactionException;
+
+ @Override
+ public GlobalStatusResponse handle(GlobalStatusRequest request, final RpcContext rpcContext) {
+ GlobalStatusResponse response = new GlobalStatusResponse();
+ exceptionHandleTemplate(new AbstractCallback() {
+ @Override
+ public void execute(GlobalStatusRequest request, GlobalStatusResponse response)
+ throws TransactionException {
+ doGlobalStatus(request, response, rpcContext);
+ }
+ }, request, response);
+ return response;
+ }
+
+ /**
+ * Do global status.
+ *
+ * @param request the request
+ * @param response the response
+ * @param rpcContext the rpc context
+ * @throws TransactionException the transaction exception
+ */
+ protected abstract void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response,
+ RpcContext rpcContext) throws TransactionException;
+
+}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java
new file mode 100755
index 000000000..43df651ee
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/Server.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server;
+
+import io.seata.common.XID;
+import io.seata.common.thread.NamedThreadFactory;
+import io.seata.common.util.NetUtil;
+import io.seata.core.rpc.netty.RpcServer;
+import io.seata.core.rpc.netty.ShutdownHook;
+import io.seata.server.coordinator.DefaultCoordinator;
+import io.seata.server.session.SessionHolder;
+
+import java.io.IOException;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * The type Server.
+ *
+ * @author jimin.jm @alibaba-inc.com
+ */
+public class Server {
+
+ private static final int MIN_SERVER_POOL_SIZE = 10;
+ private static final int MAX_SERVER_POOL_SIZE = 50;
+ private static final int MAX_TASK_QUEUE_SIZE = 2000;
+ private static final int KEEP_ALIVE_TIME = 50;
+ private static final int SERVER_DEFAULT_PORT = 8091;
+ private static final ThreadPoolExecutor WORKING_THREADS = new ThreadPoolExecutor(MIN_SERVER_POOL_SIZE,
+ MAX_SERVER_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
+ new LinkedBlockingQueue(MAX_TASK_QUEUE_SIZE),
+ new NamedThreadFactory("ServerHandlerThread", MAX_SERVER_POOL_SIZE), new ThreadPoolExecutor.CallerRunsPolicy());
+
+ /**
+ * The entry point of application.
+ *
+ * @param args the input arguments
+ * @throws IOException the io exception
+ */
+ public static void main(String[] args) throws IOException {
+ RpcServer rpcServer = new RpcServer(WORKING_THREADS);
+
+ rpcServer.setListenPort(SERVER_DEFAULT_PORT);
+
+ //log store mode : file、db
+ String storeMode = "file";
+
+ UUIDGenerator.init(1);
+ SessionHolder.init(storeMode);
+
+ DefaultCoordinator coordinator = new DefaultCoordinator(rpcServer);
+ coordinator.init();
+ rpcServer.setHandler(coordinator);
+ // register ShutdownHook
+ ShutdownHook.getInstance().addDisposable(coordinator);
+
+ XID.setIpAddress(NetUtil.getLocalIp());
+ XID.setPort(rpcServer.getListenPort());
+
+ rpcServer.init();
+
+ System.exit(0);
+ }
+}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java
new file mode 100755
index 000000000..efc55e555
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/UUIDGenerator.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicLong;
+
+import io.seata.common.exception.ShouldNeverHappenException;
+
+/**
+ * The type Uuid generator.
+ *
+ * @author sharajava
+ */
+public class UUIDGenerator {
+
+ private static final AtomicLong UUID = new AtomicLong(1000);
+ private static int serverNodeId = 1;
+ private static final long UUID_INTERNAL = 2000000000;
+
+ /**
+ * Generate uuid long.
+ *
+ * @return the long
+ */
+ public static long generateUUID() {
+ long id = UUID.incrementAndGet();
+ if (id >= UUID_INTERNAL * (serverNodeId + 1)) {
+ synchronized (UUID) {
+ if (UUID.get() >= id) {
+ id -= UUID_INTERNAL;
+ UUID.set(id);
+ }
+ }
+ }
+ return id;
+ }
+
+ /**
+ * Gets current uuid.
+ *
+ * @return the current uuid
+ */
+ public static long getCurrentUUID() {
+ return UUID.get();
+ }
+
+ /**
+ * Sets uuid.
+ *
+ * @param expect the expect
+ * @param update the update
+ * @return the uuid
+ */
+ public static boolean setUUID(long expect, long update) {
+ return UUID.compareAndSet(expect, update);
+
+ }
+
+ /**
+ * Init.
+ *
+ * @param serverNodeId the server node id
+ */
+ public static void init(int serverNodeId) {
+ try {
+ UUIDGenerator.serverNodeId = serverNodeId;
+ UUID.set(UUID_INTERNAL * serverNodeId);
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ Calendar cal = Calendar.getInstance();
+ Date date = format.parse("2019-01-01");
+ cal.setTime(date);
+ long base = cal.getTimeInMillis();
+ long current = System.currentTimeMillis();
+ UUID.addAndGet((current - base) / 1000);
+ } catch (ParseException e) {
+ throw new ShouldNeverHappenException(e);
+ }
+ }
+}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java
new file mode 100755
index 000000000..7d34dfee1
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/Core.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server.coordinator;
+
+import io.seata.core.exception.TransactionException;
+import io.seata.core.model.ResourceManagerInbound;
+import io.seata.core.model.ResourceManagerOutbound;
+import io.seata.core.model.TransactionManager;
+import io.seata.server.session.GlobalSession;
+
+/**
+ * The interface Core.
+ *
+ * @author sharajava
+ */
+public interface Core extends TransactionManager, ResourceManagerOutbound {
+
+ /**
+ * Sets resource manager inbound.
+ *
+ * @param resourceManagerInbound the resource manager inbound
+ */
+ void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbound);
+
+ /**
+ * Do global commit.
+ *
+ * @param globalSession the global session
+ * @param retrying the retrying
+ * @throws TransactionException the transaction exception
+ */
+ void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException;
+
+ /**
+ * Do global rollback.
+ *
+ * @param globalSession the global session
+ * @param retrying the retrying
+ * @throws TransactionException the transaction exception
+ */
+ void doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException;
+}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java
new file mode 100755
index 000000000..19e09f70e
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/CoreFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server.coordinator;
+
+/**
+ * The type Core factory.
+ *
+ * @author sharajava
+ */
+public class CoreFactory {
+
+ private static class SingletonHolder {
+ private static Core INSTANCE = new DefaultCore();
+ }
+
+ /**
+ * Get core.
+ *
+ * @return the core
+ */
+ public static final Core get() {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * Just for test mocking
+ *
+ * @param core the core
+ */
+ public static void set(Core core) {
+ SingletonHolder.INSTANCE = core;
+ }
+}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
new file mode 100755
index 000000000..024f741a9
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server.coordinator;
+
+import io.seata.common.XID;
+import io.seata.common.thread.NamedThreadFactory;
+import io.seata.core.exception.TransactionException;
+import io.seata.core.model.BranchStatus;
+import io.seata.core.model.BranchType;
+import io.seata.core.model.GlobalStatus;
+import io.seata.core.model.ResourceManagerInbound;
+import io.seata.core.protocol.AbstractMessage;
+import io.seata.core.protocol.AbstractResultMessage;
+import io.seata.core.protocol.transaction.*;
+import io.seata.core.rpc.Disposable;
+import io.seata.core.rpc.RpcContext;
+import io.seata.core.rpc.ServerMessageSender;
+import io.seata.core.rpc.TransactionMessageHandler;
+import io.seata.core.rpc.netty.RpcServer;
+import io.seata.server.AbstractTCInboundHandler;
+import io.seata.server.session.BranchSession;
+import io.seata.server.session.GlobalSession;
+import io.seata.server.session.SessionHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchCommitRequest;
+import static io.seata.core.exception.TransactionExceptionCode.FailedToSendBranchRollbackRequest;
+
+/**
+ * The type Default coordinator.
+ *
+ * @author sharajava
+ */
+public class DefaultCoordinator extends AbstractTCInboundHandler
+ implements TransactionMessageHandler, ResourceManagerInbound, Disposable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCoordinator.class);
+
+ private static final int TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS = 5000;
+
+ private ServerMessageSender messageSender;
+
+ private Core core = CoreFactory.get();
+
+ /**
+ * Instantiates a new Default coordinator.
+ *
+ * @param messageSender the message sender
+ */
+ public DefaultCoordinator(ServerMessageSender messageSender) {
+ this.messageSender = messageSender;
+ core.setResourceManagerInbound(this);
+ }
+
+ @Override
+ protected void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, RpcContext rpcContext)
+ throws TransactionException {
+ response.setXid(core.begin(rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(),
+ request.getTransactionName(), request.getTimeout()));
+ }
+
+ @Override
+ protected void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, RpcContext rpcContext)
+ throws TransactionException {
+ response.setGlobalStatus(core.commit(request.getXid()));
+
+ }
+
+ @Override
+ protected void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response,
+ RpcContext rpcContext) throws TransactionException {
+ response.setGlobalStatus(core.rollback(request.getXid()));
+
+ }
+
+ @Override
+ protected void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response, RpcContext rpcContext)
+ throws TransactionException {
+ response.setGlobalStatus(core.getStatus(request.getXid()));
+ }
+
+ @Override
+ protected void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response,
+ RpcContext rpcContext) throws TransactionException {
+ response.setBranchId(
+ core.branchRegister(request.getBranchType(), request.getResourceId(), rpcContext.getClientId(),
+ request.getXid(), request.getApplicationData(), request.getLockKey()));
+
+ }
+
+ @Override
+ protected void doBranchReport(BranchReportRequest request, BranchReportResponse response, RpcContext rpcContext)
+ throws TransactionException {
+ core.branchReport(request.getBranchType(), request.getXid(), request.getBranchId(),
+ request.getStatus(),
+ request.getApplicationData());
+
+ }
+
+ @Override
+ protected void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response, RpcContext rpcContext)
+ throws TransactionException {
+ response.setLockable(core.lockQuery(request.getBranchType(), request.getResourceId(),
+ request.getXid(), request.getLockKey()));
+ }
+
+ @Override
+ public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId,
+ String applicationData)
+ throws TransactionException {
+ try {
+ BranchCommitRequest request = new BranchCommitRequest();
+ request.setXid(xid);
+ request.setBranchId(branchId);
+ request.setResourceId(resourceId);
+ request.setApplicationData(applicationData);
+ request.setBranchType(branchType);
+
+ GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
+ if(globalSession == null){
+ return BranchStatus.PhaseTwo_Committed;
+ }
+ BranchSession branchSession = globalSession.getBranch(branchId);
+
+ BranchCommitResponse response = (BranchCommitResponse)messageSender.sendSyncRequest(resourceId,
+ branchSession.getClientId(), request);
+ return response.getBranchStatus();
+ } catch (IOException e) {
+ throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e);
+ } catch (TimeoutException e) {
+ throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e);
+ }
+ }
+
+ @Override
+ public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId,
+ String applicationData)
+ throws TransactionException {
+ try {
+ BranchRollbackRequest
+ request = new BranchRollbackRequest();
+ request.setXid(xid);
+ request.setBranchId(branchId);
+ request.setResourceId(resourceId);
+ request.setApplicationData(applicationData);
+ request.setBranchType(branchType);
+
+ GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
+ if(globalSession == null){
+ return BranchStatus.PhaseTwo_Rollbacked;
+ }
+ BranchSession branchSession = globalSession.getBranch(branchId);
+
+ BranchRollbackResponse response = (BranchRollbackResponse)messageSender.sendSyncRequest(resourceId,
+ branchSession.getClientId(), request);
+ return response.getBranchStatus();
+ } catch (IOException e) {
+ throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e);
+ } catch (TimeoutException e) {
+ throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e);
+ }
+ }
+
+ private void timeoutCheck() throws TransactionException {
+ Collection allSessions = SessionHolder.getRootSessionManager().allSessions();
+ if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Transaction Timeout Check Begin: " + allSessions.size());
+ }
+ for (GlobalSession globalSession : allSessions) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(globalSession.getTransactionId() + " " + globalSession.getStatus() + " " +
+ globalSession.getBeginTime() + " " + globalSession.getTimeout());
+ }
+ boolean shouldTimeout = globalSession.lockAndExcute(() -> {
+ if (globalSession.getStatus() != GlobalStatus.Begin || !globalSession.isTimeout()) {
+ return false;
+ }
+ globalSession.close();
+ globalSession.changeStatus(GlobalStatus.TimeoutRollbacking);
+ return true;
+ });
+ if (!shouldTimeout) {
+ continue;
+ }
+ LOGGER.info(
+ "Global transaction[" + globalSession.getTransactionId() + "] is timeout and will be rolled back.");
+
+ globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager());
+ SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession);
+
+ }
+ if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Transaction Timeout Check End. ");
+ }
+
+ }
+
+ private void handleRetryRollbacking() {
+ Collection rollbackingSessions = SessionHolder.getRetryRollbackingSessionManager().allSessions();
+ for (GlobalSession rollbackingSession : rollbackingSessions) {
+ try {
+ core.doGlobalRollback(rollbackingSession, true);
+ } catch (TransactionException ex) {
+ LOGGER.info("Failed to retry rollbacking [{}] {} {}",
+ rollbackingSession.getTransactionId(), ex.getCode(), ex.getMessage());
+ }
+ }
+ }
+
+ private void handleRetryCommitting() {
+ Collection committingSessions = SessionHolder.getRetryCommittingSessionManager().allSessions();
+ for (GlobalSession committingSession : committingSessions) {
+ try {
+ core.doGlobalCommit(committingSession, true);
+ } catch (TransactionException ex) {
+ LOGGER.info("Failed to retry committing [{}] {} {}",
+ committingSession.getTransactionId(), ex.getCode(), ex.getMessage());
+ }
+ }
+ }
+
+ private void handleAsyncCommitting() {
+ Collection asyncCommittingSessions = SessionHolder.getAsyncCommittingSessionManager()
+ .allSessions();
+ for (GlobalSession asyncCommittingSession : asyncCommittingSessions) {
+ try {
+ core.doGlobalCommit(asyncCommittingSession, true);
+ } catch (TransactionException ex) {
+ LOGGER.info("Failed to async committing [{}] {} {}",
+ asyncCommittingSession.getTransactionId(), ex.getCode(), ex.getMessage());
+ }
+ }
+ }
+
+ private ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1,
+ new NamedThreadFactory("RetryRollbacking", 1));
+
+ private ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1,
+ new NamedThreadFactory("RetryCommitting", 1));
+
+ private ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1,
+ new NamedThreadFactory("AsyncCommitting", 1));
+
+ private ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1,
+ new NamedThreadFactory("TxTimeoutCheck", 1));
+
+ /**
+ * Init.
+ */
+ public void init() {
+ retryRollbacking.scheduleAtFixedRate(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ handleRetryRollbacking();
+ } catch (Exception e) {
+ LOGGER.info("Exception retry rollbacking ... ", e);
+ }
+
+ }
+ }, 0, 5, TimeUnit.MILLISECONDS);
+
+ retryCommitting.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ handleRetryCommitting();
+ } catch (Exception e) {
+ LOGGER.info("Exception retry committing ... ", e);
+ }
+
+ }
+ }, 0, 5, TimeUnit.MILLISECONDS);
+
+ asyncCommitting.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ handleAsyncCommitting();
+ } catch (Exception e) {
+ LOGGER.info("Exception async committing ... ", e);
+ }
+
+ }
+ }, 0, 10, TimeUnit.MILLISECONDS);
+
+ timeoutCheck.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ timeoutCheck();
+ } catch (Exception e) {
+ LOGGER.info("Exception timeout checking ... ", e);
+ }
+
+ }
+ }, 0, 2, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public AbstractResultMessage onRequest(AbstractMessage request, RpcContext context) {
+ if (!(request instanceof AbstractTransactionRequestToTC)) {
+ throw new IllegalArgumentException();
+ }
+ AbstractTransactionRequestToTC transactionRequest = (AbstractTransactionRequestToTC)request;
+ transactionRequest.setTCInboundHandler(this);
+
+ return transactionRequest.handle(context);
+ }
+
+ @Override
+ public void onResponse(AbstractResultMessage response, RpcContext context) {
+ if (!(response instanceof AbstractTransactionResponse)) {
+ throw new IllegalArgumentException();
+ }
+
+ }
+
+ @Override
+ public void destroy() {
+ // 1. first shutdown timed task
+ retryRollbacking.shutdown();
+ retryCommitting.shutdown();
+ asyncCommitting.shutdown();
+ timeoutCheck.shutdown();
+ try {
+ retryRollbacking.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
+ retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
+ asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
+ timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ingore) {
+
+ }
+ // 2. sencond close netty flow
+ if (messageSender instanceof RpcServer){
+ ((RpcServer) messageSender).destroy();
+ }
+ // 3. last destory SessionHolder
+ SessionHolder.destory();
+ }
+}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java
new file mode 100755
index 000000000..1ba36763f
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/coordinator/DefaultCore.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server.coordinator;
+
+import io.seata.common.XID;
+import io.seata.core.exception.TransactionException;
+import io.seata.core.exception.TransactionExceptionCode;
+import io.seata.core.model.BranchStatus;
+import io.seata.core.model.BranchType;
+import io.seata.core.model.GlobalStatus;
+import io.seata.core.model.ResourceManagerInbound;
+import io.seata.server.lock.LockManager;
+import io.seata.server.lock.LockManagerFactory;
+import io.seata.server.session.BranchSession;
+import io.seata.server.session.GlobalSession;
+import io.seata.server.session.SessionHelper;
+import io.seata.server.session.SessionHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static io.seata.core.exception.TransactionExceptionCode.BranchTransactionNotExist;
+import static io.seata.core.exception.TransactionExceptionCode.FailedToAddBranch;
+import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionNotActive;
+import static io.seata.core.exception.TransactionExceptionCode.GlobalTransactionStatusInvalid;
+import static io.seata.core.exception.TransactionExceptionCode.LockKeyConflict;
+
+/**
+ * The type Default core.
+ *
+ * @author sharajava
+ */
+public class DefaultCore implements Core {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCore.class);
+
+ private LockManager lockManager = LockManagerFactory.get();
+
+ private ResourceManagerInbound resourceManagerInbound;
+
+ @Override
+ public void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbound) {
+ this.resourceManagerInbound = resourceManagerInbound;
+ }
+
+ @Override
+ public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid,
+ String applicationData, String lockKeys) throws TransactionException {
+ GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid));
+ return globalSession.lockAndExcute(() -> {
+ if (!globalSession.isActive()) {
+ throw new TransactionException(GlobalTransactionNotActive, "Current Status: " + globalSession.getStatus());
+ }
+ if (globalSession.getStatus() != GlobalStatus.Begin) {
+ throw new TransactionException(GlobalTransactionStatusInvalid,
+ globalSession.getStatus() + " while expecting " + GlobalStatus.Begin);
+ }
+ BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId,
+ applicationData, lockKeys, clientId);
+ if (!branchSession.lock()) {
+ throw new TransactionException(LockKeyConflict);
+ }
+ try {
+ globalSession.addBranch(branchSession);
+ } catch (RuntimeException ex) {
+ throw new TransactionException(FailedToAddBranch);
+ }
+ return branchSession.getBranchId();
+ });
+ }
+
+ private GlobalSession assertGlobalSessionNotNull(long transactionId) throws TransactionException {
+ GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId);
+ if (globalSession == null) {
+ throw new TransactionException(TransactionExceptionCode.GlobalTransactionNotExist, "" + transactionId + "");
+ }
+ return globalSession;
+ }
+
+
+ @Override
+ public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status,
+ String applicationData) throws TransactionException {
+ GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid));
+ BranchSession branchSession = globalSession.getBranch(branchId);
+ if (branchSession == null) {
+ throw new TransactionException(BranchTransactionNotExist);
+ }
+ globalSession.changeBranchStatus(branchSession, status);
+ }
+
+ @Override
+ public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys)
+ throws TransactionException {
+ if (branchType == BranchType.AT) {
+ return lockManager.isLockable(XID.getTransactionId(xid), resourceId, lockKeys);
+ } else {
+ return true;
+ }
+
+ }
+
+ @Override
+ public String begin(String applicationId, String transactionServiceGroup, String name, int timeout)
+ throws TransactionException {
+ GlobalSession session = GlobalSession.createGlobalSession(
+ applicationId, transactionServiceGroup, name, timeout);
+ session.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
+
+ session.begin();
+
+ return XID.generateXID(session.getTransactionId());
+ }
+
+ @Override
+ public GlobalStatus commit(String xid) throws TransactionException {
+ GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
+ if (globalSession == null) {
+ return GlobalStatus.Finished;
+ }
+ // just lock changeStatus
+ boolean shouldCommit = globalSession.lockAndExcute(() -> {
+ globalSession.closeAndClean(); // Highlight: Firstly, close the session, then no more branch can be registered.
+ if (globalSession.getStatus() == GlobalStatus.Begin) {
+ globalSession.changeStatus(GlobalStatus.Committing);
+ return true;
+ }
+ return false;
+ });
+ if (!shouldCommit){
+ return globalSession.getStatus();
+ }
+ if (globalSession.canBeCommittedAsync()) {
+ asyncCommit(globalSession);
+ return GlobalStatus.Committed;
+ } else {
+ doGlobalCommit(globalSession, false);
+ }
+ return globalSession.getStatus();
+ }
+
+ @Override
+ public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {
+ for (BranchSession branchSession : globalSession.getSortedBranches()) {
+ BranchStatus currentStatus = branchSession.getStatus();
+ if (currentStatus == BranchStatus.PhaseOne_Failed) {
+ globalSession.removeBranch(branchSession);
+ continue;
+ }
+ try {
+ BranchStatus branchStatus = resourceManagerInbound.branchCommit(branchSession.getBranchType(),
+ XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(),
+ branchSession.getResourceId(), branchSession.getApplicationData());
+
+ switch (branchStatus) {
+ case PhaseTwo_Committed:
+ globalSession.removeBranch(branchSession);
+ continue;
+ case PhaseTwo_CommitFailed_Unretryable:
+ if (globalSession.canBeCommittedAsync()) {
+ LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession);
+ continue;
+ } else {
+ SessionHelper.endCommitFailed(globalSession);
+ LOGGER.error("Finally, failed to commit global[{}] since branch[{}] commit failed",
+ globalSession.getTransactionId(), branchSession.getBranchId());
+ return;
+ }
+ default:
+ if (!retrying) {
+ queueToRetryCommit(globalSession);
+ return;
+ }
+ if (globalSession.canBeCommittedAsync()) {
+ LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession);
+ continue;
+ } else {
+ LOGGER.error(
+ "Failed to commit global[{}] since branch[{}] commit failed, will retry later.",
+ globalSession.getTransactionId(), branchSession.getBranchId());
+ return;
+ }
+
+ }
+
+ } catch (Exception ex) {
+ LOGGER.error("Exception committing branch {}", branchSession, ex);
+ if (!retrying) {
+ queueToRetryCommit(globalSession);
+ throw new TransactionException(ex);
+ }
+
+ }
+
+ }
+ if (globalSession.hasBranch()) {
+ LOGGER.info("Global[{}] committing is NOT done.", globalSession.getTransactionId());
+ return;
+ }
+ 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 {
+ globalSession.addSessionLifecycleListener(SessionHolder.getRetryCommittingSessionManager());
+ SessionHolder.getRetryCommittingSessionManager().addGlobalSession(globalSession);
+ globalSession.changeStatus(GlobalStatus.CommitRetrying);
+ }
+
+ private void queueToRetryRollback(GlobalSession globalSession) throws TransactionException {
+ globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager());
+ SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession);
+ GlobalStatus currentStatus = globalSession.getStatus();
+ if (SessionHelper.isTimeoutGlobalStatus(currentStatus)) {
+ globalSession.changeStatus(GlobalStatus.TimeoutRollbackRetrying);
+ } else {
+ globalSession.changeStatus(GlobalStatus.RollbackRetrying);
+ }
+ }
+
+ @Override
+ public GlobalStatus rollback(String xid) throws TransactionException {
+ GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
+ if (globalSession == null) {
+ return GlobalStatus.Finished;
+ }
+ // just lock changeStatus
+ boolean shouldRollBack = globalSession.lockAndExcute(() -> {
+ globalSession.close(); // Highlight: Firstly, close the session, then no more branch can be registered.
+ if (globalSession.getStatus() == GlobalStatus.Begin) {
+ globalSession.changeStatus(GlobalStatus.Rollbacking);
+ return true;
+ }
+ return false;
+ });
+ if (!shouldRollBack){
+ return globalSession.getStatus();
+ }
+
+ doGlobalRollback(globalSession, false);
+ return globalSession.getStatus();
+ }
+
+ @Override
+ public void doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException {
+ for (BranchSession branchSession : globalSession.getReverseSortedBranches()) {
+ BranchStatus currentBranchStatus = branchSession.getStatus();
+ if (currentBranchStatus == BranchStatus.PhaseOne_Failed) {
+ globalSession.removeBranch(branchSession);
+ continue;
+ }
+ try {
+ BranchStatus branchStatus = resourceManagerInbound.branchRollback(branchSession.getBranchType(),
+ XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(),
+ branchSession.getResourceId(), branchSession.getApplicationData());
+
+ switch (branchStatus) {
+ case PhaseTwo_Rollbacked:
+ globalSession.removeBranch(branchSession);
+ LOGGER.error("Successfully rolled back branch " + branchSession);
+ continue;
+ case PhaseTwo_RollbackFailed_Unretryable:
+ SessionHelper.endRollbackFailed(globalSession);
+ LOGGER.error("Failed to rollback global[" + globalSession.getTransactionId() + "] since branch["
+ + branchSession.getBranchId() + "] rollback failed");
+ return;
+ default:
+ LOGGER.info("Failed to rollback branch " + branchSession);
+ if (!retrying) {
+ queueToRetryRollback(globalSession);
+ }
+ return;
+
+ }
+ } catch (Exception ex) {
+ LOGGER.error("Exception rollbacking branch " + branchSession, ex);
+ if (!retrying) {
+ queueToRetryRollback(globalSession);
+ }
+ throw new TransactionException(ex);
+ }
+
+ }
+ SessionHelper.endRollbacked(globalSession);
+ }
+
+ @Override
+ public GlobalStatus getStatus(String xid) throws TransactionException {
+ GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
+ return globalSession.getStatus();
+ }
+}
diff --git a/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
new file mode 100755
index 000000000..a0c576c84
--- /dev/null
+++ b/pigx-visual/pigx-seata-server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 1999-2019 Seata.io Group.
+ *
+ * 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 io.seata.server.lock;
+
+import io.netty.util.internal.ConcurrentSet;
+import io.seata.common.exception.ShouldNeverHappenException;
+import io.seata.common.util.StringUtils;
+import io.seata.core.exception.TransactionException;
+import io.seata.server.session.BranchSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * The type Default lock manager.
+ *
+ * @author sharajava
+ */
+public class DefaultLockManagerImpl implements LockManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLockManagerImpl.class);
+
+ private static final int BUCKET_PER_TABLE = 128;
+
+ private static final
+ ConcurrentHashMap>>>
+ LOCK_MAP = new ConcurrentHashMap>>>();
+
+ @Override
+ public boolean acquireLock(BranchSession branchSession) throws TransactionException {
+ String resourceId = branchSession.getResourceId();
+ long transactionId = branchSession.getTransactionId();
+ ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId);
+ if (dbLockMap == null) {
+ LOCK_MAP.putIfAbsent(resourceId,
+ new ConcurrentHashMap>>());
+ dbLockMap = LOCK_MAP.get(resourceId);
+ }
+ ConcurrentHashMap