├── dts-common ├── .gitignore ├── src │ └── main │ │ ├── resource │ │ └── META-INF │ │ │ └── services │ │ │ └── io.dts.common.common.DtsContext │ │ └── java │ │ └── io │ │ └── dts │ │ └── common │ │ ├── protocol │ │ ├── RequestCode.java │ │ ├── ResultCode.java │ │ ├── heatbeat │ │ │ ├── HeartbeatResponseHeader.java │ │ │ └── HeartbeatRequestHeader.java │ │ ├── ResponseMessage.java │ │ ├── RequestMessage.java │ │ ├── ResponseCode.java │ │ └── header │ │ │ ├── GlobalCommitResultMessage.java │ │ │ ├── GlobalRollbackResultMessage.java │ │ │ ├── BeginMessage.java │ │ │ ├── GlobalCommitMessage.java │ │ │ ├── RegisterMessage.java │ │ │ ├── BeginResultMessage.java │ │ │ ├── GlobalRollbackMessage.java │ │ │ ├── RegisterResultMessage.java │ │ │ ├── BranchRollbackResultMessage.java │ │ │ ├── BranchCommitResultMessage.java │ │ │ ├── BranchRollBackMessage.java │ │ │ └── BranchCommitMessage.java │ │ ├── api │ │ ├── DtsServerMessageSender.java │ │ ├── DtsClientMessageSender.java │ │ └── DtsServerMessageHandler.java │ │ ├── util │ │ ├── ThreadFactoryImpl.java │ │ └── BlobUtil.java │ │ ├── exception │ │ └── DtsException.java │ │ ├── cluster │ │ └── ServerCluster.java │ │ └── context │ │ └── DtsContext.java └── pom.xml ├── dts-datasource ├── .gitignore ├── src │ └── main │ │ ├── java │ │ └── io │ │ │ └── dts │ │ │ └── datasource │ │ │ ├── UndoLogMode.java │ │ │ ├── wrapper │ │ │ ├── executor │ │ │ │ ├── StatementModel.java │ │ │ │ ├── AbstractExecutor.java │ │ │ │ └── PreparedStatementExecutor.java │ │ │ └── DtsPrepareStatementWrapper.java │ │ │ ├── AbstractDtsDataSource.java │ │ │ └── DtsDataSource.java │ │ └── resources │ │ └── txc_client.sql └── pom.xml ├── dts-parser ├── .gitignore ├── src │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── dts │ │ │ └── parser │ │ │ ├── struct │ │ │ ├── IndexType.java │ │ │ ├── TxcLine.java │ │ │ ├── SqlType.java │ │ │ ├── TxcField.java │ │ │ ├── DatabaseType.java │ │ │ ├── MySQLKeyword.java │ │ │ └── TxcIndex.java │ │ │ ├── DtsSQLStatement.java │ │ │ ├── vistor │ │ │ ├── mysql │ │ │ │ ├── DtsSelectVisitor.java │ │ │ │ └── DtsDeleteVisitor.java │ │ │ └── ITxcVisitor.java │ │ │ └── DtsObjectWapper.java │ └── test │ │ └── java │ │ └── io │ │ └── dts │ │ └── parser │ │ └── visitor │ │ ├── TxcUpdateVisitorTest.java │ │ ├── TxcDelectVisitorTest.java │ │ ├── TxcSelectVisitorTest.java │ │ └── TxcInsertVisitorTest.java └── pom.xml ├── dts-remoting ├── .gitignore ├── src │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── dts │ │ │ └── remoting │ │ │ ├── version │ │ │ └── V3_1_9.java │ │ │ ├── RemoteConstant.java │ │ │ ├── RemotingService.java │ │ │ ├── protocol │ │ │ ├── LanguageCode.java │ │ │ ├── protocol.txt │ │ │ ├── RemotingSysResponseCode.java │ │ │ ├── RemotingCommandType.java │ │ │ └── RemotingSerializable.java │ │ │ ├── RPCHook.java │ │ │ ├── netty │ │ │ ├── NettyEventType.java │ │ │ ├── NettyRequestProcessor.java │ │ │ ├── NettySystemConfig.java │ │ │ ├── NettyEvent.java │ │ │ ├── NettyEncoder.java │ │ │ └── NettyDecoder.java │ │ │ ├── InvokeCallback.java │ │ │ ├── CommandCustomHeader.java │ │ │ ├── annotation │ │ │ ├── CFNotNull.java │ │ │ └── CFNullable.java │ │ │ ├── exception │ │ │ ├── RemotingTooMuchRequestException.java │ │ │ ├── RemotingException.java │ │ │ ├── RemotingCommandException.java │ │ │ ├── RemotingConnectException.java │ │ │ ├── RemotingSendRequestException.java │ │ │ └── RemotingTimeoutException.java │ │ │ ├── ChannelEventListener.java │ │ │ ├── common │ │ │ ├── Pair.java │ │ │ └── SemaphoreReleaseOnlyOnce.java │ │ │ └── RemotingClient.java │ └── test │ │ └── java │ │ └── io │ │ └── dts │ │ └── remoting │ │ ├── MixTest.java │ │ ├── SyncInvokeTest.java │ │ └── NettyConnectionTest.java └── pom.xml ├── dts-rm-rabbit ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── io │ │ └── dts │ │ └── rabbit │ │ └── App.java └── pom.xml ├── dts-server ├── .gitignore └── src │ └── main │ ├── conf │ ├── server.properties │ └── logback_server.xml │ ├── resources │ ├── application.yml │ └── log4j.xml │ ├── java │ └── io │ │ └── dts │ │ └── server │ │ ├── struct │ │ ├── BranchLogState.java │ │ └── GlobalLogState.java │ │ ├── store │ │ └── DtsLogDao.java │ │ ├── network │ │ ├── FutureTaskExt.java │ │ ├── processor │ │ │ └── HeatBeatProcessor.java │ │ └── ServerFixedThreadPoolExecutor.java │ │ ├── DtsServerApp.java │ │ └── handler │ │ └── support │ │ └── RmMessageHandler.java │ └── assembly │ └── assembly.xml ├── dts-resourcemanager ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── io │ │ └── dts │ │ └── resourcemanager │ │ ├── api │ │ ├── IDtsStatement.java │ │ ├── IDtsPrepareStatement.java │ │ ├── IDtsDataSource.java │ │ └── IDtsConnection.java │ │ ├── DataSourceHolder.java │ │ ├── struct │ │ ├── ContextStep2.java │ │ └── UndoLogMode.java │ │ ├── undo │ │ ├── DtsUndo.java │ │ ├── DtsInsertUndo.java │ │ ├── DtsDeleteUndo.java │ │ └── DtsUpdateUndo.java │ │ ├── ResourceManager.java │ │ └── logmanager │ │ └── BranchCommitLogManager.java └── pom.xml ├── dts-rm-rocketmq ├── .gitignore └── pom.xml ├── dts-client ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── io │ │ └── dts │ │ └── client │ │ ├── template │ │ ├── TxcCallback.java │ │ └── TxcTransactionTemplate.java │ │ ├── aop │ │ ├── annotation │ │ │ ├── DtsTransaction.java │ │ │ └── EnableDtsConfiguration.java │ │ └── MethodDesc.java │ │ └── api │ │ └── DtsTransactionManager.java └── pom.xml ├── dts-example ├── .gitignore ├── dts-example-consumer │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ ├── static │ │ │ │ └── index.html │ │ │ ├── META-INF │ │ │ │ └── reference.json │ │ │ ├── application.yml │ │ │ └── log4j.xml │ │ │ └── java │ │ │ └── com │ │ │ └── quancheng │ │ │ └── saluki │ │ │ └── example │ │ │ ├── client │ │ │ ├── ProxyServiceController.java │ │ │ └── RpcService.java │ │ │ └── SalukiExampleClientApp.java │ ├── .gitignore │ └── pom.xml ├── dts-example-api │ ├── .gitignore │ └── src │ │ └── main │ │ ├── java │ │ └── io │ │ │ └── dts │ │ │ └── example │ │ │ └── client │ │ │ └── ClientExmaple.java │ │ └── proto │ │ └── example │ │ ├── hello_service.proto │ │ └── hello.proto └── dts-example-provider │ ├── .gitignore │ ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── quancheng │ │ │ └── saluki │ │ │ └── example │ │ │ ├── SalukiExampleServerApp.java │ │ │ ├── repository │ │ │ ├── StudentDao.java │ │ │ └── entity │ │ │ │ └── StudentDo.java │ │ │ └── server │ │ │ └── HelloServiceImpl.java │ │ └── resources │ │ ├── application.yml │ │ └── log4j.xml │ └── pom.xml ├── flow.png ├── architecture.png ├── dts-microservice-support ├── dts-saluki-support │ ├── src │ │ └── main │ │ │ ├── resource │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── io.dts.common.context.DtsContext │ │ │ └── java │ │ │ └── io │ │ │ └── dts │ │ │ └── saluki │ │ │ └── SalukiContext.java │ └── pom.xml ├── dts-springcloud-support │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ ├── servies │ │ │ │ └── io.dts.common.context.DtsContext │ │ │ │ └── spring.factories │ │ │ └── java │ │ │ └── io │ │ │ └── dts │ │ │ └── springcloud │ │ │ ├── ContextHystrixAutoConfiguration.java │ │ │ └── SpringCloudContextConfig.java │ └── pom.xml └── pom.xml ├── .gitignore ├── script ├── resource.sql └── server.sql └── README.md /dts-common/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-datasource/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-parser/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-remoting/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-rm-rabbit/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-resourcemanager/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-rm-rocketmq/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /dts-client/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /target/ 3 | -------------------------------------------------------------------------------- /dts-example/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings/ 2 | /.project 3 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | hello -------------------------------------------------------------------------------- /flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpringCloud/spring-cloud-dts/HEAD/flow.png -------------------------------------------------------------------------------- /architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpringCloud/spring-cloud-dts/HEAD/architecture.png -------------------------------------------------------------------------------- /dts-example/dts-example-api/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.project 4 | /.classpath 5 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.project 4 | /.classpath 5 | -------------------------------------------------------------------------------- /dts-example/dts-example-provider/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.project 3 | /.classpath 4 | /.settings/ 5 | -------------------------------------------------------------------------------- /dts-common/src/main/resource/META-INF/services/io.dts.common.common.DtsContext: -------------------------------------------------------------------------------- 1 | io.dts.common.common.SalukiContext -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/version/V3_1_9.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting.version; 2 | 3 | public class V3_1_9 { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /dts-microservice-support/dts-saluki-support/src/main/resource/META-INF/services/io.dts.common.context.DtsContext: -------------------------------------------------------------------------------- 1 | io.dts.saluki.SalukiContext 2 | -------------------------------------------------------------------------------- /dts-microservice-support/dts-springcloud-support/src/main/resources/META-INF/servies/io.dts.common.context.DtsContext: -------------------------------------------------------------------------------- 1 | io.dts.springcloud.SpringCloudContext 2 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/RemoteConstant.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting; 2 | 3 | public interface RemoteConstant { 4 | public static final long RPC_INVOKE_TIMEOUT = 30 * 1000; 5 | } 6 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/src/main/resources/META-INF/reference.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "service": "com.quancheng.examples.service.HelloService", 4 | "group": "example", 5 | "version": "1.0.0" 6 | } 7 | 8 | ] -------------------------------------------------------------------------------- /dts-microservice-support/dts-springcloud-support/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | io.dts.springcloud.SpringCloudContextConfig,\ 3 | io.dts.springcloud.ContextHystrixAutoConfiguration -------------------------------------------------------------------------------- /dts-server/src/main/conf/server.properties: -------------------------------------------------------------------------------- 1 | addresses=10.101.54.146,10.101.17.236,10.101.58.248 2 | keyspace=hybrid_alpha 3 | topkCacheSize=1000000 4 | clusterName=test 5 | groupId=1 6 | localIpAddress=10.9.25.95:10086 7 | serverPort=10086 8 | vnodeCount=2 9 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: dts-consumer 4 | server: 5 | port: 8080 6 | saluki: 7 | grpc: 8 | registryAddress: localhost:8500 9 | referenceDefinition: META-INF/reference.json -------------------------------------------------------------------------------- /dts-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | tcp: 2 | listenPort: 10086 3 | spring: 4 | datasource: 5 | druid: 6 | url: jdbc:mysql://127.0.0.1:3306/dts 7 | username: root 8 | password: 123 9 | driver-class-name: com.mysql.jdbc.Driver -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/RemotingService.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting; 2 | 3 | public interface RemotingService { 4 | public void start(); 5 | 6 | 7 | public void shutdown(); 8 | 9 | 10 | public void registerRPCHook(RPCHook rpcHook); 11 | } 12 | -------------------------------------------------------------------------------- /dts-rm-rabbit/src/main/java/io/dts/rabbit/App.java: -------------------------------------------------------------------------------- 1 | package io.dts.rabbit; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/protocol/LanguageCode.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting.protocol; 2 | 3 | public enum LanguageCode { 4 | JAVA, 5 | CPP, 6 | DOTNET, 7 | PYTHON, 8 | DELPHI, 9 | ERLANG, 10 | RUBY, 11 | OTHER, 12 | HTTP, 13 | } 14 | -------------------------------------------------------------------------------- /dts-example/dts-example-api/src/main/java/io/dts/example/client/ClientExmaple.java: -------------------------------------------------------------------------------- 1 | package io.dts.example.client; 2 | 3 | /** 4 | * Created by guoyubo on 2017/9/26. 5 | */ 6 | public class ClientExmaple { 7 | 8 | 9 | public static void main(String[] args) { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/RequestCode.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.protocol; 2 | 3 | 4 | public class RequestCode { 5 | 6 | public static final int HEADER_REQUEST = 200; 7 | public static final int BODY_REQUEST = 201; 8 | public static final int HEART_BEAT = 400; 9 | } 10 | -------------------------------------------------------------------------------- /dts-remoting/src/test/java/io/dts/remoting/MixTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * $Id: MixTest.java 1831 2013-05-16 01:39:51Z shijia.wxr $ 3 | */ 4 | package io.dts.remoting; 5 | 6 | import org.junit.Test; 7 | 8 | 9 | /** 10 | * @author shijia.wxr 11 | */ 12 | public class MixTest { 13 | @Test 14 | public void test_extFieldsValue() { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle/ 2 | .DS_Store 3 | 4 | target/ 5 | !.mvn/wrapper/maven-wrapper.jar 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | 21 | ### NetBeans ### 22 | nbproject/private/ 23 | build/ 24 | nbbuild/ 25 | dist/ 26 | nbdist/ 27 | .nb-gradle/ 28 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/api/IDtsStatement.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.api; 2 | 3 | import java.sql.SQLException; 4 | import java.sql.Statement; 5 | 6 | public interface IDtsStatement extends Statement { 7 | 8 | IDtsConnection getDtsConnection() throws SQLException; 9 | 10 | Statement getRawStatement() throws SQLException; 11 | 12 | String getTargetSql(); 13 | } 14 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/api/IDtsPrepareStatement.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.api; 2 | 3 | 4 | import java.sql.PreparedStatement; 5 | import java.sql.SQLException; 6 | 7 | public interface IDtsPrepareStatement extends IDtsStatement, PreparedStatement { 8 | 9 | 10 | PreparedStatement getRawStatement() throws SQLException; 11 | 12 | String getTargetSql(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /dts-client/src/main/java/io/dts/client/template/TxcCallback.java: -------------------------------------------------------------------------------- 1 | package io.dts.client.template; 2 | 3 | 4 | /** 5 | * @author qinan.qn@taobao.com 2014年10月30日 6 | */ 7 | public interface TxcCallback { 8 | /** 9 | * 事务模板回调函数,用以模板开启事务后,调用此方法执行业务逻辑 10 | * 11 | * @return 12 | * @throws Throwable 用户抛出的异常 13 | * @since 1.1.0 14 | */ 15 | public Object callback() throws Throwable; 16 | } 17 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/protocol/protocol.txt: -------------------------------------------------------------------------------- 1 | // 2 | // Remoting通信协议 3 | // 2013-01-21 19:11:14 誓嘉草拟 V0.1 4 | // 5 | // 协议格式
6 | // 1 2 3 4 7 | // 协议分4部分,含义分别如下 8 | // 1、大端4个字节整数,等于2、3、4长度总和 9 | // 2、大端4个字节整数,等于3的长度 10 | // 3、使用json序列化数据 11 | // 4、应用自定义二进制序列化数据 12 | // 13 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/RPCHook.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting; 2 | 3 | import io.dts.remoting.protocol.RemotingCommand; 4 | 5 | public interface RPCHook { 6 | public void doBeforeRequest(final String remoteAddr, final RemotingCommand request); 7 | 8 | 9 | public void doAfterResponse(final String remoteAddr, final RemotingCommand request, 10 | final RemotingCommand response); 11 | } 12 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/protocol/RemotingSysResponseCode.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting.protocol; 2 | 3 | public class RemotingSysResponseCode { 4 | // 成功 5 | public static final int SUCCESS = 0; 6 | // 发生了未捕获异常 7 | public static final int SYSTEM_ERROR = 1; 8 | // 由于线程池拥堵,系统繁忙 9 | public static final int SYSTEM_BUSY = 2; 10 | // 请求代码不支持 11 | public static final int REQUEST_CODE_NOT_SUPPORTED = 3; 12 | } 13 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/ResultCode.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.protocol; 2 | 3 | 4 | public enum ResultCode { 5 | /** 6 | * 成功 7 | */ 8 | OK(1), 9 | 10 | /** 11 | * 失败,可恢复错误,需要重试 12 | */ 13 | ERROR(0); 14 | 15 | 16 | private ResultCode(int value) { 17 | this.value = value; 18 | } 19 | 20 | public int getValue() { 21 | return value; 22 | } 23 | 24 | private int value; 25 | } 26 | -------------------------------------------------------------------------------- /script/resource.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `dts_undo_log` ( 2 | `id` bigint(11) NOT NULL AUTO_INCREMENT, 3 | `xid` char(64) NOT NULL, 4 | `branch_id` bigint(20) NOT NULL, 5 | `rollback_info` longblob, 6 | `gmt_create` datetime DEFAULT NULL, 7 | `gmt_modified` datetime DEFAULT NULL, 8 | `status` int(10) DEFAULT NULL, 9 | `server` char(32) DEFAULT NULL, 10 | PRIMARY KEY (`id`), 11 | KEY `branch_id` (`branch_id`,`xid`) 12 | ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=latin1; 13 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/heatbeat/HeartbeatResponseHeader.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.protocol.heatbeat; 2 | 3 | import io.dts.common.protocol.ResponseMessage; 4 | import io.dts.remoting.CommandCustomHeader; 5 | import io.dts.remoting.exception.RemotingCommandException; 6 | 7 | 8 | public class HeartbeatResponseHeader implements CommandCustomHeader, ResponseMessage { 9 | @Override 10 | public void checkFields() throws RemotingCommandException { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dts-client/src/main/java/io/dts/client/aop/annotation/DtsTransaction.java: -------------------------------------------------------------------------------- 1 | package io.dts.client.aop.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Inherited; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Target(ElementType.METHOD) 12 | @Inherited 13 | public @interface DtsTransaction { 14 | 15 | int timeout() default 60000; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /dts-client/src/main/java/io/dts/client/api/DtsTransactionManager.java: -------------------------------------------------------------------------------- 1 | package io.dts.client.api; 2 | 3 | import io.dts.common.exception.DtsException; 4 | 5 | /** 6 | * Created by guoyubo on 2017/8/24. 7 | */ 8 | public interface DtsTransactionManager { 9 | 10 | void begin(long timeout) throws DtsException; 11 | 12 | void commit() throws DtsException; 13 | 14 | void commit(int retryTimes) throws DtsException; 15 | 16 | void rollback() throws DtsException; 17 | 18 | void rollback(int retryTimes) throws DtsException; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /dts-example/dts-example-api/src/main/proto/example/hello_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | option java_package = "com.quancheng.examples.service"; 3 | option java_outer_classname = "HelloServiceProto2"; 4 | package com.quancheng.examples.service; 5 | import "example/hello.proto"; 6 | service HelloService { 7 | rpc dtsNormal (com.quancheng.examples.model.HelloRequest) returns (com.quancheng.examples.model.HelloReply) {} 8 | 9 | 10 | rpc dtsException (com.quancheng.examples.model.HelloRequest) returns (com.quancheng.examples.model.HelloReply) {} 11 | 12 | } -------------------------------------------------------------------------------- /dts-example/dts-example-provider/src/main/java/com/quancheng/saluki/example/SalukiExampleServerApp.java: -------------------------------------------------------------------------------- 1 | package com.quancheng.saluki.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.transaction.annotation.EnableTransactionManagement; 6 | 7 | @SpringBootApplication 8 | @EnableTransactionManagement 9 | public class SalukiExampleServerApp { 10 | 11 | public static void main(String[] args) { 12 | 13 | SpringApplication.run(SalukiExampleServerApp.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/api/DtsServerMessageSender.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.api; 2 | 3 | import io.dts.common.exception.DtsException; 4 | import io.dts.common.protocol.RequestMessage; 5 | 6 | /** 7 | * server调用client端接口 8 | * 9 | */ 10 | public interface DtsServerMessageSender extends BaseMessageSender { 11 | 12 | public T invokeSync(String clientAddress, String clientKey, RequestMessage msg, long timeout) 13 | throws DtsException; 14 | 15 | public void invokeAsync(String clientAddress, String clientKey, RequestMessage msg, long timeout) 16 | throws DtsException; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/struct/IndexType.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.struct; 2 | 3 | public enum IndexType { 4 | /** */ 5 | PRIMARY(0), 6 | /** */ 7 | Normal(1), 8 | /** */ 9 | Unique(2), 10 | /** */ 11 | FullText(3); 12 | 13 | private int i; 14 | 15 | private IndexType(int i) { 16 | this.i = i; 17 | } 18 | 19 | public int value() { 20 | return this.i; 21 | } 22 | 23 | public static IndexType valueOf(int i) { 24 | for (IndexType t : values()) { 25 | if (t.value() == i) { 26 | return t; 27 | } 28 | } 29 | throw new IllegalArgumentException("Invalid IndexType:" + i); 30 | } 31 | } -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/struct/BranchLogState.java: -------------------------------------------------------------------------------- 1 | package io.dts.server.struct; 2 | 3 | /** 4 | * 分支状态 5 | */ 6 | public enum BranchLogState { 7 | 8 | /** 9 | * 分支开始 10 | */ 11 | Begin(1), 12 | 13 | /** 14 | * 分支成功 15 | */ 16 | Success(2), 17 | 18 | /** 19 | * 分支失败 20 | */ 21 | Failed(3); 22 | 23 | 24 | /** 25 | * @param value 26 | */ 27 | private BranchLogState(int value) { 28 | this.value = value; 29 | } 30 | 31 | /** 32 | * @return 33 | */ 34 | public int getValue() { 35 | return value; 36 | } 37 | 38 | /** 39 | * 状态值 40 | */ 41 | private int value; 42 | } 43 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/util/ThreadFactoryImpl.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.util; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.AtomicLong; 5 | 6 | 7 | public class ThreadFactoryImpl implements ThreadFactory { 8 | private final AtomicLong threadIndex = new AtomicLong(0); 9 | private final String threadNamePrefix; 10 | 11 | public ThreadFactoryImpl(final String threadNamePrefix) { 12 | this.threadNamePrefix = threadNamePrefix; 13 | } 14 | 15 | @Override 16 | public Thread newThread(Runnable r) { 17 | return new Thread(r, threadNamePrefix + this.threadIndex.incrementAndGet()); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /dts-example/dts-example-api/src/main/proto/example/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | //option java_multiple_files = true; 3 | option java_package = "com.quancheng.examples.model"; 4 | option java_outer_classname = "Hello"; 5 | package com.quancheng.examples.model; 6 | import "saluki/validator.proto"; 7 | 8 | // The request message containing the user's name. 9 | message HelloRequest { 10 | string name = 1; 11 | } 12 | // The response message containing the greetings 13 | message HelloReply { 14 | string message = 1; 15 | } 16 | 17 | message Project { 18 | string id = 1; 19 | } 20 | 21 | enum PhoneType { 22 | MOBILE = 0; 23 | HOME = 1; 24 | WORK = 2; 25 | } 26 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/api/IDtsDataSource.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.api; 2 | 3 | import java.sql.SQLException; 4 | 5 | import javax.sql.DataSource; 6 | 7 | import io.dts.parser.struct.DatabaseType; 8 | 9 | public interface IDtsDataSource extends DataSource { 10 | /** 11 | * 获取不带事务的datasource 12 | * 13 | * @return DataSource 14 | * @throws SQLException 15 | */ 16 | DataSource getRawDataSource() throws SQLException; 17 | 18 | /** 19 | * 获取数据源名:unitName+appName+dbKey 20 | * 21 | * @return 22 | */ 23 | String getDbName(); 24 | 25 | 26 | DatabaseType getDatabaseType() throws SQLException; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/src/main/java/com/quancheng/saluki/example/client/ProxyServiceController.java: -------------------------------------------------------------------------------- 1 | package com.quancheng.saluki.example.client; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.quancheng.examples.model.hello.HelloReply; 8 | 9 | @RestController 10 | @RequestMapping("/proxy") 11 | public class ProxyServiceController { 12 | 13 | 14 | @Autowired 15 | private RpcService rpcService; 16 | 17 | @RequestMapping("/hello") 18 | public HelloReply hello() { 19 | return rpcService.callService(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/api/IDtsConnection.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.api; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | import io.dts.parser.struct.TxcRuntimeContext; 7 | 8 | public interface IDtsConnection extends Connection { 9 | /** 10 | * 获取不带事务的数据库连接 11 | * 12 | * @return 13 | * @throws SQLException 14 | */ 15 | Connection getRawConnection() throws SQLException; 16 | 17 | /** 18 | * 获取TxcDataSource 19 | * 20 | * @return 21 | * @throws SQLException 22 | */ 23 | IDtsDataSource getDataSource() throws SQLException; 24 | 25 | /** 26 | * 获取上下文 27 | * @return 28 | */ 29 | TxcRuntimeContext getTxcContext(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /dts-datasource/src/main/java/io/dts/datasource/UndoLogMode.java: -------------------------------------------------------------------------------- 1 | package io.dts.datasource; 2 | 3 | /** 4 | * Created by guoyubo on 2017/9/20. 5 | */ 6 | public enum UndoLogMode { 7 | /** 8 | * 正常日志 9 | */ 10 | COMMON_LOG(0), 11 | 12 | /** 13 | * 错误日志 14 | */ 15 | ERROR_LOG(1), 16 | 17 | /** 18 | * 已删除日志 19 | */ 20 | DELETED_LOG(2), 21 | 22 | /** 23 | * rt journel for record servers that has been connected by rt-rm 24 | */ 25 | RT_JOURNEL(3), 26 | 27 | /** 28 | * 数据库表Meta 29 | */ 30 | TABLE_MATA(9001); 31 | 32 | private UndoLogMode(int value) { 33 | this.value = value; 34 | } 35 | 36 | public int getValue() { 37 | return value; 38 | } 39 | 40 | private int value; 41 | } 42 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/heatbeat/HeartbeatRequestHeader.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.protocol.heatbeat; 2 | 3 | import io.dts.common.protocol.RequestMessage; 4 | import io.dts.remoting.CommandCustomHeader; 5 | import io.dts.remoting.exception.RemotingCommandException; 6 | 7 | 8 | public class HeartbeatRequestHeader implements CommandCustomHeader, RequestMessage { 9 | 10 | private String clientOrResourceInfo; 11 | 12 | public String getClientOrResourceInfo() { 13 | return clientOrResourceInfo; 14 | } 15 | 16 | public void setClientOrResourceInfo(String dbName) { 17 | this.clientOrResourceInfo = dbName; 18 | } 19 | 20 | @Override 21 | public void checkFields() throws RemotingCommandException {} 22 | 23 | } 24 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/api/DtsClientMessageSender.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.api; 2 | 3 | import io.dts.common.cluster.ServerCluster; 4 | import io.dts.common.exception.DtsException; 5 | import io.dts.common.protocol.RequestMessage; 6 | 7 | /** 8 | * client同步调用server端接口 9 | * 10 | */ 11 | public interface DtsClientMessageSender extends BaseMessageSender { 12 | 13 | public T invoke(RequestMessage msg, long timeout) throws DtsException; 14 | 15 | public T invoke(String serverAddress, RequestMessage msg, long timeout) throws DtsException; 16 | 17 | public T invoke(RequestMessage msg) throws DtsException; 18 | 19 | default String selectAddress() { 20 | return ServerCluster.getServerCluster().select(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/DataSourceHolder.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager; 2 | 3 | import javax.sql.DataSource; 4 | 5 | import io.dts.common.cluster.ServerCluster; 6 | 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | /** 10 | * Created by guoyubo on 2017/9/27. 11 | */ 12 | public class DataSourceHolder { 13 | 14 | private static ConcurrentHashMap dataSourceMap = new ConcurrentHashMap<>(); 15 | 16 | public static void registerDataSource(String dbName, DataSource dataSource) { 17 | ServerCluster.getServerCluster(); 18 | dataSourceMap.put(dbName, dataSource); 19 | } 20 | 21 | public static DataSource getDataSource(String dbName) { 22 | return dataSourceMap.get(dbName); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /dts-client/src/main/java/io/dts/client/template/TxcTransactionTemplate.java: -------------------------------------------------------------------------------- 1 | package io.dts.client.template; 2 | 3 | 4 | 5 | import io.dts.client.api.DtsTransactionManager; 6 | import io.dts.client.api.impl.DefaultDtsTransactionManager; 7 | 8 | 9 | public class TxcTransactionTemplate { 10 | private DtsTransactionManager tm = DefaultDtsTransactionManager.getInstance(); 11 | 12 | 13 | public Object run(TxcCallback callback, long timeout) throws Throwable { 14 | try { 15 | tm.begin(timeout); 16 | Object obj = callback.callback(); 17 | tm.commit(); 18 | return obj; 19 | } catch (Throwable e) { 20 | try { 21 | tm.rollback(); 22 | } catch (Throwable ee) { 23 | } 24 | throw e; 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/exception/DtsException.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.exception; 2 | 3 | 4 | public class DtsException extends RuntimeException { 5 | 6 | private static final long serialVersionUID = 1L; 7 | 8 | private int result; 9 | 10 | public DtsException() {} 11 | 12 | public DtsException(int result, String msg) { 13 | super(msg); 14 | this.setResult(result); 15 | } 16 | 17 | public DtsException(String msg) { 18 | this(1, msg); 19 | } 20 | 21 | public DtsException(Throwable th) { 22 | super(th); 23 | this.result = 0; 24 | } 25 | 26 | public DtsException(Throwable th, String msg) { 27 | super(msg, th); 28 | this.result = 0; 29 | } 30 | 31 | public int getResult() { 32 | return result; 33 | } 34 | 35 | public void setResult(int result) { 36 | this.result = result; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/ResponseMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol; 15 | 16 | /** 17 | * @author liushiming 18 | * @version ResponseMessage.java, v 0.0.1 2017年9月6日 下午5:53:06 liushiming 19 | */ 20 | public interface ResponseMessage { 21 | } 22 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/RequestMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol; 15 | 16 | /** 17 | * @author liushiming 18 | * @version RequestHeaderMessage.java, v 0.0.1 2017年9月12日 下午3:53:43 liushiming 19 | */ 20 | public interface RequestMessage { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/struct/ContextStep2.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.struct; 2 | 3 | 4 | public class ContextStep2 { 5 | private long globalXid; 6 | private String xid; 7 | private long branchId; 8 | private String dbname; 9 | 10 | public long getGlobalXid() { 11 | return globalXid; 12 | } 13 | 14 | public void setGlobalXid(long globalXid) { 15 | this.globalXid = globalXid; 16 | } 17 | 18 | public String getXid() { 19 | return xid; 20 | } 21 | 22 | public void setXid(String xid) { 23 | this.xid = xid; 24 | } 25 | 26 | public long getBranchId() { 27 | return branchId; 28 | } 29 | 30 | public void setBranchId(long branchId) { 31 | this.branchId = branchId; 32 | } 33 | 34 | 35 | 36 | public String getDbname() { 37 | return dbname; 38 | } 39 | 40 | public void setDbname(String dbname) { 41 | this.dbname = dbname; 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/undo/DtsUndo.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.undo; 2 | 3 | import java.util.List; 4 | 5 | import io.dts.common.exception.DtsException; 6 | import io.dts.parser.struct.RollbackInfor; 7 | 8 | /** 9 | * Created by guoyubo on 2017/10/16. 10 | */ 11 | public interface DtsUndo { 12 | 13 | List buildRollbackSql(); 14 | 15 | 16 | public static DtsUndo createDtsundo(RollbackInfor undoLog) { 17 | DtsUndo undo = null; 18 | switch (undoLog.getSqlType()) { 19 | case DELETE: 20 | undo = new DtsDeleteUndo(undoLog); 21 | break; 22 | case INSERT: 23 | undo = new DtsInsertUndo(undoLog); 24 | break; 25 | case UPDATE: 26 | undo = new DtsUpdateUndo(undoLog); 27 | break; 28 | default: 29 | throw new DtsException("sqltype error:" + undoLog.getSqlType()); 30 | } 31 | 32 | return undo; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/src/main/java/com/quancheng/saluki/example/SalukiExampleClientApp.java: -------------------------------------------------------------------------------- 1 | package com.quancheng.saluki.example; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.CommandLineRunner; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | import io.dts.client.aop.DtsTransactionScaner; 9 | import io.dts.client.aop.annotation.EnableDtsConfiguration; 10 | 11 | @SpringBootApplication 12 | @EnableDtsConfiguration 13 | public class SalukiExampleClientApp implements CommandLineRunner { 14 | 15 | @Autowired 16 | private DtsTransactionScaner scaner; 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(SalukiExampleClientApp.class, args); 20 | } 21 | 22 | @Override 23 | public void run(String... arg0) throws Exception { 24 | System.out.println(scaner); 25 | } 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /dts-client/src/main/java/io/dts/client/aop/MethodDesc.java: -------------------------------------------------------------------------------- 1 | package io.dts.client.aop; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import io.dts.client.aop.annotation.DtsTransaction; 6 | 7 | 8 | public class MethodDesc { 9 | private DtsTransaction trasactionAnnotation; 10 | private Method m; 11 | 12 | /** 13 | * @param trasactionAnnotation 14 | * @param m 15 | */ 16 | public MethodDesc(DtsTransaction trasactionAnnotation, Method m) { 17 | super(); 18 | this.trasactionAnnotation = trasactionAnnotation; 19 | this.m = m; 20 | } 21 | 22 | public DtsTransaction getTrasactionAnnotation() { 23 | return trasactionAnnotation; 24 | } 25 | 26 | public void setTrasactionAnnotation(DtsTransaction trasactionAnnotation) { 27 | this.trasactionAnnotation = trasactionAnnotation; 28 | } 29 | 30 | public Method getM() { 31 | return m; 32 | } 33 | 34 | public void setM(Method m) { 35 | this.m = m; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/netty/NettyEventType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.netty; 17 | 18 | /** 19 | * Netty产生的事件类型 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public enum NettyEventType { 25 | CONNECT, 26 | CLOSE, 27 | IDLE, 28 | EXCEPTION 29 | } 30 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/ResponseCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol; 15 | 16 | import io.dts.remoting.protocol.RemotingSysResponseCode; 17 | 18 | /** 19 | * @author liushiming 20 | * @version ResponseCode.java, v 0.0.1 2017年9月6日 下午2:11:18 liushiming 21 | */ 22 | public class ResponseCode extends RemotingSysResponseCode { 23 | 24 | } 25 | -------------------------------------------------------------------------------- /dts-rm-rabbit/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-rm-rabbit 12 | dts-rm-rabbit 13 | http://maven.apache.org 14 | 15 | UTF-8 16 | 17 | 18 | 19 | org.apache.rocketmq 20 | rocketmq-client 21 | 4.0.0-incubating 22 | 23 | 24 | io.dts 25 | dts-resourcemanager 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/protocol/RemotingCommandType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.protocol; 17 | 18 | /** 19 | * 标识RemotingCommand是请求还是应答类型 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public enum RemotingCommandType { 25 | REQUEST_COMMAND, 26 | RESPONSE_COMMAND; 27 | } 28 | -------------------------------------------------------------------------------- /dts-rm-rocketmq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-rm-rocketmq 12 | dts-rocketmq 13 | http://maven.apache.org 14 | 15 | UTF-8 16 | 17 | 18 | 19 | org.apache.rocketmq 20 | rocketmq-client 21 | 4.0.0-incubating 22 | 23 | 24 | io.dts 25 | dts-resourcemanager 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/struct/TxcLine.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.struct; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class TxcLine { 9 | /** 10 | * 保存与数据库表对应的一行内容 11 | */ 12 | private List fields = null; 13 | 14 | @JSONField(serialize = false) 15 | private TxcTableMeta tableMeta; 16 | 17 | public TxcTableMeta getTableMeta() { 18 | return tableMeta; 19 | } 20 | 21 | public void setTableMeta(TxcTableMeta tableMeta) { 22 | this.tableMeta = tableMeta; 23 | } 24 | 25 | public TxcLine() { 26 | } 27 | 28 | public List getFields() { 29 | return fields; 30 | } 31 | 32 | public void addFields(TxcField field) { 33 | if (fields == null) { 34 | fields = new ArrayList(); 35 | } 36 | fields.add(field); 37 | } 38 | 39 | public void setFields(List fields) { 40 | this.fields = fields; 41 | } 42 | 43 | public int getFieldsNum() { 44 | return fields.size(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dts-remoting/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | io.dts 5 | dts 6 | 0.0.1-SNAPSHOT 7 | 8 | 4.0.0 9 | dts-remoting 10 | jar 11 | 12 | 13 | io.netty 14 | netty-all 15 | 16 | 17 | org.slf4j 18 | slf4j-api 19 | 20 | 21 | com.alibaba 22 | fastjson 23 | 24 | 25 | junit 26 | junit 27 | 4.11 28 | test 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/InvokeCallback.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting; 17 | 18 | import io.dts.remoting.netty.ResponseFuture; 19 | 20 | /** 21 | * 异步调用应答回调接口 22 | * 23 | * @author shijia.wxr 24 | * @since 2013-7-13 25 | */ 26 | public interface InvokeCallback { 27 | public void operationComplete(final ResponseFuture responseFuture); 28 | } 29 | -------------------------------------------------------------------------------- /dts-microservice-support/dts-saluki-support/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts-microservice-support 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-saluki-support 12 | dts-saluki-support 13 | http://maven.apache.org 14 | 15 | 16 | com.quancheng.saluki 17 | saluki-core 18 | provided 19 | 20 | 21 | io.dts 22 | dts-datasource 23 | 24 | 25 | io.dts 26 | dts-client 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /dts-datasource/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-datasource 12 | dts-datasource 13 | http://maven.apache.org 14 | 15 | UTF-8 16 | 17 | 18 | 19 | io.dts 20 | dts-common 21 | 22 | 23 | io.dts 24 | dts-resourcemanager 25 | 26 | 27 | io.dts 28 | dts-parser 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/struct/GlobalLogState.java: -------------------------------------------------------------------------------- 1 | package io.dts.server.struct; 2 | 3 | /** 4 | * 5 | * 全局事务状态 6 | */ 7 | public enum GlobalLogState { 8 | 9 | /** 10 | * 开始 11 | */ 12 | Begin(1), 13 | 14 | /** 15 | * 已提交 16 | */ 17 | Committed(2), 18 | 19 | /** 20 | * 已回滚 21 | */ 22 | Rollbacked(3), 23 | 24 | /** 25 | * 提交失败 26 | */ 27 | CmmittedFailed(4), 28 | 29 | /** 30 | * 回滚失败 31 | */ 32 | RollbackFailed(5); 33 | /** 34 | * @param value 35 | */ 36 | private GlobalLogState(int value) { 37 | this.value = value; 38 | } 39 | 40 | /** 41 | * @return 42 | */ 43 | public int getValue() { 44 | return value; 45 | } 46 | 47 | /** 48 | * 状态值 49 | */ 50 | private int value; 51 | 52 | public static GlobalLogState parse(int value) { 53 | for (GlobalLogState state : GlobalLogState.values()) { 54 | if (state.getValue() == value) { 55 | return state; 56 | } 57 | } 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/CommandCustomHeader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting; 17 | 18 | import io.dts.remoting.exception.RemotingCommandException; 19 | 20 | /** 21 | * RemotingCommand中自定义字段反射对象的公共接口 22 | * 23 | * @author shijia.wxr 24 | * @since 2013-7-13 25 | */ 26 | public interface CommandCustomHeader { 27 | public void checkFields() throws RemotingCommandException; 28 | } 29 | -------------------------------------------------------------------------------- /dts-datasource/src/main/java/io/dts/datasource/wrapper/executor/StatementModel.java: -------------------------------------------------------------------------------- 1 | 2 | package io.dts.datasource.wrapper.executor; 3 | 4 | import java.sql.SQLException; 5 | 6 | import io.dts.parser.struct.SqlType; 7 | import io.dts.resourcemanager.api.IDtsDataSource; 8 | import io.dts.resourcemanager.api.IDtsStatement; 9 | 10 | 11 | public final class StatementModel { 12 | 13 | private final IDtsStatement statement; 14 | 15 | private final IDtsDataSource dataSource; 16 | 17 | private final String sql; 18 | 19 | public StatementModel(IDtsDataSource dataSource, IDtsStatement statement, String sql) { 20 | super(); 21 | this.statement = statement; 22 | this.dataSource = dataSource; 23 | this.sql = sql; 24 | } 25 | 26 | public SqlType getSqlType() throws SQLException { 27 | return SqlTypeParser.getSqlType(sql); 28 | } 29 | 30 | public IDtsDataSource getDataSource() { 31 | return dataSource; 32 | } 33 | 34 | public String getSql() { 35 | return sql; 36 | } 37 | 38 | public IDtsStatement getStatement() { 39 | return statement; 40 | } 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/DtsSQLStatement.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser; 2 | 3 | import com.alibaba.druid.sql.ast.SQLStatement; 4 | 5 | import io.dts.parser.struct.DatabaseType; 6 | import io.dts.parser.struct.SqlType; 7 | 8 | /** 9 | * Created by guoyubo on 2017/9/23. 10 | */ 11 | public class DtsSQLStatement { 12 | 13 | private String sql; 14 | 15 | private SqlType sqlType; 16 | 17 | private DatabaseType databaseType; 18 | 19 | private SQLStatement sqlStatement; 20 | 21 | public DtsSQLStatement(final String sql, final SqlType sqlType, final DatabaseType databaseType, 22 | final SQLStatement sqlStatement) { 23 | this.sql = sql; 24 | this.sqlType = sqlType; 25 | this.databaseType = databaseType; 26 | this.sqlStatement = sqlStatement; 27 | } 28 | 29 | public SQLStatement getSQLStatement() { 30 | return sqlStatement; 31 | } 32 | 33 | public SqlType getType() { 34 | return sqlType; 35 | } 36 | 37 | public DatabaseType getDatabaseType() { 38 | return databaseType; 39 | } 40 | 41 | public String getSql() { 42 | return sql; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/cluster/ServerCluster.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.cluster; 15 | 16 | /** 17 | * @author liushiming 18 | * @version ServerAddressSelector.java, v 0.0.1 2017年10月17日 下午5:05:26 liushiming 19 | */ 20 | public interface ServerCluster { 21 | 22 | 23 | public String select(); 24 | 25 | 26 | public Integer registry(int port); 27 | 28 | public static ServerCluster getServerCluster() { 29 | return ZookeeperServerCluster.getInstance(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/struct/SqlType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2015 dangdang.com.

Licensed under the Apache License, Version 2.0 (the 3 | * "License"); you may not use this file except in compliance with the License. You may obtain a 4 | * copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License 9 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 10 | * or implied. See the License for the specific language governing permissions and limitations under 11 | * the License.

12 | */ 13 | 14 | package io.dts.parser.struct; 15 | 16 | /** 17 | * SQL Type. 18 | * 19 | */ 20 | public enum SqlType { 21 | SELECT, 22 | 23 | INSERT, 24 | 25 | UPDATE, 26 | 27 | DELETE; 28 | 29 | public static SqlType convert(final String sql) { 30 | for (SqlType sqlType : SqlType.values()) { 31 | if (sqlType.name().toLowerCase().equals(sql.toLowerCase())) { 32 | return sqlType; 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/annotation/CFNotNull.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.annotation; 17 | 18 | import java.lang.annotation.*; 19 | 20 | 21 | /** 22 | * 表示字段不允许为空 23 | * 24 | * @author shijia.wxr 25 | * @since 2013-7-13 26 | */ 27 | @Documented 28 | @Retention(RetentionPolicy.RUNTIME) 29 | @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE }) 30 | public @interface CFNotNull { 31 | } 32 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/annotation/CFNullable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.annotation; 17 | 18 | import java.lang.annotation.*; 19 | 20 | 21 | /** 22 | * 标识字段可以非空 23 | * 24 | * @author shijia.wxr 25 | * @since 2013-7-13 26 | */ 27 | @Documented 28 | @Retention(RetentionPolicy.RUNTIME) 29 | @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE }) 30 | public @interface CFNullable { 31 | } 32 | -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/store/DtsLogDao.java: -------------------------------------------------------------------------------- 1 | package io.dts.server.store; 2 | 3 | 4 | import java.util.List; 5 | 6 | import io.dts.server.struct.BranchLog; 7 | import io.dts.server.struct.GlobalLog; 8 | 9 | public interface DtsLogDao { 10 | 11 | public void insertGlobalLog(GlobalLog globalLog); 12 | 13 | public void updateGlobalLog(GlobalLog globalLog); 14 | 15 | public void deleteGlobalLog(long tx_id); 16 | 17 | public GlobalLog getGlobalLog(long tx_id); 18 | 19 | public List getGlobalLogs(); 20 | 21 | public void insertBranchLog(BranchLog branchLog); 22 | 23 | public void updateBranchLog(BranchLog branchLog); 24 | 25 | public void updateBranchState(BranchLog branchLog); 26 | 27 | public void deleteBranchLog(long branchId); 28 | 29 | public List getBranchLogs(long txId); 30 | 31 | public List getBranchLogs(); 32 | 33 | public BranchLog getBranchLog(long branchId); 34 | 35 | public void insertBranchErrorLog(BranchLog branchLog); 36 | 37 | public void updateBranchErrorLog(BranchLog branchLog); 38 | 39 | public List findWaitNotifyErrorLog(int commit_type); 40 | } 41 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/exception/RemotingTooMuchRequestException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.exception; 17 | 18 | /** 19 | * 异步调用或者Oneway调用,堆积的请求超过信号量最大值 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public class RemotingTooMuchRequestException extends RemotingException { 25 | private static final long serialVersionUID = 4326919581254519654L; 26 | 27 | 28 | public RemotingTooMuchRequestException(String message) { 29 | super(message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/netty/NettyRequestProcessor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.netty; 17 | 18 | import io.dts.remoting.protocol.RemotingCommand; 19 | import io.netty.channel.ChannelHandlerContext; 20 | 21 | 22 | /** 23 | * 接收请求处理器,服务器与客户端通用 24 | * 25 | * @author shijia.wxr 26 | * @since 2013-7-13 27 | */ 28 | public interface NettyRequestProcessor { 29 | public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) 30 | throws Exception; 31 | } 32 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/undo/DtsInsertUndo.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.undo; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import io.dts.parser.struct.RollbackInfor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 11 | * @author xiaoyan 12 | */ 13 | public class DtsInsertUndo extends AbstractDtsUndo { 14 | 15 | public DtsInsertUndo(RollbackInfor txcUndoLogRollbackInfor) { 16 | super(txcUndoLogRollbackInfor); 17 | } 18 | 19 | @Override 20 | public List buildRollbackSql() { 21 | // 可一并删除,减少SQL数 22 | List sqls = Lists.newArrayList(); 23 | 24 | if (getPresentValue().getLinesNum() > 0) { 25 | String tableName = getPresentValue().getTableMeta().getTableName(); 26 | String pkName = getPresentValue().getTableMeta().getPkName(); 27 | 28 | StringBuilder sqlAppender = new StringBuilder(); 29 | sqlAppender.append("DELETE FROM "); 30 | sqlAppender.append(tableName); 31 | sqlAppender.append(" WHERE "); 32 | sqlAppender.append(linesExpressionSerialization(getPresentValue().getLines(), pkName, true)); 33 | 34 | sqls.add(sqlAppender.toString()); 35 | } 36 | return sqls; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dts-example/dts-example-provider/src/main/java/com/quancheng/saluki/example/repository/StudentDao.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package com.quancheng.saluki.example.repository; 15 | 16 | import org.springframework.data.repository.PagingAndSortingRepository; 17 | import org.springframework.stereotype.Repository; 18 | 19 | import com.quancheng.saluki.example.repository.entity.StudentDo; 20 | 21 | /** 22 | * @author liushiming 23 | * @version StudentRepository.java, v 0.0.1 2017年11月2日 下午2:14:50 liushiming 24 | */ 25 | @Repository 26 | public interface StudentDao extends PagingAndSortingRepository { 27 | 28 | } 29 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/exception/RemotingException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.exception; 17 | 18 | /** 19 | * 通信层异常父类 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public class RemotingException extends Exception { 25 | private static final long serialVersionUID = -5690687334570505110L; 26 | 27 | 28 | public RemotingException(String message) { 29 | super(message); 30 | } 31 | 32 | 33 | public RemotingException(String message, Throwable cause) { 34 | super(message, cause); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dts-example/dts-example-provider/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: dts-provider 4 | datasource: 5 | type: com.alibaba.druid.pool.DruidDataSource 6 | url: jdbc:mysql://127.0.0.1:3306/dts 7 | username: root 8 | password: 123 9 | driverClassName: com.mysql.jdbc.Driver 10 | initialSize: 5 11 | minIdle: 5 12 | maxActive: 20 13 | maxWait: 60000 14 | timeBetweenEvictionRunsMillis: 60000 15 | minEvictableIdleTimeMillis: 300000 16 | validationQuery: SELECT 1 FROM DUAL 17 | testWhileIdle: true 18 | testOnBorrow: false 19 | testOnReturn: false 20 | poolPreparedStatements: true 21 | maxPoolPreparedStatementPerConnectionSize: 20 22 | filters: stat,wall,log4j 23 | connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 24 | jpa: 25 | database: MYSQL 26 | show-sql: true 27 | generate-ddl: true 28 | hibernate: 29 | ddl-auto: update 30 | naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy 31 | properties: 32 | hibernate: 33 | dialect: org.hibernate.dialect.MySQL5InnoDBDialect 34 | server: 35 | port: 8083 36 | saluki: 37 | grpc: 38 | registryAddress: localhost:8500 39 | group: example 40 | version: 1.0.0 41 | realityRpcPort: 12201 -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/ResourceManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.resourcemanager; 15 | 16 | import io.dts.common.exception.DtsException; 17 | 18 | /** 19 | * @author liushiming 20 | * @version ResourceManager.java, v 0.0.1 2017年10月13日 下午2:23:40 liushiming 21 | */ 22 | public interface ResourceManager { 23 | 24 | public long register(String key) throws DtsException; 25 | 26 | public String getRegisterKey(); 27 | 28 | public void branchCommit(String xid, long branchId, String resourceInfo) throws DtsException; 29 | 30 | public void branchRollback(String xid, long branchId, String resourceInfo) throws DtsException; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/exception/RemotingCommandException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.exception; 17 | 18 | /** 19 | * 命令解析自定义字段时,校验字段有效性抛出异常 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public class RemotingCommandException extends RemotingException { 25 | private static final long serialVersionUID = -6061365915274953096L; 26 | 27 | 28 | public RemotingCommandException(String message) { 29 | super(message, null); 30 | } 31 | 32 | 33 | public RemotingCommandException(String message, Throwable cause) { 34 | super(message, cause); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/exception/RemotingConnectException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.exception; 17 | 18 | /** 19 | * Client连接Server失败,抛出此异常 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public class RemotingConnectException extends RemotingException { 25 | private static final long serialVersionUID = -5565366231695911316L; 26 | 27 | 28 | public RemotingConnectException(String addr) { 29 | this(addr, null); 30 | } 31 | 32 | 33 | public RemotingConnectException(String addr, Throwable cause) { 34 | super("connect to <" + addr + "> failed", cause); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/exception/RemotingSendRequestException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.exception; 17 | 18 | /** 19 | * RPC调用中,客户端发送请求失败,抛出此异常 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public class RemotingSendRequestException extends RemotingException { 25 | private static final long serialVersionUID = 5391285827332471674L; 26 | 27 | 28 | public RemotingSendRequestException(String addr) { 29 | this(addr, null); 30 | } 31 | 32 | 33 | public RemotingSendRequestException(String addr, Throwable cause) { 34 | super("send request to <" + addr + "> failed", cause); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dts-resourcemanager/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-resourcemanager 12 | dts-resourcemanager 13 | http://maven.apache.org 14 | 15 | UTF-8 16 | 17 | 18 | 19 | io.dts 20 | dts-remoting 21 | 22 | 23 | io.dts 24 | dts-common 25 | 26 | 27 | io.dts 28 | dts-parser 29 | 30 | 31 | com.google.guava 32 | guava 33 | 34 | 35 | org.springframework 36 | spring-jdbc 37 | ${spring.version} 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/struct/TxcField.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.struct; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | 5 | /** 6 | * 对数据库一个属性字段的描述 7 | * 8 | * @author xiaoyan 9 | */ 10 | public class TxcField { 11 | /** 12 | * 属性名 13 | */ 14 | private String name; 15 | 16 | /** 17 | * 属性类型:java.sql.Types 18 | */ 19 | private int type; 20 | 21 | /** 22 | * 属性值 23 | */ 24 | private Object value; 25 | 26 | /** 27 | * 默认无参构造函数 28 | */ 29 | public TxcField() { 30 | } 31 | 32 | public String getFieldName() { 33 | return name; 34 | } 35 | 36 | public void setFieldName(String attrName) { 37 | this.name = attrName; 38 | } 39 | 40 | public int getFieldType() { 41 | return type; 42 | } 43 | 44 | public void setFieldType(int attrType) { 45 | this.type = attrType; 46 | } 47 | 48 | public Object getFieldValue() { 49 | return value; 50 | } 51 | 52 | public void setFieldValue(Object value) { 53 | this.value = jsonObjectSerialize(value); 54 | } 55 | 56 | public static Object jsonObjectSerialize(Object value) { 57 | if (value == null) { 58 | return null; 59 | } else if (java.util.Date.class.isAssignableFrom(value.getClass())) { 60 | return JSON.toJSONString(value); 61 | } else { 62 | return value; 63 | } 64 | } 65 | 66 | public boolean isKey(String pkname) { 67 | return name.equalsIgnoreCase(pkname); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/ChannelEventListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting; 17 | 18 | import io.netty.channel.Channel; 19 | 20 | 21 | /** 22 | * 监听Channel的事件,包括连接断开、连接建立、连接异常,传送这些事件到应用层 23 | * 24 | * @author shijia.wxr 25 | * @since 2013-7-13 26 | */ 27 | public interface ChannelEventListener { 28 | public void onChannelConnect(final String remoteAddr, final Channel channel); 29 | 30 | 31 | public void onChannelClose(final String remoteAddr, final Channel channel); 32 | 33 | 34 | public void onChannelException(final String remoteAddr, final Channel channel); 35 | 36 | 37 | public void onChannelIdle(final String remoteAddr, final Channel channel); 38 | } 39 | -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/network/FutureTaskExt.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.server.network; 15 | 16 | import java.util.concurrent.Callable; 17 | import java.util.concurrent.FutureTask; 18 | 19 | /** 20 | * @author liushiming 21 | * @version FutureTaskExt.java, v 0.0.1 2017年9月12日 下午6:43:30 liushiming 22 | */ 23 | public class FutureTaskExt extends FutureTask { 24 | private final Runnable runnable; 25 | 26 | public FutureTaskExt(final Callable callable) { 27 | super(callable); 28 | this.runnable = null; 29 | } 30 | 31 | public FutureTaskExt(final Runnable runnable, final V result) { 32 | super(runnable, result); 33 | this.runnable = runnable; 34 | } 35 | 36 | public Runnable getRunnable() { 37 | return runnable; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/undo/DtsDeleteUndo.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.undo; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import io.dts.parser.struct.RollbackInfor; 6 | import io.dts.parser.struct.TxcField; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * 12 | * @author xiaoyan 13 | */ 14 | public class DtsDeleteUndo extends AbstractDtsUndo { 15 | 16 | public DtsDeleteUndo(RollbackInfor txcUndoLogRollbackInfor) { 17 | super(txcUndoLogRollbackInfor); 18 | } 19 | 20 | @Override 21 | public List buildRollbackSql() { 22 | List sqls = Lists.newArrayList(); 23 | // 逐行反向写回数据库 24 | for (int index = 0; index < getOriginalValue().getLinesNum(); index++) { 25 | // 得到行的所有属性 26 | String tableName = getOriginalValue().getTableMeta().getTableName(); 27 | List fields = getOriginalValue().getLines().get(index).getFields(); 28 | StringBuilder sqlAppender = new StringBuilder(); 29 | 30 | sqlAppender.append("INSERT INTO "); 31 | sqlAppender.append(tableName); 32 | sqlAppender.append("("); 33 | sqlAppender.append(fieldNamesSerialization(fields)); 34 | sqlAppender.append(")"); 35 | 36 | sqlAppender.append(" VALUES "); 37 | sqlAppender.append("("); 38 | sqlAppender.append(fieldsValueSerialization(fields)); 39 | sqlAppender.append(")"); 40 | sqls.add(sqlAppender.toString()); 41 | } 42 | return sqls; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/api/DtsServerMessageHandler.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.api; 2 | 3 | import io.dts.common.protocol.header.BeginMessage; 4 | import io.dts.common.protocol.header.BeginResultMessage; 5 | import io.dts.common.protocol.header.GlobalCommitMessage; 6 | import io.dts.common.protocol.header.GlobalCommitResultMessage; 7 | import io.dts.common.protocol.header.GlobalRollbackMessage; 8 | import io.dts.common.protocol.header.GlobalRollbackResultMessage; 9 | import io.dts.common.protocol.header.RegisterMessage; 10 | import io.dts.common.protocol.header.RegisterResultMessage; 11 | 12 | 13 | public interface DtsServerMessageHandler { 14 | 15 | /** 16 | * 开始一个分布式事务 17 | * 18 | */ 19 | public void handleMessage(String clientIp, BeginMessage message, 20 | BeginResultMessage resultMessage); 21 | 22 | /** 23 | * 处理全局事务提交 24 | * 25 | */ 26 | public void handleMessage(String clientIp, GlobalCommitMessage message, 27 | GlobalCommitResultMessage resultMessage); 28 | 29 | /** 30 | * 处理全局事务回滚 31 | * 32 | */ 33 | public void handleMessage(String clientIp, GlobalRollbackMessage message, 34 | GlobalRollbackResultMessage resultMessage); 35 | 36 | /** 37 | * 处理事务分支注册 38 | * 39 | */ 40 | public void handleMessage(String clientIp, RegisterMessage message, 41 | RegisterResultMessage resultMessage); 42 | 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /dts-microservice-support/dts-springcloud-support/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts-microservice-support 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-springcloud-support 12 | dts-springcloud-support 13 | http://maven.apache.org 14 | 15 | 16 | org.springframework.cloud 17 | spring-cloud-starter-feign 18 | provided 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-starter-hystrix 23 | provided 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 1.5.6.RELEASE 29 | 30 | 31 | io.dts 32 | dts-datasource 33 | 34 | 35 | io.dts 36 | dts-client 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /dts-remoting/src/test/java/io/dts/remoting/SyncInvokeTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * $Id: SyncInvokeTest.java 1831 2013-05-16 01:39:51Z shijia.wxr $ 3 | */ 4 | package io.dts.remoting; 5 | 6 | import io.dts.remoting.RemotingClient; 7 | import io.dts.remoting.RemotingServer; 8 | import io.dts.remoting.protocol.RemotingCommand; 9 | 10 | import org.junit.Test; 11 | 12 | import static org.junit.Assert.assertTrue; 13 | 14 | 15 | /** 16 | * @author shijia.wxr 17 | */ 18 | public class SyncInvokeTest { 19 | @Test 20 | public void test_RPC_Sync() throws Exception { 21 | RemotingServer server = NettyRPCTest.createRemotingServer(); 22 | RemotingClient client = NettyRPCTest.createRemotingClient(); 23 | 24 | for (int i = 0; i < 100; i++) { 25 | try { 26 | RemotingCommand request = RemotingCommand.createRequestCommand(0, null); 27 | RemotingCommand response = client.invokeSync("localhost:8888", request, 1000 * 3); 28 | System.out.println(i + "\t" + "invoke result = " + response); 29 | assertTrue(response != null); 30 | } 31 | catch (Exception e) { 32 | e.printStackTrace(); 33 | throw e; 34 | } 35 | } 36 | 37 | client.shutdown(); 38 | server.shutdown(); 39 | System.out.println("-----------------------------------------------------------------"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/struct/UndoLogMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.resourcemanager.struct; 15 | 16 | /** 17 | * @author liushiming 18 | * @version UndoLogMode.java, v 0.0.1 2017年10月25日 下午6:31:03 liushiming 19 | */ 20 | public enum UndoLogMode { 21 | /** 22 | * 正常日志 23 | */ 24 | COMMON_LOG(0), 25 | 26 | /** 27 | * 错误日志 28 | */ 29 | ERROR_LOG(1), 30 | 31 | /** 32 | * 已删除日志 33 | */ 34 | DELETED_LOG(2), 35 | 36 | /** 37 | * rt journel for record servers that has been connected by rt-rm 38 | */ 39 | RT_JOURNEL(3), 40 | 41 | /** 42 | * 数据库表Meta 43 | */ 44 | TABLE_MATA(9001); 45 | 46 | private UndoLogMode(int value) { 47 | this.value = value; 48 | } 49 | 50 | public int getValue() { 51 | return value; 52 | } 53 | 54 | private int value; 55 | } 56 | -------------------------------------------------------------------------------- /dts-server/src/main/assembly/assembly.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | assembly 6 | 7 | tar.gz 8 | 9 | 10 | 11 | src/main/bin 12 | hybrid-server/bin 13 | 14 | 15 | * 16 | 17 | 18 | 19 | src/main/conf 20 | hybrid-server/conf 21 | 22 | 23 | * 24 | 25 | 26 | 27 | src/main/logs 28 | hybrid-server/logs 29 | 30 | 31 | * 32 | 33 | 34 | 35 | 36 | 37 | 38 | false 39 | compile 40 | hybrid-server/lib 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /dts-client/src/main/java/io/dts/client/aop/annotation/EnableDtsConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.client.aop.annotation; 15 | 16 | import java.lang.annotation.Documented; 17 | import java.lang.annotation.ElementType; 18 | import java.lang.annotation.Inherited; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | import org.springframework.context.annotation.Import; 24 | 25 | import io.dts.client.aop.DtsTransactionScaner; 26 | 27 | /** 28 | * @author liushiming 29 | * @version EnableDtsConfiguration.java, v 0.0.1 2017年11月10日 下午4:04:10 liushiming 30 | */ 31 | @Target(ElementType.TYPE) 32 | @Retention(RetentionPolicy.RUNTIME) 33 | @Documented 34 | @Inherited 35 | @Import(DtsTransactionScaner.class) 36 | public @interface EnableDtsConfiguration { 37 | 38 | } 39 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/common/Pair.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.common; 17 | 18 | /** 19 | * 包装2个对象 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public class Pair { 25 | private T1 object1; 26 | private T2 object2; 27 | 28 | 29 | public Pair(T1 object1, T2 object2) { 30 | this.object1 = object1; 31 | this.object2 = object2; 32 | } 33 | 34 | 35 | public T1 getObject1() { 36 | return object1; 37 | } 38 | 39 | 40 | public void setObject1(T1 object1) { 41 | this.object1 = object1; 42 | } 43 | 44 | 45 | public T2 getObject2() { 46 | return object2; 47 | } 48 | 49 | 50 | public void setObject2(T2 object2) { 51 | this.object2 = object2; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dts-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-common 12 | dts-common 13 | http://maven.apache.org 14 | 15 | 16 | io.dts 17 | dts-remoting 18 | 19 | 20 | commons-lang 21 | commons-lang 22 | 23 | 24 | commons-io 25 | commons-io 26 | 27 | 28 | com.google.guava 29 | guava 30 | 31 | 32 | com.alibaba 33 | fastjson 34 | 35 | 36 | org.apache.curator 37 | curator-recipes 38 | 2.11.1 39 | 40 | 41 | io.netty 42 | netty 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /dts-example/dts-example-provider/src/main/java/com/quancheng/saluki/example/server/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quancheng.saluki.example.server; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.transaction.annotation.Transactional; 5 | 6 | import com.quancheng.examples.model.hello.HelloReply; 7 | import com.quancheng.examples.model.hello.HelloRequest; 8 | import com.quancheng.examples.service.HelloService; 9 | import com.quancheng.saluki.boot.SalukiService; 10 | import com.quancheng.saluki.core.common.RpcContext; 11 | import com.quancheng.saluki.example.repository.StudentDao; 12 | import com.quancheng.saluki.example.repository.entity.StudentDo; 13 | 14 | @SalukiService 15 | public class HelloServiceImpl implements HelloService { 16 | 17 | @Autowired 18 | private StudentDao studentDao; 19 | 20 | @Override 21 | @Transactional 22 | public HelloReply dtsNormal(HelloRequest hellorequest) { 23 | System.out.println(RpcContext.getContext().get("123")); 24 | StudentDo studentDo = new StudentDo(); 25 | studentDo.setName("liushiming"); 26 | studentDao.save(studentDo); 27 | HelloReply reply = new HelloReply(); 28 | reply.setMessage("update"); 29 | return reply; 30 | } 31 | 32 | @Override 33 | public HelloReply dtsException(HelloRequest hellorequest) { 34 | throw new RuntimeException("rollback"); 35 | // HelloReply reply = new HelloReply(); 36 | // reply.setMessage("none"); 37 | // return reply; 38 | } 39 | 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /dts-datasource/src/main/java/io/dts/datasource/AbstractDtsDataSource.java: -------------------------------------------------------------------------------- 1 | package io.dts.datasource; 2 | 3 | import java.io.PrintWriter; 4 | import java.sql.SQLException; 5 | import java.sql.SQLFeatureNotSupportedException; 6 | import java.util.logging.Logger; 7 | 8 | import io.dts.resourcemanager.api.IDtsDataSource; 9 | 10 | 11 | /** 12 | * Created by guoyubo on 2017/9/20. 13 | */ 14 | public abstract class AbstractDtsDataSource implements IDtsDataSource { 15 | 16 | @Override 17 | public T unwrap(final Class iface) throws SQLException { 18 | return getRawDataSource().unwrap(iface); 19 | } 20 | 21 | @Override 22 | public boolean isWrapperFor(final Class iface) throws SQLException { 23 | return getRawDataSource().isWrapperFor(iface); 24 | } 25 | 26 | @Override 27 | public PrintWriter getLogWriter() throws SQLException { 28 | return getRawDataSource().getLogWriter(); 29 | } 30 | 31 | @Override 32 | public void setLogWriter(final PrintWriter out) throws SQLException { 33 | getRawDataSource().setLogWriter(out); 34 | } 35 | 36 | @Override 37 | public void setLoginTimeout(final int seconds) throws SQLException { 38 | getRawDataSource().setLoginTimeout(seconds); 39 | } 40 | 41 | @Override 42 | public int getLoginTimeout() throws SQLException { 43 | return getRawDataSource().getLoginTimeout(); 44 | } 45 | 46 | @Override 47 | public Logger getParentLogger() throws SQLFeatureNotSupportedException { 48 | throw new SQLFeatureNotSupportedException(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/GlobalCommitResultMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.ResponseMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version GlobalCommitResultMessage.java, v 0.0.1 2017年9月4日 下午2:34:10 liushiming 24 | */ 25 | public class GlobalCommitResultMessage implements CommandCustomHeader, ResponseMessage { 26 | 27 | @CFNotNull 28 | private long tranId; 29 | 30 | public long getTranId() { 31 | return tranId; 32 | } 33 | 34 | public void setTranId(long tranId) { 35 | this.tranId = tranId; 36 | } 37 | 38 | @Override 39 | public void checkFields() throws RemotingCommandException { 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/GlobalRollbackResultMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.ResponseMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version GlobalRollbackResultMessage.java, v 0.0.1 2017年9月4日 下午2:35:25 liushiming 24 | */ 25 | public class GlobalRollbackResultMessage implements CommandCustomHeader, ResponseMessage { 26 | @CFNotNull 27 | private long tranId; 28 | 29 | public long getTranId() { 30 | return tranId; 31 | } 32 | 33 | public void setTranId(long tranId) { 34 | this.tranId = tranId; 35 | } 36 | 37 | @Override 38 | public void checkFields() throws RemotingCommandException { 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/exception/RemotingTimeoutException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.exception; 17 | 18 | /** 19 | * RPC调用超时异常 20 | * 21 | * @author shijia.wxr 22 | * @since 2013-7-13 23 | */ 24 | public class RemotingTimeoutException extends RemotingException { 25 | 26 | private static final long serialVersionUID = 4106899185095245979L; 27 | 28 | 29 | public RemotingTimeoutException(String message) { 30 | super(message); 31 | } 32 | 33 | 34 | public RemotingTimeoutException(String addr, long timeoutMillis) { 35 | this(addr, timeoutMillis, null); 36 | } 37 | 38 | 39 | public RemotingTimeoutException(String addr, long timeoutMillis, Throwable cause) { 40 | super("wait response on the channel <" + addr + "> timeout, " + timeoutMillis + "(ms)", cause); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /script/server.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `dts_branch_error_log` ( 2 | `branch_id` bigint(20) NOT NULL, 3 | `tx_id` bigint(20) NOT NULL, 4 | `client_ip` varchar(15) COLLATE utf8_bin NOT NULL, 5 | `client_info` varchar(255) COLLATE utf8_bin NOT NULL, 6 | `state` tinyint(1) NOT NULL DEFAULT '0', 7 | `gmt_created` datetime NOT NULL, 8 | `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 9 | `is_notify` tinyint(1) DEFAULT '0', 10 | PRIMARY KEY (`branch_id`), 11 | UNIQUE KEY `branch_id` (`branch_id`), 12 | KEY `tx_id` (`tx_id`) 13 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 14 | 15 | CREATE TABLE `dts_branch_log` ( 16 | `branch_id` bigint(20) NOT NULL AUTO_INCREMENT, 17 | `tx_id` bigint(20) NOT NULL, 18 | `client_ip` varchar(200) COLLATE utf8_bin NOT NULL, 19 | `client_info` varchar(200) COLLATE utf8_bin NOT NULL, 20 | `state` tinyint(1) NOT NULL, 21 | `gmt_created` datetime NOT NULL, 22 | `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 23 | PRIMARY KEY (`branch_id`), 24 | KEY `tx_id` (`tx_id`) 25 | ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 26 | 27 | CREATE TABLE `dts_global_log` ( 28 | `tx_id` bigint(20) NOT NULL AUTO_INCREMENT, 29 | `state` tinyint(1) NOT NULL, 30 | `gmt_created` datetime NOT NULL, 31 | `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 32 | PRIMARY KEY (`tx_id`) 33 | ) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 34 | -------------------------------------------------------------------------------- /dts-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-client 12 | dts-client 13 | http://maven.apache.org 14 | 15 | UTF-8 16 | 17 | 18 | 19 | io.dts 20 | dts-common 21 | 22 | 23 | org.springframework 24 | spring-core 25 | ${spring.version} 26 | 27 | 28 | org.springframework 29 | spring-context 30 | ${spring.version} 31 | 32 | 33 | org.springframework 34 | spring-tx 35 | ${spring.version} 36 | 37 | 38 | com.quancheng.saluki 39 | saluki-core 40 | 1.5.7.RELEASE 41 | provided 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/BeginMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.RequestMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * 开始事务消息 23 | * 24 | * @author liushiming 25 | * @version BeginMessage.java, v 0.0.1 2017年9月1日 下午5:45:54 liushiming 26 | */ 27 | public class BeginMessage implements CommandCustomHeader, RequestMessage { 28 | 29 | @CFNotNull 30 | public long timeout = 60000; 31 | 32 | public long getTimeout() { 33 | return timeout; 34 | } 35 | 36 | public void setTimeout(long timeout) { 37 | this.timeout = timeout; 38 | } 39 | 40 | @Override 41 | public void checkFields() throws RemotingCommandException { 42 | 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/GlobalCommitMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.RequestMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version GlobalCommitMessage.java, v 0.0.1 2017年9月1日 下午6:25:26 liushiming 24 | */ 25 | public class GlobalCommitMessage implements CommandCustomHeader, RequestMessage { 26 | /** 27 | * 事务ID 28 | */ 29 | @CFNotNull 30 | private long tranId; 31 | 32 | public long getTranId() { 33 | return tranId; 34 | } 35 | 36 | public void setTranId(long tranId) { 37 | this.tranId = tranId; 38 | } 39 | 40 | 41 | 42 | @Override 43 | public void checkFields() throws RemotingCommandException { 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dts-parser/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.dts 8 | dts 9 | 0.0.1-SNAPSHOT 10 | 11 | dts-parser 12 | dts-parser 13 | http://maven.apache.org 14 | 15 | UTF-8 16 | 17 | 18 | 19 | com.google.guava 20 | guava 21 | 22 | 23 | io.dts 24 | dts-common 25 | 26 | 27 | com.alibaba 28 | druid 29 | 1.0.15 30 | 31 | 32 | cglib 33 | cglib 34 | 3.1 35 | 36 | 37 | junit 38 | junit 39 | 4.11 40 | test 41 | 42 | 43 | mysql 44 | mysql-connector-java 45 | 5.1.40 46 | test 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/common/SemaphoreReleaseOnlyOnce.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.common; 17 | 18 | import java.util.concurrent.Semaphore; 19 | import java.util.concurrent.atomic.AtomicBoolean; 20 | 21 | 22 | /** 23 | * 使用布尔原子变量,信号量保证只释放一次 24 | * 25 | * @author shijia.wxr 26 | * @since 2013-7-13 27 | */ 28 | public class SemaphoreReleaseOnlyOnce { 29 | private final AtomicBoolean released = new AtomicBoolean(false); 30 | private final Semaphore semaphore; 31 | 32 | 33 | public SemaphoreReleaseOnlyOnce(Semaphore semaphore) { 34 | this.semaphore = semaphore; 35 | } 36 | 37 | 38 | public void release() { 39 | if (this.semaphore != null) { 40 | if (this.released.compareAndSet(false, true)) { 41 | this.semaphore.release(); 42 | } 43 | } 44 | } 45 | 46 | 47 | public Semaphore getSemaphore() { 48 | return semaphore; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/util/BlobUtil.java: -------------------------------------------------------------------------------- 1 | package io.dts.common.util; 2 | 3 | 4 | import javax.sql.rowset.serial.SerialBlob; 5 | 6 | import io.dts.common.exception.DtsException; 7 | 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.sql.Blob; 12 | 13 | public class BlobUtil { 14 | public static Blob string2blob(String str) { 15 | if (str == null) { 16 | return null; 17 | } 18 | 19 | try { 20 | return new SerialBlob(str.getBytes()); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | throw (DtsException) e; 24 | } 25 | } 26 | 27 | public static String blob2string(Blob blob) { 28 | if (blob == null) { 29 | return null; 30 | } 31 | 32 | try { 33 | return new String(blob.getBytes((long) 1, (int) blob.length())); 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | throw (DtsException) e; 37 | } 38 | } 39 | 40 | public static String inputStream2String(InputStream is) { 41 | try { 42 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 43 | int i = -1; 44 | while ((i = is.read()) != -1) { 45 | baos.write(i); 46 | } 47 | return baos.toString(); 48 | } catch (Exception e) { 49 | e.printStackTrace(); 50 | throw (DtsException) e; 51 | } 52 | } 53 | 54 | // 测试方法 55 | public static void main(String[] args) throws IOException { 56 | // 测试字符串 57 | String str = "%5B%7B%22lastUpdateTime%22%3A%222011-10-28+9%3A39%3A41%22%2C%22smsList%22%3A%5B%7B%22liveState%22%3A%221"; 58 | 59 | System.out.println("原长度:" + str.length()); 60 | System.out.println("原长度:" + BlobUtil.string2blob(str)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/netty/NettySystemConfig.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting.netty; 2 | 3 | public class NettySystemConfig { 4 | public static final String SystemPropertyNettyPooledByteBufAllocatorEnable = 5 | "com.rocketmq.remoting.nettyPooledByteBufAllocatorEnable"; 6 | public static boolean NettyPooledByteBufAllocatorEnable = // 7 | Boolean 8 | .parseBoolean(System.getProperty(SystemPropertyNettyPooledByteBufAllocatorEnable, "false")); 9 | 10 | public static final String SystemPropertySocketSndbufSize = // 11 | "com.rocketmq.remoting.socket.sndbuf.size"; 12 | public static int SocketSndbufSize = // 13 | Integer.parseInt(System.getProperty(SystemPropertySocketSndbufSize, "65535")); 14 | 15 | public static final String SystemPropertySocketRcvbufSize = // 16 | "com.rocketmq.remoting.socket.rcvbuf.size"; 17 | public static int SocketRcvbufSize = // 18 | Integer.parseInt(System.getProperty(SystemPropertySocketRcvbufSize, "65535")); 19 | 20 | public static final String SystemPropertyClientAsyncSemaphoreValue = // 21 | "com.rocketmq.remoting.clientAsyncSemaphoreValue"; 22 | public static int ClientAsyncSemaphoreValue = // 23 | Integer.parseInt(System.getProperty(SystemPropertyClientAsyncSemaphoreValue, "2048")); 24 | 25 | public static final String SystemPropertyClientOnewaySemaphoreValue = // 26 | "com.rocketmq.remoting.clientOnewaySemaphoreValue"; 27 | public static int ClientOnewaySemaphoreValue = // 28 | Integer.parseInt(System.getProperty(SystemPropertyClientOnewaySemaphoreValue, "2048")); 29 | } 30 | -------------------------------------------------------------------------------- /dts-microservice-support/dts-springcloud-support/src/main/java/io/dts/springcloud/ContextHystrixAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.springcloud; 15 | 16 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 17 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | 21 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 22 | 23 | import io.dts.client.aop.DtsTransactionScaner; 24 | 25 | /** 26 | * @author liushiming 27 | * @version ContextHystrixAutoConfiguration.java, v 0.0.1 2017年11月22日 下午6:27:06 liushiming 28 | */ 29 | @Configuration 30 | @ConditionalOnClass(HystrixCommand.class) 31 | @ConditionalOnBean(DtsTransactionScaner.class) 32 | public class ContextHystrixAutoConfiguration { 33 | 34 | @Bean 35 | ContextHystrixConcurrencyStrategy contextHystrixConcurrencyStrategy() { 36 | return new ContextHystrixConcurrencyStrategy(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dts-example/dts-example-provider/src/main/java/com/quancheng/saluki/example/repository/entity/StudentDo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package com.quancheng.saluki.example.repository.entity; 15 | 16 | import javax.persistence.Column; 17 | import javax.persistence.Entity; 18 | import javax.persistence.GeneratedValue; 19 | import javax.persistence.GenerationType; 20 | import javax.persistence.Id; 21 | import javax.persistence.Table; 22 | 23 | /** 24 | * @author liushiming 25 | * @version Student.java, v 0.0.1 2017年11月2日 下午2:10:55 liushiming 26 | */ 27 | @Table(name = "t_student") 28 | @Entity 29 | public class StudentDo { 30 | 31 | @Id 32 | @GeneratedValue(strategy = GenerationType.AUTO) 33 | @Column(name = "student_id") 34 | private Long id; 35 | private String name; 36 | 37 | public Long getId() { 38 | return id; 39 | } 40 | 41 | public void setId(Long id) { 42 | this.id = id; 43 | } 44 | 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public void setName(String name) { 50 | this.name = name; 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/struct/DatabaseType.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.struct; 2 | 3 | import com.alibaba.druid.util.JdbcUtils; 4 | import com.google.common.base.Optional; 5 | import com.google.common.base.Predicate; 6 | import com.google.common.collect.Iterators; 7 | 8 | import java.util.Arrays; 9 | 10 | /** 11 | * Created by guoyubo on 2017/9/20. 12 | */ 13 | public enum DatabaseType { 14 | 15 | H2("H2", JdbcUtils.H2), 16 | 17 | MySQL("MySQL", JdbcUtils.MYSQL), 18 | 19 | Oracle("Oracle", JdbcUtils.ORACLE), 20 | 21 | SQLServer("Microsoft SQL Server", JdbcUtils.SQL_SERVER), 22 | 23 | PostgreSQL("PostgreSQL", JdbcUtils.POSTGRESQL), 24 | 25 | DB2("DB2", JdbcUtils.DB2); 26 | 27 | private final String productName; 28 | private final String druidSqlType; 29 | 30 | DatabaseType(final String productName, final String druidSqlType) { 31 | this.productName = productName; 32 | this.druidSqlType = druidSqlType; 33 | } 34 | 35 | public String getDruidSqlType() { 36 | return druidSqlType; 37 | } 38 | 39 | 40 | public static DatabaseType valueFrom(final String databaseProductName) { 41 | Optional databaseTypeOptional = Iterators.tryFind(Arrays.asList(DatabaseType.values()).iterator(), new Predicate() { 42 | 43 | @Override 44 | public boolean apply(final DatabaseType input) { 45 | return input.productName.equals(databaseProductName); 46 | } 47 | }); 48 | if (databaseTypeOptional.isPresent()) { 49 | return databaseTypeOptional.get(); 50 | } 51 | throw new UnsupportedOperationException(String.format("Can not support database type [%s].", databaseProductName)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dts-microservice-support/dts-springcloud-support/src/main/java/io/dts/springcloud/SpringCloudContextConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.springcloud; 15 | 16 | import org.springframework.context.annotation.Bean; 17 | import org.springframework.context.annotation.Configuration; 18 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 19 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 20 | 21 | import feign.RequestInterceptor; 22 | 23 | 24 | /** 25 | * @author liushiming 26 | * @version SpringCloudContextConfig.java, v 0.0.1 2017年11月20日 下午2:34:06 liushiming 27 | */ 28 | @Configuration 29 | public class SpringCloudContextConfig extends WebMvcConfigurerAdapter { 30 | 31 | 32 | @Override 33 | public void addInterceptors(InterceptorRegistry registry) { 34 | registry.addInterceptor(new SpringCloudContextInterceptor())// 35 | .addPathPatterns("/*"); 36 | super.addInterceptors(registry); 37 | } 38 | 39 | @Bean 40 | public RequestInterceptor requestInterceptor() { 41 | return new SpringCloudContextInterceptor(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/netty/NettyEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.netty; 17 | 18 | import io.netty.channel.Channel; 19 | 20 | 21 | /** 22 | * Netty产生的各种事件 23 | * 24 | * @author shijia.wxr 25 | * @since 2013-7-13 26 | */ 27 | public class NettyEvent { 28 | private final NettyEventType type; 29 | private final String remoteAddr; 30 | private final Channel channel; 31 | 32 | 33 | public NettyEvent(NettyEventType type, String remoteAddr, Channel channel) { 34 | this.type = type; 35 | this.remoteAddr = remoteAddr; 36 | this.channel = channel; 37 | } 38 | 39 | 40 | public NettyEventType getType() { 41 | return type; 42 | } 43 | 44 | 45 | public String getRemoteAddr() { 46 | return remoteAddr; 47 | } 48 | 49 | 50 | public Channel getChannel() { 51 | return channel; 52 | } 53 | 54 | 55 | @Override 56 | public String toString() { 57 | return "NettyEvent [type=" + type + ", remoteAddr=" + remoteAddr + ", channel=" + channel + "]"; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/RegisterMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.RequestMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version RegisterMessage.java, v 0.0.1 2017年9月1日 下午6:29:38 liushiming 24 | */ 25 | public class RegisterMessage implements CommandCustomHeader, RequestMessage { 26 | /** 27 | * 事务ID 28 | */ 29 | @CFNotNull 30 | private long tranId; 31 | /** 32 | * 资源名称 33 | */ 34 | private String clientInfo; 35 | 36 | 37 | public long getTranId() { 38 | return tranId; 39 | } 40 | 41 | public void setTranId(long tranId) { 42 | this.tranId = tranId; 43 | } 44 | 45 | public String getClientInfo() { 46 | return clientInfo; 47 | } 48 | 49 | public void setClientInfo(String dbName) { 50 | this.clientInfo = dbName; 51 | } 52 | 53 | @Override 54 | public void checkFields() throws RemotingCommandException { 55 | 56 | } 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /dts-remoting/src/test/java/io/dts/remoting/NettyConnectionTest.java: -------------------------------------------------------------------------------- 1 | package io.dts.remoting; 2 | 3 | import io.dts.remoting.RemotingClient; 4 | import io.dts.remoting.exception.RemotingConnectException; 5 | import io.dts.remoting.exception.RemotingSendRequestException; 6 | import io.dts.remoting.exception.RemotingTimeoutException; 7 | import io.dts.remoting.netty.NettyClientConfig; 8 | import io.dts.remoting.netty.NettyRemotingClient; 9 | import io.dts.remoting.protocol.RemotingCommand; 10 | 11 | import org.junit.Test; 12 | 13 | 14 | /** 15 | * 连接超时测试 16 | * 17 | * @author shijia.wxr 18 | * @since 2013-7-6 19 | */ 20 | public class NettyConnectionTest { 21 | public static RemotingClient createRemotingClient() { 22 | NettyClientConfig config = new NettyClientConfig(); 23 | config.setClientChannelMaxIdleTimeSeconds(15); 24 | RemotingClient client = new NettyRemotingClient(config); 25 | client.start(); 26 | return client; 27 | } 28 | 29 | 30 | @Test 31 | public void test_connect_timeout() throws InterruptedException, RemotingConnectException, 32 | RemotingSendRequestException, RemotingTimeoutException { 33 | RemotingClient client = createRemotingClient(); 34 | 35 | for (int i = 0; i < 100; i++) { 36 | try { 37 | RemotingCommand request = RemotingCommand.createRequestCommand(0, null); 38 | RemotingCommand response = client.invokeSync("localhost:8888", request, 1000 * 3); 39 | } 40 | catch (Exception e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | client.shutdown(); 46 | System.out.println("-----------------------------------------------------------------"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dts-datasource/src/main/resources/txc_client.sql: -------------------------------------------------------------------------------- 1 | /*---- create table rt_sql---------*/ 2 | /*---- 单表总记录数:99999,单表日增记录数:999999 ----*/ 3 | 4 | create table rt_sql ( 5 | id bigint unsigned not null comment '主键' auto_increment, 6 | gmt_create datetime comment '创建时间', 7 | gmt_modified datetime comment '修改时间', 8 | xid varchar(20) not null comment '事务ID', 9 | branch_id bigint unsigned not null comment '分支ID', 10 | tsql blob not null comment '重试Sql', 11 | primary key (id), 12 | key xid (xid,branch_id) 13 | ) engine=InnoDB default charset=utf8 comment='rt模式SQL存储表'; 14 | 15 | /*---- create table txc_activity_info---------*/ 16 | /*---- 单表总记录数:9999999,单表日增记录数:999999 ----*/ 17 | 18 | create table txc_activity_info ( 19 | id bigint unsigned not null comment '主键' auto_increment, 20 | gmt_create datetime not null comment '创建时间', 21 | gmt_modified datetime not null comment '修改时间', 22 | xid varchar(100) not null comment '全局事务ID', 23 | branch_id int unsigned not null comment '分支事务ID', 24 | table_name varchar(100) not null comment '互斥锁表名', 25 | key_value bigint unsigned not null comment '互斥锁主键值', 26 | primary key (id) 27 | ) engine=InnoDB default charset=utf8 comment='事务锁表'; 28 | 29 | /*---- create table txc_undo_log---------*/ 30 | /*---- 单表总记录数:999999,单表日增记录数:99999 ----*/ 31 | 32 | create table txc_undo_log ( 33 | id bigint unsigned not null comment '主键' auto_increment, 34 | gmt_create datetime not null comment '创建时间', 35 | gmt_modified datetime not null comment '修改时间', 36 | xid varchar(100) not null comment '全局事务ID', 37 | branch_id int unsigned not null comment '分支事务ID', 38 | rollback_info blob not null comment 'LOG', 39 | status bigint unsigned not null comment '状态', 40 | server varchar(32) not null comment '分支所在DB IP', 41 | primary key (id), 42 | key unionkey (xid,branch_id) 43 | ) engine=InnoDB default charset=utf8 comment='事务日志表'; -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/src/main/java/com/quancheng/saluki/example/client/RpcService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package com.quancheng.saluki.example.client; 15 | 16 | import org.springframework.stereotype.Service; 17 | 18 | import com.quancheng.examples.model.hello.HelloReply; 19 | import com.quancheng.examples.model.hello.HelloRequest; 20 | import com.quancheng.examples.service.HelloService; 21 | import com.quancheng.saluki.boot.SalukiReference; 22 | import com.quancheng.saluki.core.common.RpcContext; 23 | 24 | import io.dts.client.aop.annotation.DtsTransaction; 25 | 26 | /** 27 | * @author liushiming 28 | * @version RpcService.java, v 0.0.1 2017年11月7日 下午1:38:13 liushiming 29 | */ 30 | @Service 31 | public class RpcService { 32 | 33 | @SalukiReference 34 | private HelloService helloService; 35 | 36 | 37 | 38 | @DtsTransaction 39 | public HelloReply callService() { 40 | RpcContext.getContext().set("123", "123"); 41 | HelloRequest request = new HelloRequest(); 42 | request.setName("liushiming"); 43 | HelloReply reply = helloService.dtsNormal(request); 44 | helloService.dtsException(request); 45 | System.out.println(RpcContext.getContext().get("123")); 46 | return reply; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/BeginResultMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.ResponseMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * 开始事务的返回消息 23 | * 24 | * @author liushiming 25 | * @version BeginResultMessage.java, v 0.0.1 2017年9月1日 下午6:32:09 liushiming 26 | */ 27 | public class BeginResultMessage implements CommandCustomHeader, ResponseMessage { 28 | /** 29 | * 全局唯一的事务ID 30 | */ 31 | @CFNotNull 32 | private String xid; 33 | /** 34 | * Server双写配置下,next node的地址 35 | */ 36 | @CFNotNull 37 | private String nextSvrAddr; 38 | 39 | public String getXid() { 40 | return xid; 41 | } 42 | 43 | public void setXid(String xid) { 44 | this.xid = xid; 45 | } 46 | 47 | public String getNextSvrAddr() { 48 | return nextSvrAddr; 49 | } 50 | 51 | public void setNextSvrAddr(String nextSvrAddr) { 52 | this.nextSvrAddr = nextSvrAddr; 53 | } 54 | 55 | @Override 56 | public void checkFields() throws RemotingCommandException { 57 | 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/GlobalRollbackMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.RequestMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version GlobalRollbackMessage.java, v 0.0.1 2017年9月1日 下午6:27:32 liushiming 24 | */ 25 | public class GlobalRollbackMessage implements CommandCustomHeader, RequestMessage { 26 | /** 27 | * 事务ID 28 | */ 29 | @CFNotNull 30 | private long tranId; 31 | 32 | /** 33 | * 当server采用cluster mode,有可能消息接收svr并不是发起事务的svr,这个属性指示发起事务的svr地址 34 | */ 35 | private String realSvrAddr; 36 | 37 | public long getTranId() { 38 | return tranId; 39 | } 40 | 41 | public void setTranId(long tranId) { 42 | this.tranId = tranId; 43 | } 44 | 45 | public String getRealSvrAddr() { 46 | return realSvrAddr; 47 | } 48 | 49 | public void setRealSvrAddr(String realSvrAddr) { 50 | this.realSvrAddr = realSvrAddr; 51 | } 52 | 53 | 54 | @Override 55 | public void checkFields() throws RemotingCommandException { 56 | 57 | } 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /dts-datasource/src/main/java/io/dts/datasource/wrapper/executor/AbstractExecutor.java: -------------------------------------------------------------------------------- 1 | package io.dts.datasource.wrapper.executor; 2 | 3 | import java.sql.SQLException; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import io.dts.common.exception.DtsException; 8 | 9 | /** 10 | * Created by guoyubo on 2017/9/21. 11 | */ 12 | public abstract class AbstractExecutor { 13 | 14 | public T executeStatement(final StatementModel statementUnit, 15 | final ExecuteCallback executeCallback) throws Exception { 16 | return execute(statementUnit, Collections.emptyList(), executeCallback); 17 | } 18 | 19 | public T executePreparedStatement(final StatementModel preparedStatementUnits, 20 | final List parameters, final ExecuteCallback executeCallback) 21 | 22 | throws Exception { 23 | return execute(preparedStatementUnits, parameters, executeCallback); 24 | } 25 | 26 | private T execute(StatementModel baseStatementUnit, final List parameterSet, 27 | final ExecuteCallback executeCallback) throws Exception { 28 | T result = executeInternal(baseStatementUnit, parameterSet, executeCallback); 29 | return result; 30 | } 31 | 32 | private T executeInternal(final StatementModel baseStatementUnit, 33 | final List parameterSet, final ExecuteCallback executeCallback) throws Exception { 34 | try { 35 | ExecutorHelper commiter = new ExecutorHelper(baseStatementUnit, parameterSet); 36 | commiter.beforeExecute(); 37 | T result = executeCallback.execute(baseStatementUnit); 38 | commiter.afterExecute(); 39 | return result; 40 | } catch (final SQLException ex) { 41 | throw new DtsException(ex); 42 | } 43 | 44 | } 45 | 46 | 47 | static interface ExecuteCallback { 48 | 49 | T execute(StatementModel baseStatementUnit) throws Exception; 50 | } 51 | 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /dts-parser/src/test/java/io/dts/parser/visitor/TxcUpdateVisitorTest.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.visitor; 2 | 3 | 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import com.alibaba.druid.pool.DruidDataSource; 8 | import com.alibaba.fastjson.JSON; 9 | import com.google.common.collect.Lists; 10 | 11 | import javax.sql.DataSource; 12 | 13 | import java.sql.Connection; 14 | import java.sql.SQLException; 15 | import java.sql.Statement; 16 | 17 | import io.dts.parser.DtsVisitorFactory; 18 | import io.dts.parser.struct.DatabaseType; 19 | import io.dts.parser.vistor.ITxcVisitor; 20 | 21 | /** 22 | * Created by guoyubo on 2017/10/20. 23 | */ 24 | public class TxcUpdateVisitorTest { 25 | 26 | private Connection connection; 27 | 28 | @Before 29 | public void init() throws SQLException { 30 | connection = dataSource().getConnection(); 31 | } 32 | 33 | private static DataSource dataSource() { 34 | DruidDataSource dataSource = new DruidDataSource(); 35 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 36 | dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/dts"); 37 | dataSource.setUsername("root"); 38 | dataSource.setPassword("123"); 39 | dataSource.setMaxActive(15); 40 | return dataSource; 41 | } 42 | 43 | 44 | @Test 45 | public void parse() throws SQLException { 46 | Statement statement = connection.createStatement(); 47 | String sql = "update txc_global_log l set l.state = 5 where l.tx_id=2"; 48 | ITxcVisitor visitor = DtsVisitorFactory.createSqlVisitor(DatabaseType.MySQL, connection, sql, 49 | Lists.newArrayList()); 50 | visitor.buildTableMeta(); 51 | visitor.executeAndGetFrontImage(statement); 52 | System.out.println(visitor.getSelectSql()); 53 | System.out.println(JSON.toJSON(visitor.getTableOriginalValue())); 54 | statement.execute(sql); 55 | visitor.executeAndGetRearImage(statement); 56 | System.out.println(JSON.toJSON(visitor.getTablePresentValue())); 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/vistor/mysql/DtsSelectVisitor.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.vistor.mysql; 2 | 3 | import java.sql.SQLException; 4 | import java.sql.Statement; 5 | import java.util.List; 6 | 7 | import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; 8 | import com.alibaba.druid.sql.ast.statement.SQLSelectItem; 9 | import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; 10 | import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; 11 | import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; 12 | 13 | import io.dts.parser.DtsSQLStatement; 14 | import io.dts.parser.struct.TxcTable; 15 | 16 | public class DtsSelectVisitor extends AbstractDtsVisitor { 17 | 18 | public DtsSelectVisitor(DtsSQLStatement node, List parameterSet) { 19 | super(node, parameterSet); 20 | } 21 | 22 | @Override 23 | public String parseWhereCondition(Statement st) { 24 | SQLSelectStatement selectStatement = (SQLSelectStatement) this.node.getSQLStatement(); 25 | StringBuffer out = parseWhereCondition( 26 | ((SQLSelectQueryBlock) selectStatement.getSelect().getQuery()).getWhere()); 27 | return out.toString(); 28 | } 29 | 30 | 31 | @Override 32 | public TxcTable executeAndGetFrontImage(final Statement st) throws SQLException { 33 | return getTableOriginalValue(); 34 | } 35 | 36 | @Override 37 | public TxcTable executeAndGetRearImage(final Statement st) throws SQLException { 38 | return getTablePresentValue(); 39 | } 40 | 41 | @Override 42 | public boolean visit(final MySqlSelectQueryBlock x) { 43 | if (x.getFrom() instanceof SQLExprTableSource) { 44 | SQLExprTableSource tableExpr = (SQLExprTableSource) x.getFrom(); 45 | setTableName(tableExpr.getExpr().toString()); 46 | setTableNameAlias(tableExpr.getAlias() != null ? tableExpr.getAlias() : null); 47 | } 48 | return super.visit(x); 49 | } 50 | 51 | public boolean visit(final SQLSelectItem x) { 52 | return super.visit(x); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | dts-example 6 | io.dts 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | 11 | dts-example-consumer 12 | 13 | osx-x86_64 14 | 15 | 16 | 17 | io.dts 18 | dts-saluki-support 19 | ${dts.version} 20 | 21 | 22 | com.quancheng.saluki 23 | spring-boot-starter-saluki 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-log4j 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | spring-boot-starter-tomcat 35 | org.springframework.boot 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-jetty 42 | 43 | 44 | io.dts 45 | dts-example-api 46 | ${project.version} 47 | 48 | 49 | io.netty 50 | netty-tcnative-boringssl-static 51 | ${netty-tcnative.version} 52 | ${os.detected.classifier} 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/RegisterResultMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.ResponseMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version RegisterResultMessage.java, v 0.0.1 2017年9月4日 下午2:43:44 liushiming 24 | */ 25 | public class RegisterResultMessage implements CommandCustomHeader, ResponseMessage { 26 | /** 27 | * 事务ID 28 | */ 29 | @CFNotNull 30 | private long tranId; 31 | /** 32 | * 分支ID 33 | */ 34 | @CFNotNull 35 | private long branchId; 36 | 37 | /** 38 | * 结果 39 | */ 40 | @CFNotNull 41 | private int result; 42 | 43 | public long getTranId() { 44 | return tranId; 45 | } 46 | 47 | public void setTranId(long tranId) { 48 | this.tranId = tranId; 49 | } 50 | 51 | public long getBranchId() { 52 | return branchId; 53 | } 54 | 55 | public void setBranchId(long branchId) { 56 | this.branchId = branchId; 57 | } 58 | 59 | 60 | public int getResult() { 61 | return result; 62 | } 63 | 64 | public void setResult(int result) { 65 | this.result = result; 66 | } 67 | 68 | @Override 69 | public void checkFields() throws RemotingCommandException { 70 | 71 | } 72 | 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /dts-microservice-support/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | io.dts 7 | dts 8 | 0.0.1-SNAPSHOT 9 | 10 | dts-microservice-support 11 | 12 | dts-saluki-support 13 | dts-springcloud-support 14 | 15 | pom 16 | 17 | 18 | 19 | com.quancheng.saluki 20 | saluki-core 21 | 1.5.7.RELEASE 22 | provided 23 | 24 | 25 | org.springframework.cloud 26 | spring-cloud-netflix-dependencies 27 | 1.3.5.RELEASE 28 | pom 29 | import 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-compiler-plugin 38 | 2.3.2 39 | 40 | 1.8 41 | 1.8 42 | utf-8 43 | true 44 | true 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-source-plugin 50 | 2.1.2 51 | 52 | 53 | attach-sources 54 | 55 | jar 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/BranchRollbackResultMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.ResponseMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version BranchRollbackResultMessage.java, v 0.0.1 2017年9月4日 下午2:23:56 liushiming 24 | */ 25 | public class BranchRollbackResultMessage implements CommandCustomHeader, ResponseMessage { 26 | /** 27 | * 事务ID 28 | */ 29 | @CFNotNull 30 | private long tranId; 31 | /** 32 | * 分支ID 33 | */ 34 | @CFNotNull 35 | private long branchId; 36 | 37 | /** 38 | * 回滚结果 39 | */ 40 | @CFNotNull 41 | private int result; 42 | 43 | public long getTranId() { 44 | return tranId; 45 | } 46 | 47 | public void setTranId(long tranId) { 48 | this.tranId = tranId; 49 | } 50 | 51 | public long getBranchId() { 52 | return branchId; 53 | } 54 | 55 | public void setBranchId(long branchId) { 56 | this.branchId = branchId; 57 | } 58 | 59 | public int getResult() { 60 | return result; 61 | } 62 | 63 | public void setResult(int result) { 64 | this.result = result; 65 | } 66 | 67 | @Override 68 | public void checkFields() throws RemotingCommandException { 69 | 70 | } 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /dts-datasource/src/main/java/io/dts/datasource/DtsDataSource.java: -------------------------------------------------------------------------------- 1 | package io.dts.datasource; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | import javax.sql.DataSource; 7 | 8 | import io.dts.parser.struct.DatabaseType; 9 | import io.dts.resourcemanager.DataSourceHolder; 10 | import io.dts.resourcemanager.DataSourceResourceManager; 11 | import io.dts.resourcemanager.ResourceManager; 12 | 13 | /** 14 | * Created by guoyubo on 2017/9/20. 15 | */ 16 | public class DtsDataSource extends AbstractDtsDataSource { 17 | 18 | private DataSource dataSource; 19 | 20 | private String dbName; 21 | 22 | private ResourceManager resourceManager; 23 | 24 | 25 | public DtsDataSource(final DataSource dataSource, String dbName) { 26 | this.dataSource = dataSource; 27 | this.dbName = dbName; 28 | DataSourceHolder.registerDataSource(dbName, dataSource); 29 | } 30 | 31 | public void setResourceManager(final ResourceManager resourceManager) { 32 | this.resourceManager = resourceManager; 33 | } 34 | 35 | public DatabaseType getDatabaseType() throws SQLException { 36 | try (Connection connection = dataSource.getConnection()) { 37 | return DatabaseType.valueFrom(connection.getMetaData().getDatabaseProductName()); 38 | } 39 | } 40 | 41 | @Override 42 | public Connection getConnection() throws SQLException { 43 | return new DtsConnection(this, dataSource.getConnection()); 44 | } 45 | 46 | @Override 47 | public Connection getConnection(final String username, final String password) 48 | throws SQLException { 49 | return new DtsConnection(this, dataSource.getConnection(username, password)); 50 | } 51 | 52 | public DataSource getRawDataSource() { 53 | return dataSource; 54 | } 55 | 56 | @Override 57 | public String getDbName() { 58 | return dbName; 59 | } 60 | 61 | public ResourceManager getResourceManager() { 62 | if (resourceManager == null) { 63 | resourceManager = DataSourceResourceManager.newResourceManager(); 64 | } 65 | return resourceManager; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/undo/DtsUpdateUndo.java: -------------------------------------------------------------------------------- 1 | package io.dts.resourcemanager.undo; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.util.List; 6 | 7 | import io.dts.common.exception.DtsException; 8 | import io.dts.common.protocol.ResultCode; 9 | import io.dts.parser.struct.RollbackInfor; 10 | import io.dts.parser.struct.TxcField; 11 | 12 | /** 13 | * 14 | * @author xiaoyan 15 | */ 16 | public class DtsUpdateUndo extends AbstractDtsUndo { 17 | 18 | public DtsUpdateUndo(RollbackInfor txcUndoLogRollbackInfor) { 19 | super(txcUndoLogRollbackInfor); 20 | } 21 | 22 | /** 23 | * 根据数据行原值还原数据库
24 | * SQL如果修改了表关键字,会造成回滚失败
25 | */ 26 | @Override 27 | public List buildRollbackSql() { 28 | // 检查脏写 29 | String rule = getTxcUndoLogRollbackInfor().getRollbackRule(); 30 | if (rule == null) { 31 | // 检查数据行是否一致,update不应该影响行数目 32 | if (getOriginalValue().getLinesNum() != getPresentValue().getLinesNum()) { 33 | throw new DtsException(ResultCode.ERROR.getValue(), "line num changed."); 34 | } 35 | } 36 | List sqls = Lists.newArrayList(); 37 | 38 | for (int index = 0; index < getOriginalValue().getLinesNum(); index++) { 39 | // 得到行的所有属性 40 | String tableName = getOriginalValue().getTableMeta().getTableName(); 41 | String pkName = getOriginalValue().getTableMeta().getPkName(); 42 | List fields = getOriginalValue().getLines().get(index).getFields(); 43 | 44 | StringBuilder sqlAppender = new StringBuilder(); 45 | sqlAppender.append("UPDATE "); 46 | sqlAppender.append(tableName); 47 | sqlAppender.append(" SET "); 48 | if (rule == null) 49 | sqlAppender.append(fieldsExpressionSerialization(fields, ",", pkName, false)); 50 | else 51 | sqlAppender.append(rule); 52 | sqlAppender.append(" WHERE "); 53 | sqlAppender.append(fieldsExpressionSerialization(fields, "AND", pkName, true)); 54 | sqls.add(sqlAppender.toString()); 55 | } 56 | return sqls; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/BranchCommitResultMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.ResponseMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version BranchCommitResultMessage.java, v 0.0.1 2017年9月4日 下午2:20:45 liushiming 24 | */ 25 | public class BranchCommitResultMessage implements CommandCustomHeader, ResponseMessage { 26 | /** 27 | * 事务IDs 28 | */ 29 | @CFNotNull 30 | private Long tranId; 31 | /** 32 | * 分支IDs 33 | */ 34 | @CFNotNull 35 | private Long branchId; 36 | 37 | /** 38 | * 提交结果 39 | */ 40 | @CFNotNull 41 | private int result; 42 | 43 | 44 | public Long getTranId() { 45 | return tranId; 46 | } 47 | 48 | public void setTranId(Long tranId) { 49 | this.tranId = tranId; 50 | } 51 | 52 | public Long getBranchId() { 53 | return branchId; 54 | } 55 | 56 | public void setBranchId(Long branchId) { 57 | this.branchId = branchId; 58 | } 59 | 60 | public int getResult() { 61 | return result; 62 | } 63 | 64 | public void setResult(int result) { 65 | this.result = result; 66 | } 67 | 68 | @Override 69 | public void checkFields() throws RemotingCommandException { 70 | 71 | } 72 | 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /dts-parser/src/test/java/io/dts/parser/visitor/TxcDelectVisitorTest.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.visitor; 2 | 3 | 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import com.alibaba.druid.pool.DruidDataSource; 8 | import com.google.common.collect.Lists; 9 | 10 | import javax.sql.DataSource; 11 | 12 | import java.sql.Connection; 13 | import java.sql.PreparedStatement; 14 | import java.sql.SQLException; 15 | import java.util.List; 16 | 17 | import io.dts.parser.DtsVisitorFactory; 18 | import io.dts.parser.struct.DatabaseType; 19 | import io.dts.parser.vistor.ITxcVisitor; 20 | 21 | /** 22 | * Created by guoyubo on 2017/10/20. 23 | */ 24 | public class TxcDelectVisitorTest { 25 | 26 | private Connection connection; 27 | 28 | @Before 29 | public void init() throws SQLException { 30 | connection = dataSource().getConnection(); 31 | } 32 | 33 | private static DataSource dataSource() { 34 | DruidDataSource dataSource = new DruidDataSource(); 35 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 36 | dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/dts"); 37 | dataSource.setUsername("root"); 38 | dataSource.setPassword("123456"); 39 | dataSource.setMaxActive(15); 40 | return dataSource; 41 | } 42 | 43 | 44 | @Test 45 | public void parse() throws SQLException { 46 | List parameters = Lists.newArrayList(1, 2); 47 | String sql = "DELETE FROM txc_global_log WHERE `state`=? "; 48 | PreparedStatement statement = connection.prepareStatement(sql); 49 | 50 | ITxcVisitor visitor = DtsVisitorFactory.createSqlVisitor( 51 | DatabaseType.MySQL, 52 | connection, 53 | sql, 54 | parameters); 55 | visitor.buildTableMeta(); 56 | visitor.executeAndGetFrontImage(statement); 57 | System.out.println(visitor.getSelectSql()); 58 | System.out.println(visitor.getTableOriginalValue()); 59 | statement.setInt(1, 1); 60 | statement.execute(); 61 | visitor.executeAndGetRearImage(statement); 62 | System.out.println(visitor.getTablePresentValue()); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /dts-parser/src/test/java/io/dts/parser/visitor/TxcSelectVisitorTest.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.visitor; 2 | 3 | 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import com.alibaba.druid.pool.DruidDataSource; 8 | import com.google.common.collect.Lists; 9 | 10 | import javax.sql.DataSource; 11 | 12 | import java.sql.Connection; 13 | import java.sql.PreparedStatement; 14 | import java.sql.SQLException; 15 | import java.util.List; 16 | 17 | import io.dts.parser.DtsVisitorFactory; 18 | import io.dts.parser.struct.DatabaseType; 19 | import io.dts.parser.vistor.ITxcVisitor; 20 | 21 | /** 22 | * Created by guoyubo on 2017/10/20. 23 | */ 24 | public class TxcSelectVisitorTest { 25 | 26 | private Connection connection; 27 | 28 | @Before 29 | public void init() throws SQLException { 30 | connection = dataSource().getConnection(); 31 | } 32 | 33 | private static DataSource dataSource() { 34 | DruidDataSource dataSource = new DruidDataSource(); 35 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 36 | dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/dts"); 37 | dataSource.setUsername("root"); 38 | dataSource.setPassword("123456"); 39 | dataSource.setMaxActive(15); 40 | return dataSource; 41 | } 42 | 43 | 44 | @Test 45 | public void parse() throws SQLException { 46 | List parameters = Lists.newArrayList(1, 2); 47 | String sql = "select l1.tx_id, l1.state from txc_global_log l1 where l1.state=? "; 48 | PreparedStatement statement = connection.prepareStatement(sql); 49 | 50 | ITxcVisitor visitor = DtsVisitorFactory.createSqlVisitor( 51 | DatabaseType.MySQL, 52 | connection, 53 | sql, 54 | parameters); 55 | visitor.buildTableMeta(); 56 | visitor.executeAndGetFrontImage(statement); 57 | System.out.println(visitor.getSelectSql()); 58 | System.out.println(visitor.getTableOriginalValue()); 59 | statement.setInt(1, 1); 60 | statement.execute(); 61 | visitor.executeAndGetRearImage(statement); 62 | System.out.println(visitor.getTablePresentValue()); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /dts-parser/src/test/java/io/dts/parser/visitor/TxcInsertVisitorTest.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.visitor; 2 | 3 | 4 | import java.sql.Connection; 5 | import java.sql.PreparedStatement; 6 | import java.sql.SQLException; 7 | import java.util.List; 8 | 9 | import javax.sql.DataSource; 10 | 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | 14 | import com.alibaba.druid.pool.DruidDataSource; 15 | import com.google.common.collect.Lists; 16 | 17 | import io.dts.parser.DtsVisitorFactory; 18 | import io.dts.parser.struct.DatabaseType; 19 | import io.dts.parser.vistor.ITxcVisitor; 20 | 21 | /** 22 | * Created by guoyubo on 2017/10/20. 23 | */ 24 | public class TxcInsertVisitorTest { 25 | 26 | private Connection connection; 27 | 28 | @Before 29 | public void init() throws SQLException { 30 | connection = dataSource().getConnection(); 31 | } 32 | 33 | private static DataSource dataSource() { 34 | DruidDataSource dataSource = new DruidDataSource(); 35 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 36 | dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/dts"); 37 | dataSource.setUsername("root"); 38 | dataSource.setPassword("123"); 39 | dataSource.setMaxActive(15); 40 | return dataSource; 41 | } 42 | 43 | 44 | @Test 45 | public void parse() throws SQLException { 46 | List parameters = Lists.newArrayList(1, 2); 47 | String sql = 48 | "insert into txc_global_log (state,mid,gmt_created,gmt_modified) values (?,?,now(),now())"; 49 | PreparedStatement statement = connection.prepareStatement(sql); 50 | 51 | ITxcVisitor visitor = 52 | DtsVisitorFactory.createSqlVisitor(DatabaseType.MySQL, connection, sql, parameters); 53 | visitor.buildTableMeta(); 54 | visitor.executeAndGetFrontImage(statement); 55 | System.out.println(visitor.getSelectSql()); 56 | System.out.println(visitor.getTableOriginalValue()); 57 | statement.setInt(1, 1); 58 | statement.setInt(2, 2); 59 | statement.execute(); 60 | visitor.executeAndGetRearImage(statement); 61 | System.out.println(visitor.getTablePresentValue()); 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | Dts是一款高性能、高可靠、接入简单的分布式事务中间件,用于解决分布式环境下的事务一致性问题;
4 | 在单机数据库下很容易维持事务的 ACID特性,但在分布式系统中并不容易,DTS可以保证分布式系统中的分布式事务的 ACID 特性 5 | 6 | # 功能 7 | * 跨消息和数据库的分布式事务
8 | 在某些业务场景中,需要进行多个 DB 操作的同时,还会调用消息系统,DB 操作成功、消息发送失败或者反过来都会造成业务的不完整 9 | * 跨服务的分布式事务
10 | 业务完成服务化后,资源与客户端调用解耦,同时又要保证多个服务调用间资源的变化保持强一致,否则会造成业务数据的不完整,DTS支持跨服务的事务 11 | 12 | # 详细说明 13 | 14 | * Dts Server:事务协调器。负责分布式事务的推进,管理事务生命周期 15 | * Dts Client:事务发起者。通过事务协调器,开启、提交、回滚分布式事务 16 | * Dts Resource:资源,包括数据库、MQ 17 | 18 | # 架构方案 19 | * 请查看根目录下的架构图 20 | 21 |  ![架构图](architecture.png) 22 | 23 | * 流程图 24 |  ![流程图](flow.png) 25 | 26 | # Compile 27 | ``` 28 | mvn install -Dmaven.test.skip=true 29 | ``` 30 | # 关于Sample 31 |  详细请查看 sample 32 | 33 | # Quick Start 34 | * 客户端及资源端添加pom依赖 35 | 36 | ``` 37 | 38 | io.dts 39 | dts-saluki-support 40 | ${dts.version} 41 | 42 | ``` 43 | 44 | * 在Dts客户端、Dts资源端、Dts服务端的启动参数加上-DZK_CONNECTION=127.0.0.1:2181,zookeeper的连接地址,Dts使用zookeeper来做集群管理 45 | 46 | * 客户端,在服务调用不同的接口添加@DtsTransaction注解,将两个服务调用纳入整个分布式事务管理 47 | 48 | 49 | ``` 50 | @DtsTransaction 51 | public HelloReply callService() { 52 | HelloRequest request = new HelloRequest(); 53 | request.setName("liushiming"); 54 | HelloReply reply = helloService.dtsNormal(request); 55 | helloService.dtsException(request); 56 | return reply; 57 | } 58 | 59 | ``` 60 | * 资源端,针对数据库资源,使用Dts的适配DtsDataSource来使数据库连接池转变为Dts资源 61 | 62 | 1. 执行script/resource.sql脚本 63 | 2. 将数据库连接池适配为Dts资源端 ,如下示例: 64 | 65 | ``` 66 | @Bean 67 | @Primary 68 | public DataSource dataSource() { 69 | DruidDataSource datasource = new DruidDataSource(); 70 | int startIndex = dbUrl.lastIndexOf("/"); 71 | String databaseName = dbUrl.substring(startIndex + 1, dbUrl.length()); 72 | datasource.setConnectionProperties(connectionProperties); 73 | return new DtsDataSource(datasource, databaseName); 74 | } 75 | 76 | ``` 77 | 78 | * 服务端,针对spring boot直接启动Main,将事务协调器启动起来 79 | 80 | 1. 执行script/server.sql脚本 81 | 2. 启动事务协调器服务端 82 | 83 | 84 | -------------------------------------------------------------------------------- /dts-microservice-support/dts-saluki-support/src/main/java/io/dts/saluki/SalukiContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.saluki; 15 | 16 | import java.util.Map; 17 | 18 | import com.google.common.collect.Maps; 19 | import com.quancheng.saluki.core.common.RpcContext; 20 | 21 | import io.dts.common.context.DtsContext; 22 | 23 | /** 24 | * @author liushiming 25 | * @version SalukiContext.java, v 0.0.1 2017年11月14日 下午6:17:41 liushiming 26 | */ 27 | public class SalukiContext extends DtsContext { 28 | 29 | private static final ThreadLocal> LOCAL = 30 | new InheritableThreadLocal>() { 31 | 32 | @Override 33 | protected Map initialValue() { 34 | return Maps.newHashMap(); 35 | } 36 | }; 37 | 38 | @Override 39 | public String getCurrentXid() { 40 | String txId = RpcContext.getContext().getAttachment(TXC_XID_KEY); 41 | // 当已经Rpc调用完毕之后,整个RpcContext会被清理掉,这时候应该取本地的ThreadLocal值 42 | if (txId == null) { 43 | txId = LOCAL.get().get(TXC_XID_KEY); 44 | } 45 | return txId; 46 | } 47 | 48 | @Override 49 | public synchronized void bind(String xid) { 50 | LOCAL.get().put(TXC_XID_KEY, xid); 51 | RpcContext.getContext().setAttachment(TXC_XID_KEY, xid); 52 | } 53 | 54 | @Override 55 | public void unbind() { 56 | LOCAL.remove(); 57 | } 58 | 59 | @Override 60 | public boolean inTxcTransaction() { 61 | return getCurrentXid() != null; 62 | } 63 | 64 | @Override 65 | public int priority() { 66 | return 0; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /dts-datasource/src/main/java/io/dts/datasource/wrapper/executor/PreparedStatementExecutor.java: -------------------------------------------------------------------------------- 1 | 2 | package io.dts.datasource.wrapper.executor; 3 | 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.util.List; 7 | 8 | 9 | public final class PreparedStatementExecutor extends AbstractExecutor { 10 | 11 | private final StatementModel preparedStatementUnit; 12 | 13 | private final List parameters; 14 | 15 | public PreparedStatementExecutor(StatementModel preparedStatementUnit, List parameters) { 16 | super(); 17 | this.preparedStatementUnit = preparedStatementUnit; 18 | this.parameters = parameters; 19 | } 20 | 21 | public ResultSet executeQuery() throws Exception { 22 | return super.executePreparedStatement(preparedStatementUnit, parameters, 23 | new ExecuteCallback() { 24 | 25 | @Override 26 | public ResultSet execute(final StatementModel baseStatementUnit) throws Exception { 27 | return ((PreparedStatement) baseStatementUnit.getStatement().getRawStatement()) 28 | .executeQuery(); 29 | } 30 | }); 31 | } 32 | 33 | public int executeUpdate() throws Exception { 34 | Integer results = super.executePreparedStatement(preparedStatementUnit, parameters, 35 | new ExecuteCallback() { 36 | 37 | @Override 38 | public Integer execute(final StatementModel baseStatementUnit) throws Exception { 39 | return ((PreparedStatement) baseStatementUnit.getStatement().getRawStatement()) 40 | .executeUpdate(); 41 | } 42 | }); 43 | return results; 44 | } 45 | 46 | 47 | public boolean execute() throws Exception { 48 | Boolean result = super.executePreparedStatement(preparedStatementUnit, parameters, 49 | new ExecuteCallback() { 50 | 51 | @Override 52 | public Boolean execute(final StatementModel baseStatementUnit) throws Exception { 53 | return ((PreparedStatement) baseStatementUnit.getStatement().getRawStatement()) 54 | .execute(); 55 | } 56 | }); 57 | if (null == result) { 58 | return false; 59 | } 60 | return result; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/context/DtsContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.context; 15 | 16 | import java.util.ArrayList; 17 | import java.util.Collections; 18 | import java.util.Comparator; 19 | import java.util.List; 20 | import java.util.ServiceLoader; 21 | 22 | /** 23 | * @author liushiming 24 | * @version DtsContext2Helper.java, v 0.0.1 2017年10月27日 下午3:24:34 liushiming 25 | */ 26 | public abstract class DtsContext { 27 | protected static final String TXC_XID_KEY = "XID"; 28 | private static List contexts; 29 | static { 30 | contexts = load(); 31 | } 32 | 33 | private static List load() { 34 | Iterable candidates = ServiceLoader.load(DtsContext.class); 35 | List list = new ArrayList(); 36 | for (DtsContext current : candidates) { 37 | list.add(current); 38 | } 39 | Collections.sort(list, Collections.reverseOrder(new Comparator() { 40 | @Override 41 | public int compare(DtsContext f1, DtsContext f2) { 42 | return f1.priority() - f2.priority(); 43 | } 44 | })); 45 | return Collections.unmodifiableList(list); 46 | } 47 | 48 | public static DtsContext getInstance() { 49 | if (contexts == null || contexts.isEmpty()) { 50 | contexts = load(); 51 | } 52 | return contexts.get(0); 53 | } 54 | 55 | public abstract int priority(); 56 | 57 | public abstract String getCurrentXid(); 58 | 59 | public abstract void bind(String xid); 60 | 61 | public abstract void unbind(); 62 | 63 | public abstract boolean inTxcTransaction(); 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/vistor/ITxcVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2015 dangdang.com.

Licensed under the Apache License, Version 2.0 (the 3 | * "License"); you may not use this file except in compliance with the License. You may obtain a 4 | * copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License 9 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 10 | * or implied. See the License for the specific language governing permissions and limitations under 11 | * the License.

12 | */ 13 | 14 | package io.dts.parser.vistor; 15 | 16 | import java.sql.Connection; 17 | import java.sql.SQLException; 18 | import java.sql.Statement; 19 | 20 | import io.dts.parser.DtsSQLStatement; 21 | import io.dts.parser.struct.SqlType; 22 | import io.dts.parser.struct.TxcTable; 23 | import io.dts.parser.struct.TxcTableMeta; 24 | 25 | /** 26 | * SQL解析基础访问器接口. 27 | * 28 | */ 29 | public interface ITxcVisitor { 30 | 31 | void setConnection(Connection connection); 32 | 33 | TxcTableMeta buildTableMeta() throws SQLException; 34 | 35 | /** 36 | * 获取前置镜像 37 | * 38 | * @throws SQLException 39 | */ 40 | TxcTable executeAndGetFrontImage(Statement st) throws SQLException; 41 | 42 | 43 | TxcTable getTableOriginalValue() throws SQLException; 44 | 45 | /** 46 | * 获取后置镜像 47 | * 48 | * @throws SQLException 49 | */ 50 | TxcTable executeAndGetRearImage(Statement st) throws SQLException; 51 | 52 | TxcTable getTablePresentValue() throws SQLException; 53 | 54 | /** 55 | * 获取原始数据的SQL 56 | * 57 | * @return 58 | */ 59 | String getInputSql(); 60 | 61 | /** 62 | * 获取原始数据的SQL 63 | * 64 | * @return 65 | */ 66 | String getFullSql(); 67 | 68 | /** 69 | * 查询SQL,用于取得DB行变更前后镜像 70 | * 71 | * @return 72 | */ 73 | String getSelectSql() throws SQLException; 74 | 75 | 76 | String getWhereCondition(TxcTable table); 77 | 78 | 79 | String getTableName() throws SQLException; 80 | 81 | SqlType getSqlType(); 82 | 83 | 84 | 85 | TxcTableMeta getTableMeta(); 86 | 87 | DtsSQLStatement getSQLStatement(); 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /dts-server/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /dts-server/src/main/conf/logback_server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | ${user.home}/logs/hybrid/server_default.log 6 | true 7 | 8 | ${user.home}/logs/hybrid/backup/server_default.%i.log 9 | 10 | 1 11 | 5 12 | 13 | 15 | 100MB 16 | 17 | 18 | %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n 19 | UTF-8 20 | 21 | 22 | 23 | 25 | ${user.home}/logs/hybrid/server.log 26 | true 27 | 28 | ${user.home}/logs/hybrid/backup/server.%i.log 29 | 30 | 1 31 | 5 32 | 33 | 35 | 100MB 36 | 37 | 38 | %d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n 39 | UTF-8 40 | 41 | 42 | 43 | 44 | true 45 | 46 | %d{yyy-MM-dd HH\:mm\:ss,SSS} %p %t - %m%n 47 | UTF-8 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/BranchRollBackMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.RequestMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version BranchRollBackMessage.java, v 0.0.1 2017年9月1日 下午5:47:51 liushiming 24 | */ 25 | public class BranchRollBackMessage implements CommandCustomHeader, RequestMessage { 26 | /** 27 | * 服务端地址 28 | */ 29 | private String serverAddr; 30 | /** 31 | * 事务ID 32 | */ 33 | @CFNotNull 34 | private long tranId; 35 | /** 36 | * 分支ID 37 | */ 38 | @CFNotNull 39 | private long branchId; 40 | 41 | 42 | private String resourceInfo; 43 | 44 | 45 | public String getServerAddr() { 46 | return serverAddr; 47 | } 48 | 49 | public void setServerAddr(String serverAddr) { 50 | this.serverAddr = serverAddr; 51 | } 52 | 53 | public long getTranId() { 54 | return tranId; 55 | } 56 | 57 | public void setTranId(long tranId) { 58 | this.tranId = tranId; 59 | } 60 | 61 | public long getBranchId() { 62 | return branchId; 63 | } 64 | 65 | public void setBranchId(long branchId) { 66 | this.branchId = branchId; 67 | } 68 | 69 | public String getResourceInfo() { 70 | return resourceInfo; 71 | } 72 | 73 | public void setResourceInfo(String dbName) { 74 | this.resourceInfo = dbName; 75 | } 76 | 77 | @Override 78 | public void checkFields() throws RemotingCommandException { 79 | 80 | } 81 | 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /dts-example/dts-example-consumer/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /dts-example/dts-example-provider/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/network/processor/HeatBeatProcessor.java: -------------------------------------------------------------------------------- 1 | package io.dts.server.network.processor; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.stereotype.Component; 6 | 7 | import io.dts.common.protocol.RequestCode; 8 | import io.dts.common.protocol.heatbeat.HeartbeatRequestHeader; 9 | import io.dts.common.protocol.heatbeat.HeartbeatResponseHeader; 10 | import io.dts.remoting.exception.RemotingCommandException; 11 | import io.dts.remoting.netty.NettyRequestProcessor; 12 | import io.dts.remoting.protocol.RemotingCommand; 13 | import io.dts.remoting.protocol.RemotingSysResponseCode; 14 | import io.dts.server.network.channel.ChannelInfo; 15 | import io.dts.server.network.channel.ChannelRepository; 16 | import io.netty.channel.ChannelHandlerContext; 17 | 18 | /** 19 | * 20 | * @author liushiming 21 | * @version ChannelHeatBeatProcessor.java, v 0.0.1 2017年9月6日 上午11:37:02 liushiming 22 | */ 23 | @Component 24 | @Qualifier("heatBeatProcessor") 25 | public class HeatBeatProcessor implements NettyRequestProcessor { 26 | 27 | @Autowired 28 | private ChannelRepository channelRepository; 29 | 30 | @Override 31 | public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) 32 | throws Exception { 33 | switch (request.getCode()) { 34 | case RequestCode.HEART_BEAT: 35 | return this.heartbeat(ctx, request); 36 | default: 37 | break; 38 | } 39 | return null; 40 | } 41 | 42 | private RemotingCommand heartbeat(ChannelHandlerContext ctx, RemotingCommand request) 43 | throws RemotingCommandException { 44 | HeartbeatRequestHeader header = 45 | (HeartbeatRequestHeader) request.decodeCommandCustomHeader(HeartbeatRequestHeader.class); 46 | ChannelInfo clientChannelInfo = new ChannelInfo(// 47 | ctx.channel(), // 48 | header.getClientOrResourceInfo(), // 49 | request.getLanguage(), // 50 | request.getVersion()// 51 | ); 52 | channelRepository.registerChannel(clientChannelInfo); 53 | RemotingCommand response = RemotingCommand.createResponseCommand(HeartbeatResponseHeader.class); 54 | response.setCode(RemotingSysResponseCode.SUCCESS); 55 | return response; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/netty/NettyEncoder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.netty; 17 | 18 | import io.dts.remoting.common.RemotingHelper; 19 | import io.dts.remoting.common.RemotingUtil; 20 | import io.dts.remoting.protocol.RemotingCommand; 21 | import io.netty.buffer.ByteBuf; 22 | import io.netty.channel.ChannelHandlerContext; 23 | import io.netty.handler.codec.MessageToByteEncoder; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.nio.ByteBuffer; 28 | 29 | 30 | /** 31 | * 协议编码器 32 | * 33 | * @author shijia.wxr 34 | * @since 2013-7-13 35 | */ 36 | public class NettyEncoder extends MessageToByteEncoder { 37 | private static final Logger log = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); 38 | 39 | 40 | @Override 41 | public void encode(ChannelHandlerContext ctx, RemotingCommand remotingCommand, ByteBuf out) 42 | throws Exception { 43 | try { 44 | ByteBuffer header = remotingCommand.encodeHeader(); 45 | out.writeBytes(header); 46 | byte[] body = remotingCommand.getBody(); 47 | if (body != null) { 48 | out.writeBytes(body); 49 | } 50 | } 51 | catch (Exception e) { 52 | log.error("encode exception, " + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e); 53 | if (remotingCommand != null) { 54 | log.error(remotingCommand.toString()); 55 | } 56 | // 这里关闭后, 会在pipeline中产生事件,通过具体的close事件来清理数据结构 57 | RemotingUtil.closeChannel(ctx.channel()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/vistor/mysql/DtsDeleteVisitor.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.vistor.mysql; 2 | 3 | import java.sql.SQLException; 4 | import java.sql.Statement; 5 | import java.util.List; 6 | 7 | import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; 8 | import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; 9 | 10 | import io.dts.parser.DtsSQLStatement; 11 | import io.dts.parser.struct.TxcTable; 12 | import io.dts.parser.struct.TxcTableMeta; 13 | 14 | 15 | public class DtsDeleteVisitor extends AbstractDtsVisitor { 16 | 17 | public DtsDeleteVisitor(DtsSQLStatement node, List parameterSet) { 18 | super(node, parameterSet); 19 | } 20 | 21 | @Override 22 | public String parseWhereCondition(Statement st) { 23 | SQLDeleteStatement selectStatement = (SQLDeleteStatement) this.node.getSQLStatement(); 24 | StringBuffer out = parseWhereCondition(selectStatement.getWhere()); 25 | return out.toString(); 26 | } 27 | 28 | @Override 29 | public TxcTable executeAndGetFrontImage(Statement st) throws SQLException { 30 | String sql = getSelectSql() + getWhereCondition(st) + " FOR UPDATE"; 31 | 32 | TxcTable tableOriginalValue = getTableOriginalValue(); 33 | TxcTableMeta tableMeta = getTableMeta(); 34 | 35 | tableOriginalValue.setTableMeta(tableMeta); 36 | tableOriginalValue.setTableName(tableMeta.getTableName()); 37 | tableOriginalValue.setAlias(tableMeta.getAlias()); 38 | tableOriginalValue.setSchemaName(tableMeta.getSchemaName()); 39 | tableOriginalValue.setLines(addLines(sql)); 40 | return tableOriginalValue; 41 | } 42 | 43 | @Override 44 | public TxcTable executeAndGetRearImage(Statement st) throws SQLException { 45 | // SQL执行后查询DB行现值,用户脏读检查 46 | // 删除后,数据库已没有满足条件的数据,不需操作 47 | TxcTableMeta tableMeta = getTableMeta(); 48 | TxcTable tablePresentValue = getTablePresentValue(); 49 | tablePresentValue.setTableMeta(tableMeta); 50 | tablePresentValue.setTableName(tableMeta.getTableName()); 51 | tablePresentValue.setAlias(tableMeta.getAlias()); 52 | tablePresentValue.setSchemaName(tableMeta.getSchemaName()); 53 | return tablePresentValue; 54 | } 55 | 56 | @Override 57 | public boolean visit(final MySqlDeleteStatement x) { 58 | setTableName(x.getTableName().toString()); 59 | setTableNameAlias(x.getAlias() != null ? x.getAlias() : null); 60 | return super.visit(x); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/DtsObjectWapper.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser; 2 | 3 | 4 | import com.alibaba.fastjson.JSON; 5 | import com.alibaba.fastjson.serializer.SerializerFeature; 6 | 7 | import io.dts.common.exception.DtsException; 8 | 9 | import java.util.Date; 10 | 11 | public class DtsObjectWapper { 12 | public static String jsonObjectDeserialize(int type, Object value) { 13 | if (value == null) { 14 | return "null"; 15 | } 16 | 17 | switch (type) { 18 | case java.sql.Types.ARRAY: 19 | case java.sql.Types.CHAR: 20 | case java.sql.Types.LONGNVARCHAR: 21 | case java.sql.Types.LONGVARCHAR: 22 | case java.sql.Types.NCHAR: 23 | case java.sql.Types.VARCHAR: 24 | case java.sql.Types.NVARCHAR: 25 | return "'" + value + "'"; 26 | case java.sql.Types.DATE: 27 | case java.sql.Types.TIME: 28 | case java.sql.Types.TIMESTAMP: 29 | Date d = new Date(Long.parseLong(value.toString())); 30 | return JSON.toJSONString(d, SerializerFeature.WriteDateUseDateFormat, 31 | SerializerFeature.UseSingleQuotes); 32 | default: 33 | return value.toString(); 34 | } 35 | } 36 | 37 | 38 | public static void appendParamMarkerObject(Object value, StringBuilder appender) { 39 | if (value == null) { 40 | appender.append("null"); 41 | return; 42 | } 43 | 44 | if (String.class.isAssignableFrom(value.getClass())) { 45 | String text = (String) value; 46 | appender.append("'" + text.replaceAll("'", "''") + "'"); 47 | } else if (Date.class.isAssignableFrom(value.getClass())) { 48 | appender.append("'" + value + "'"); 49 | } else if (Number.class.isAssignableFrom(value.getClass())) { 50 | appender.append(value); 51 | } else { 52 | throw new DtsException("" + value.getClass()); 53 | } 54 | } 55 | 56 | public static void appendParamMarkerObject(String name, Object value, StringBuilder appender) { 57 | 58 | appender.append(name); 59 | appender.append(" = "); 60 | if (String.class.isAssignableFrom(value.getClass())) { 61 | appender.append("'" + value + "'"); 62 | } else if (Date.class.isAssignableFrom(value.getClass())) { 63 | appender.append("'" + value + "'"); 64 | } else if (Number.class.isAssignableFrom(value.getClass())) { 65 | appender.append(value); 66 | } else { 67 | appender.append("NULL"); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /dts-common/src/main/java/io/dts/common/protocol/header/BranchCommitMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.common.protocol.header; 15 | 16 | import io.dts.common.protocol.RequestMessage; 17 | import io.dts.remoting.CommandCustomHeader; 18 | import io.dts.remoting.annotation.CFNotNull; 19 | import io.dts.remoting.exception.RemotingCommandException; 20 | 21 | /** 22 | * @author liushiming 23 | * @version BranchCommitMessage.java, v 0.0.1 2017年9月1日 下午5:46:22 liushiming 24 | */ 25 | public class BranchCommitMessage implements CommandCustomHeader, RequestMessage { 26 | 27 | private String serverAddr; 28 | 29 | @CFNotNull 30 | private Long tranId; 31 | 32 | @CFNotNull 33 | private Long branchId; 34 | 35 | @CFNotNull 36 | private String clientIp; 37 | 38 | private String resourceInfo; 39 | 40 | 41 | public String getServerAddr() { 42 | return serverAddr; 43 | } 44 | 45 | public void setServerAddr(String serverAddr) { 46 | this.serverAddr = serverAddr; 47 | } 48 | 49 | public Long getTranId() { 50 | return tranId; 51 | } 52 | 53 | public void setTranId(Long tranId) { 54 | this.tranId = tranId; 55 | } 56 | 57 | public Long getBranchId() { 58 | return branchId; 59 | } 60 | 61 | public void setBranchId(Long branchId) { 62 | this.branchId = branchId; 63 | } 64 | 65 | public String getClientIp() { 66 | return clientIp; 67 | } 68 | 69 | public void setClientIp(String clientIp) { 70 | this.clientIp = clientIp; 71 | } 72 | 73 | 74 | 75 | public String getResourceInfo() { 76 | return resourceInfo; 77 | } 78 | 79 | public void setResourceInfo(String dbName) { 80 | this.resourceInfo = dbName; 81 | } 82 | 83 | 84 | @Override 85 | public void checkFields() throws RemotingCommandException { 86 | 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/DtsServerApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.server; 15 | 16 | import javax.sql.DataSource; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | import org.springframework.context.ConfigurableApplicationContext; 22 | import org.springframework.context.annotation.Bean; 23 | import org.springframework.jdbc.core.JdbcTemplate; 24 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 25 | import org.springframework.transaction.PlatformTransactionManager; 26 | import org.springframework.transaction.support.TransactionTemplate; 27 | 28 | import io.dts.server.network.NettyServerController; 29 | 30 | /** 31 | * @author liushiming 32 | * @version Application.java, v 0.0.1 2017年9月5日 下午6:31:29 liushiming 33 | */ 34 | @SpringBootApplication 35 | public class DtsServerApp { 36 | 37 | public static void main(String[] args) throws Exception { 38 | ConfigurableApplicationContext context = SpringApplication.run(DtsServerApp.class, args); 39 | NettyServerController controller = context.getBean(NettyServerController.class); 40 | controller.start(); 41 | } 42 | 43 | @Bean 44 | public PlatformTransactionManager annotationDrivenTransactionManager( 45 | @Autowired DataSource dataSource) { 46 | return new DataSourceTransactionManager(dataSource); 47 | } 48 | 49 | @Bean 50 | public TransactionTemplate transactionTemplate( 51 | @Autowired PlatformTransactionManager transactionManager) { 52 | return new TransactionTemplate(transactionManager); 53 | } 54 | 55 | @Bean 56 | public JdbcTemplate transactionTemplate(@Autowired DataSource dataSource) { 57 | return new JdbcTemplate(dataSource); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /dts-example/dts-example-provider/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | dts-example 6 | io.dts 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | dts-example-provider 11 | 12 | 13 | osx-x86_64 14 | 15 | 16 | 17 | io.dts 18 | dts-saluki-support 19 | ${dts.version} 20 | 21 | 22 | com.alibaba 23 | druid 24 | 1.0.15 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-data-jpa 29 | 30 | 31 | mysql 32 | mysql-connector-java 33 | 5.1.40 34 | 35 | 36 | com.quancheng.saluki 37 | spring-boot-starter-saluki 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-log4j 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-web 46 | 47 | 48 | spring-boot-starter-tomcat 49 | org.springframework.boot 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-jetty 56 | 57 | 58 | io.netty 59 | netty-tcnative-boringssl-static 60 | ${netty-tcnative.version} 61 | ${os.detected.classifier} 62 | 63 | 64 | io.dts 65 | dts-example-api 66 | ${project.version} 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/netty/NettyDecoder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting.netty; 17 | 18 | import io.dts.remoting.common.RemotingHelper; 19 | import io.dts.remoting.common.RemotingUtil; 20 | import io.dts.remoting.protocol.RemotingCommand; 21 | import io.netty.buffer.ByteBuf; 22 | import io.netty.channel.ChannelHandlerContext; 23 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.nio.ByteBuffer; 28 | 29 | 30 | /** 31 | * 协议解码器 32 | * 33 | * @author shijia.wxr 34 | * @since 2013-7-13 35 | */ 36 | public class NettyDecoder extends LengthFieldBasedFrameDecoder { 37 | private static final Logger log = LoggerFactory.getLogger(RemotingHelper.RemotingLogName); 38 | private static final int FRAME_MAX_LENGTH = // 39 | Integer.parseInt(System.getProperty("com.rocketmq.remoting.frameMaxLength", "8388608")); 40 | 41 | 42 | public NettyDecoder() { 43 | super(FRAME_MAX_LENGTH, 0, 4, 0, 4); 44 | } 45 | 46 | 47 | @Override 48 | public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { 49 | ByteBuf frame = null; 50 | try { 51 | frame = (ByteBuf) super.decode(ctx, in); 52 | if (null == frame) { 53 | return null; 54 | } 55 | 56 | ByteBuffer byteBuffer = frame.nioBuffer(); 57 | 58 | return RemotingCommand.decode(byteBuffer); 59 | } 60 | catch (Exception e) { 61 | log.error("decode exception, " + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e); 62 | // 这里关闭后, 会在pipeline中产生事件,通过具体的close事件来清理数据结构 63 | RemotingUtil.closeChannel(ctx.channel()); 64 | } 65 | finally { 66 | if (null != frame) { 67 | frame.release(); 68 | } 69 | } 70 | 71 | return null; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/struct/MySQLKeyword.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2015 dangdang.com. 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *

16 | */ 17 | 18 | package io.dts.parser.struct; 19 | 20 | /** 21 | * MySQL keyword. 22 | * 23 | * @author zhangliang 24 | */ 25 | public enum MySQLKeyword { 26 | 27 | SHOW, 28 | DUAL, 29 | LIMIT, 30 | OFFSET, 31 | VALUE, 32 | BEGIN, 33 | FORCE, 34 | PARTITION, 35 | DISTINCTROW, 36 | KILL, 37 | QUICK, 38 | BINARY, 39 | CACHE, 40 | SQL_CACHE, 41 | SQL_NO_CACHE, 42 | SQL_SMALL_RESULT, 43 | SQL_BIG_RESULT, 44 | SQL_BUFFER_RESULT, 45 | SQL_CALC_FOUND_ROWS, 46 | LOW_PRIORITY, 47 | HIGH_PRIORITY, 48 | OPTIMIZE, 49 | ANALYZE, 50 | IGNORE, 51 | CHANGE, 52 | FIRST, 53 | FULLTEXT, 54 | SPATIAL, 55 | ALGORITHM, 56 | CHARACTER, 57 | COLLATE, 58 | DISCARD, 59 | IMPORT, 60 | VALIDATION, 61 | REORGANIZE, 62 | EXCHANGE, 63 | REBUILD, 64 | REPAIR, 65 | REMOVE, 66 | UPGRADE, 67 | KEY_BLOCK_SIZE, 68 | AUTO_INCREMENT, 69 | AVG_ROW_LENGTH, 70 | CHECKSUM, 71 | COMPRESSION, 72 | CONNECTION, 73 | DIRECTORY, 74 | DELAY_KEY_WRITE, 75 | ENCRYPTION, 76 | ENGINE, 77 | INSERT_METHOD, 78 | MAX_ROWS, 79 | MIN_ROWS, 80 | PACK_KEYS, 81 | ROW_FORMAT, 82 | DYNAMIC, 83 | FIXED, 84 | COMPRESSED, 85 | REDUNDANT, 86 | COMPACT, 87 | STATS_AUTO_RECALC, 88 | STATS_PERSISTENT, 89 | STATS_SAMPLE_PAGES, 90 | DISK, 91 | MEMORY, 92 | ROLLUP, 93 | RESTRICT, 94 | STRAIGHT_JOIN; 95 | 96 | public static boolean isKeyword(final String columnName) { 97 | for (MySQLKeyword mySQLKeyword : MySQLKeyword.values()) { 98 | if (mySQLKeyword.name().equals(columnName)) { 99 | return true; 100 | } 101 | } 102 | return false; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/protocol/RemotingSerializable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.remoting.protocol; 15 | 16 | import java.nio.charset.Charset; 17 | 18 | import com.alibaba.fastjson.JSON; 19 | import com.alibaba.fastjson.serializer.SerializerFeature; 20 | 21 | 22 | /** 23 | * 复杂对象的序列化,利用json来实现 24 | * 25 | * @author shijia.wxr 26 | * @since 2013-7-13 27 | */ 28 | public abstract class RemotingSerializable { 29 | public String toJson() { 30 | return toJson(false); 31 | } 32 | 33 | 34 | public String toJson(final boolean prettyFormat) { 35 | return toJson(this, prettyFormat); 36 | } 37 | 38 | 39 | public static String toJson(final Object obj, boolean prettyFormat) { 40 | return JSON.toJSONString(obj, prettyFormat); 41 | } 42 | 43 | 44 | public static T fromJson(String json, Class classOfT) { 45 | return JSON.parseObject(json, classOfT); 46 | } 47 | 48 | 49 | public byte[] encode() { 50 | final String json = this.toJson(); 51 | if (json != null) { 52 | return json.getBytes(); 53 | } 54 | return null; 55 | } 56 | 57 | 58 | public static byte[] encode(final Object obj) { 59 | final String json = toJson(obj, false); 60 | if (json != null) { 61 | return json.getBytes(Charset.forName("UTF-8")); 62 | } 63 | return null; 64 | } 65 | 66 | private static final SerializerFeature[] featuresWriteClassName = 67 | new SerializerFeature[] {SerializerFeature.PrettyFormat, SerializerFeature.WriteClassName}; 68 | 69 | 70 | public static byte[] encode1(final Object obj) { 71 | final String json = JSON.toJSONString(obj, featuresWriteClassName); 72 | if (json != null) { 73 | return json.getBytes(Charset.forName("UTF-8")); 74 | } 75 | return null; 76 | } 77 | 78 | public static T decode(final byte[] data, Class classOfT) { 79 | final String json = new String(data, Charset.forName("UTF-8")); 80 | return fromJson(json, classOfT); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /dts-datasource/src/main/java/io/dts/datasource/wrapper/DtsPrepareStatementWrapper.java: -------------------------------------------------------------------------------- 1 | package io.dts.datasource.wrapper; 2 | 3 | import java.sql.PreparedStatement; 4 | import java.sql.ResultSet; 5 | import java.sql.SQLException; 6 | 7 | import io.dts.common.context.DtsContext; 8 | import io.dts.datasource.DtsConnection; 9 | import io.dts.datasource.wrapper.executor.PreparedStatementExecutor; 10 | 11 | /** 12 | * Created by guoyubo on 2017/9/26. 13 | */ 14 | public class DtsPrepareStatementWrapper extends AbstractDtsPrepareStatement { 15 | 16 | 17 | public DtsPrepareStatementWrapper(final DtsConnection dtsConnection, 18 | final PreparedStatement statement, String sql) { 19 | super(dtsConnection, statement); 20 | setTargetSql(sql); 21 | } 22 | 23 | @Override 24 | public ResultSet executeQuery() throws SQLException { 25 | return getRawStatement().executeQuery(); 26 | } 27 | 28 | 29 | @Override 30 | public int executeUpdate() throws SQLException { 31 | try { 32 | return new PreparedStatementExecutor(createStatementModel(getTargetSql()), getParameters()) 33 | .executeUpdate(); 34 | } catch (Exception e) { 35 | throw new SQLException(e); 36 | } 37 | } 38 | 39 | @Override 40 | public boolean execute() throws SQLException { 41 | try { 42 | return new PreparedStatementExecutor(createStatementModel(getTargetSql()), getParameters()) 43 | .execute(); 44 | } catch (Exception e) { 45 | throw new SQLException(e); 46 | } 47 | } 48 | 49 | @Override 50 | public void addBatch() throws SQLException { 51 | if (DtsContext.getInstance().inTxcTransaction()) { 52 | throw new UnsupportedOperationException("unsupport add batch in dts transaction"); 53 | } 54 | getRawStatement().addBatch(); 55 | } 56 | 57 | @Override 58 | public void addBatch(final String sql) throws SQLException { 59 | if (DtsContext.getInstance().inTxcTransaction()) { 60 | throw new UnsupportedOperationException("unsupport add batch in dts transaction"); 61 | } 62 | getRawStatement().addBatch(sql); 63 | } 64 | 65 | @Override 66 | public void clearBatch() throws SQLException { 67 | if (DtsContext.getInstance().inTxcTransaction()) { 68 | throw new UnsupportedOperationException("unsupport clear batch in dts transaction"); 69 | } 70 | getRawStatement().clearBatch(); 71 | } 72 | 73 | @Override 74 | public int[] executeBatch() throws SQLException { 75 | if (DtsContext.getInstance().inTxcTransaction()) { 76 | throw new UnsupportedOperationException("unsupport execute batch in dts transaction"); 77 | } 78 | return getRawStatement().executeBatch(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /dts-resourcemanager/src/main/java/io/dts/resourcemanager/logmanager/BranchCommitLogManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.resourcemanager.logmanager; 15 | 16 | import java.sql.SQLException; 17 | 18 | import javax.sql.DataSource; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.jdbc.core.JdbcTemplate; 23 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 24 | import org.springframework.transaction.TransactionStatus; 25 | import org.springframework.transaction.support.TransactionCallbackWithoutResult; 26 | import org.springframework.transaction.support.TransactionTemplate; 27 | 28 | import io.dts.resourcemanager.DataSourceHolder; 29 | import io.dts.resourcemanager.struct.ContextStep2; 30 | import io.dts.resourcemanager.struct.UndoLogMode; 31 | 32 | /** 33 | * @author liushiming 34 | * @version BranchCommitLogManager.java, v 0.0.1 2017年10月24日 下午3:52:14 liushiming 35 | */ 36 | public class BranchCommitLogManager extends DtsLogManagerImpl { 37 | 38 | private static final Logger logger = LoggerFactory.getLogger(BranchCommitLogManager.class); 39 | 40 | @Override 41 | public void branchCommit(ContextStep2 context) throws SQLException { 42 | DataSource datasource = DataSourceHolder.getDataSource(context.getDbname()); 43 | DataSourceTransactionManager tm = new DataSourceTransactionManager(datasource); 44 | TransactionTemplate transactionTemplate = new TransactionTemplate(tm); 45 | final JdbcTemplate template = new JdbcTemplate(datasource); 46 | transactionTemplate.execute(new TransactionCallbackWithoutResult() { 47 | @Override 48 | protected void doInTransactionWithoutResult(TransactionStatus status) { 49 | String deleteSql = String.format("delete from %s where id in (%s) and status = %d", 50 | txcLogTableName, context.getGlobalXid(), UndoLogMode.COMMON_LOG.getValue()); 51 | logger.info("delete undo log sql:" + deleteSql); 52 | template.execute(deleteSql); 53 | } 54 | }); 55 | } 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /dts-parser/src/main/java/io/dts/parser/struct/TxcIndex.java: -------------------------------------------------------------------------------- 1 | package io.dts.parser.struct; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class TxcIndex { 8 | private List values = new ArrayList(); 9 | 10 | private boolean nonUnique; // 不唯一 11 | private String indexQualifier;// 索引目录(可能为空) 12 | private String indexName;// 索引的名称 13 | private short type;// 索引类型 14 | private IndexType indextype; 15 | private String ascOrDesc;// 列排序顺序:升序还是降序 16 | private int cardinality; // 基数 17 | private int ordinalPosition; // 表中列的索引(从1开始) 18 | 19 | public TxcIndex() { 20 | } 21 | 22 | // public TxcIndex(ColumnMeta column) { 23 | // indexName = column.getName(); 24 | // values.add(new TxcColumnMeta(column)); 25 | // } 26 | 27 | public List getValues() { 28 | return values; 29 | } 30 | 31 | public void setValues(List values) { 32 | this.values = values; 33 | } 34 | 35 | public boolean isNonUnique() { 36 | return nonUnique; 37 | } 38 | 39 | public void setNonUnique(boolean nonUnique) { 40 | this.nonUnique = nonUnique; 41 | } 42 | 43 | public String getIndexQualifier() { 44 | return indexQualifier; 45 | } 46 | 47 | public void setIndexQualifier(String indexQualifier) { 48 | this.indexQualifier = indexQualifier; 49 | } 50 | 51 | public String getIndexName() { 52 | return indexName; 53 | } 54 | 55 | public void setIndexName(String indexName) { 56 | this.indexName = indexName; 57 | } 58 | 59 | public short getType() { 60 | return type; 61 | } 62 | 63 | public void setType(short type) { 64 | this.type = type; 65 | } 66 | 67 | public String getAscOrDesc() { 68 | return ascOrDesc; 69 | } 70 | 71 | public void setAscOrDesc(String ascOrDesc) { 72 | this.ascOrDesc = ascOrDesc; 73 | } 74 | 75 | public int getCardinality() { 76 | return cardinality; 77 | } 78 | 79 | public void setCardinality(int cardinality) { 80 | this.cardinality = cardinality; 81 | } 82 | 83 | public int getOrdinalPosition() { 84 | return ordinalPosition; 85 | } 86 | 87 | public void setOrdinalPosition(int ordinalPosition) { 88 | this.ordinalPosition = ordinalPosition; 89 | } 90 | 91 | public IndexType getIndextype() { 92 | return indextype; 93 | } 94 | 95 | public void setIndextype(IndexType indextype) { 96 | this.indextype = indextype; 97 | } 98 | 99 | public List getIndexvalue() { 100 | return values; 101 | } 102 | 103 | public String toString() { 104 | return "indexName:" + indexName + "->" + "type:" + type + "->" + "values:" + values; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /dts-remoting/src/main/java/io/dts/remoting/RemotingClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2010-2013 Alibaba Group Holding Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.dts.remoting; 17 | 18 | import io.dts.remoting.exception.RemotingConnectException; 19 | import io.dts.remoting.exception.RemotingSendRequestException; 20 | import io.dts.remoting.exception.RemotingTimeoutException; 21 | import io.dts.remoting.exception.RemotingTooMuchRequestException; 22 | import io.dts.remoting.netty.NettyRequestProcessor; 23 | import io.dts.remoting.protocol.RemotingCommand; 24 | 25 | import java.util.List; 26 | import java.util.concurrent.ExecutorService; 27 | 28 | 29 | /** 30 | * 远程通信,Client接口 31 | * 32 | * @author shijia.wxr 33 | * @since 2013-7-13 34 | */ 35 | public interface RemotingClient extends RemotingService { 36 | 37 | public void updateNameServerAddressList(final List addrs); 38 | 39 | 40 | public List getNameServerAddressList(); 41 | 42 | 43 | public RemotingCommand invokeSync(final String addr, final RemotingCommand request, 44 | final long timeoutMillis) throws InterruptedException, RemotingConnectException, 45 | RemotingSendRequestException, RemotingTimeoutException; 46 | 47 | 48 | public void invokeAsync(final String addr, final RemotingCommand request, final long timeoutMillis, 49 | final InvokeCallback invokeCallback) throws InterruptedException, RemotingConnectException, 50 | RemotingTooMuchRequestException, RemotingTimeoutException, RemotingSendRequestException; 51 | 52 | 53 | public void invokeOneway(final String addr, final RemotingCommand request, final long timeoutMillis) 54 | throws InterruptedException, RemotingConnectException, RemotingTooMuchRequestException, 55 | RemotingTimeoutException, RemotingSendRequestException; 56 | 57 | 58 | public void registerProcessor(final int requestCode, final NettyRequestProcessor processor, 59 | final ExecutorService executor); 60 | 61 | 62 | public boolean isChannelWriteable(final String addr); 63 | } 64 | -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/handler/support/RmMessageHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.server.handler.support; 15 | 16 | import io.dts.common.api.DtsServerMessageSender; 17 | import io.dts.common.exception.DtsException; 18 | import io.dts.common.protocol.header.RegisterMessage; 19 | import io.dts.server.store.DtsLogDao; 20 | import io.dts.server.struct.BranchLog; 21 | import io.dts.server.struct.BranchLogState; 22 | import io.dts.server.struct.GlobalLog; 23 | import io.dts.server.struct.GlobalLogState; 24 | 25 | /** 26 | * @author liushiming 27 | * @version RmMessageHandler.java, v 0.0.1 2017年9月19日 下午2:48:59 liushiming 28 | */ 29 | public interface RmMessageHandler { 30 | 31 | Long processMessage(RegisterMessage registerMessage, String clientIp); 32 | 33 | public static RmMessageHandler createResourceManagerMessageProcessor(DtsLogDao dtsLogDao, 34 | DtsServerMessageSender messageSender) { 35 | 36 | return new RmMessageHandler() { 37 | 38 | @Override 39 | public Long processMessage(RegisterMessage registerMessage, String clientIp) { 40 | long tranId = registerMessage.getTranId(); 41 | GlobalLog globalLog = dtsLogDao.getGlobalLog(tranId); 42 | if (globalLog == null || globalLog.getState() != GlobalLogState.Begin.getValue()) { 43 | if (globalLog == null) { 44 | throw new DtsException("Transaction " + tranId + " doesn't exist"); 45 | } else { 46 | throw new DtsException( 47 | "Transaction " + tranId + " is in state:" + globalLog.getState()); 48 | } 49 | } 50 | BranchLog branchLog = new BranchLog(); 51 | branchLog.setTransId(tranId); 52 | branchLog.setClientInfo(registerMessage.getClientInfo()); 53 | branchLog.setClientIp(clientIp); 54 | branchLog.setState(BranchLogState.Begin.getValue()); 55 | dtsLogDao.insertBranchLog(branchLog); 56 | Long branchId = branchLog.getBranchId(); 57 | globalLog.getBranchIds().add(branchId); 58 | return branchId; 59 | } 60 | 61 | }; 62 | } 63 | 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /dts-server/src/main/java/io/dts/server/network/ServerFixedThreadPoolExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.dts.server.network; 15 | 16 | import java.util.concurrent.BlockingQueue; 17 | import java.util.concurrent.RejectedExecutionHandler; 18 | import java.util.concurrent.RunnableFuture; 19 | import java.util.concurrent.ThreadFactory; 20 | import java.util.concurrent.ThreadPoolExecutor; 21 | import java.util.concurrent.TimeUnit; 22 | 23 | /** 24 | * @author liushiming 25 | * @version ServerFixedThreadPoolExecutor.java, v 0.0.1 2017年9月12日 下午6:42:31 liushiming 26 | */ 27 | public class ServerFixedThreadPoolExecutor extends ThreadPoolExecutor { 28 | public ServerFixedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, 29 | final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue) { 30 | super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 31 | } 32 | 33 | public ServerFixedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, 34 | final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue, 35 | final ThreadFactory threadFactory) { 36 | super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); 37 | } 38 | 39 | public ServerFixedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, 40 | final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue, 41 | final RejectedExecutionHandler handler) { 42 | super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); 43 | } 44 | 45 | public ServerFixedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, 46 | final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue, 47 | final ThreadFactory threadFactory, final RejectedExecutionHandler handler) { 48 | super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); 49 | } 50 | 51 | @Override 52 | protected RunnableFuture newTaskFor(final Runnable runnable, final T value) { 53 | return new FutureTaskExt(runnable, value); 54 | } 55 | } 56 | --------------------------------------------------------------------------------