From 7ca3332d67c2f0d43ce7d854e6bbb04e48bcae8b Mon Sep 17 00:00:00 2001 From: zhangthen <45684527+zhangthen@users.noreply.github.com> Date: Fri, 24 May 2019 17:47:44 +0800 Subject: [PATCH 1/5] Release 0.6.0 (#1106) --- .gitignore | 3 +- README.md | 2 +- all/pom.xml | 30 +- bom/pom.xml | 27 +- .../main/java/io/seata/common/Constants.java | 11 + .../common/loader/EnhancedServiceLoader.java | 80 ++- .../io/seata/common/loader/LoadLevel.java | 2 +- .../java/io/seata/common/util/BlobUtils.java | 46 +- .../io/seata/common/util/CollectionUtils.java | 44 ++ .../io/seata/common/util/DurationUtil.java | 74 ++ .../io/seata/common/util/StringUtils.java | 118 ++-- .../io/seata/common/util/BlobUtilsTest.java | 35 +- .../io/seata/common/util/StringUtilsTest.java | 56 +- config/pom.xml | 1 + config/seata-config-all/pom.xml | 5 + .../seata/config/AbstractConfiguration.java | 21 + .../main/java/io/seata/config/ConfigType.java | 6 +- .../java/io/seata/config/Configuration.java | 28 + .../io/seata/config/ConfigurationFactory.java | 22 +- .../src/main/resources/file.conf | 6 +- .../src/main/resources/registry.conf | 5 +- config/seata-config-etcd3/pom.xml | 49 ++ .../seata/config/etcd/EtcdConfiguration.java | 318 +++++++++ .../etcd/EtcdConfigurationProvider.java | 32 + .../io.seata.config.ConfigurationProvider | 1 + core/pom.xml | 11 + .../core/constants/ConfigurationKeys.java | 107 +++ .../java/io/seata/core/constants/DBType.java | 93 +++ .../exception/AbstractExceptionHandler.java | 7 + .../io/seata/core/lock/AbstractLocker.java | 85 +++ .../io/seata/core/lock/LocalDBLocker.java | 42 ++ .../java/io/seata/core/lock/LockMode.java | 37 + .../main/java/io/seata/core/lock/Locker.java | 59 ++ .../main/java/io/seata/core/lock/RowLock.java | 193 +++++ .../seata/core/protocol/AbstractMessage.java | 3 +- .../java/io/seata/core/protocol/Version.java | 2 +- .../io/seata/core/rpc/ChannelManager.java | 1 - .../java/io/seata/core/rpc/RpcContext.java | 1 - .../core/rpc/netty/AbstractRpcRemoting.java | 5 - .../core/rpc/netty/NettyClientConfig.java | 2 - .../core/rpc/netty/NettyPoolableFactory.java | 1 - .../rpc/netty/RegisterCheckAuthHandler.java | 2 - .../core/rpc/netty/RegisterMsgListener.java | 2 - .../seata/core/store/BranchTransactionDO.java | 277 ++++++++ .../seata/core/store/GlobalTransactionDO.java | 256 +++++++ .../main/java/io/seata/core/store/LockDO.java | 178 +++++ .../java/io/seata/core/store/LockStore.java | 68 ++ .../java/io/seata/core/store/LogStore.java | 110 +++ .../store/db/AbstractDataSourceGenerator.java | 148 ++++ .../core/store/db/DataSourceGenerator.java | 35 + .../core/store/db/LockStoreDataBaseDAO.java | 356 ++++++++++ .../io/seata/core/store/db/LockStoreSqls.java | 143 ++++ .../core/store/db/LogStoreDataBaseDAO.java | 533 ++++++++++++++ .../io/seata/core/store/db/LogStoreSqls.java | 323 +++++++++ .../services/io.seata.core.store.LockStore | 1 + .../services/io.seata.core.store.LogStore | 1 + .../core/protocol/RegisterTMRequestTest.java | 192 +++++ .../store/db/DataBaseLockStoreDAOTest.java | 300 ++++++++ .../store/db/LogStoreDataBaseDAOTest.java | 659 ++++++++++++++++++ .../config/ConfigurationFactoryTest.java | 32 + .../eureka/EurekaRegistryProvider.java | 1 - .../registry/nacos/NacosRegistryProvider.java | 1 - .../registry/redis/RedisRegistryProvider.java | 2 - .../redis/RedisRegistryServiceImpl.java | 1 - pom.xml | 4 +- rm-datasource/pom.xml | 11 + .../AbstractPreparedStatementProxy.java | 1 - .../io/seata/rm/datasource/AsyncWorker.java | 4 +- .../rm/datasource/PreparedStatementProxy.java | 2 - .../seata/rm/datasource/StatementProxy.java | 2 - .../rm/datasource/exec/DeleteExecutor.java | 2 - .../rm/datasource/sql/WhereRecognizer.java | 1 - .../datasource/undo/AbstractUndoExecutor.java | 162 ++++- .../rm/datasource/undo/UndoLogManager.java | 15 +- .../undo/AbstractUndoExecutorTest.java | 316 +++++++++ .../rm/datasource/undo/UndoExecutorTest.java | 40 +- .../datasource/undo/UndoLogManagerTest.java | 16 +- .../keyword/MySQLKeywordCheckerTest.java | 1 - server/pom.xml | 18 + .../server/AbstractTCInboundHandler.java | 7 +- .../src/main/java/io/seata/server/Server.java | 2 +- .../coordinator/DefaultCoordinator.java | 215 ++++-- .../seata/server/coordinator/DefaultCore.java | 39 +- .../server/lock/AbstractLockManager.java | 117 ++++ .../seata/server/lock/DefaultLockManager.java | 103 +++ .../server/lock/DefaultLockManagerImpl.java | 186 ----- .../io/seata/server/lock/LockManager.java | 23 +- .../io/seata/server/lock/LockerFactory.java | 99 +++ .../seata/server/lock/db/DataBaseLocker.java | 101 +++ .../server/lock/memory/MemoryLocker.java | 193 +++++ .../session/AbstractSessionManager.java | 64 +- .../seata/server/session/BranchSession.java | 84 ++- .../server/session/DefaultSessionManager.java | 59 +- .../seata/server/session/GlobalSession.java | 120 +++- .../server/session/SessionCondition.java | 82 ++- .../seata/server/session/SessionHelper.java | 1 + .../seata/server/session/SessionHolder.java | 35 +- .../seata/server/session/SessionManager.java | 5 +- .../session/db/DataBaseSessionManager.java | 186 +++++ .../{ => file}/FileBasedSessionManager.java | 82 ++- .../AbstractTransactionStoreManager.java | 44 ++ .../ReloadableStore.java} | 36 +- .../server/store/TransactionStoreManager.java | 26 +- .../db/DatabaseTransactionStoreManager.java | 299 ++++++++ .../store/db/DbcpDataSourceGenerator.java | 54 ++ .../store/db/DruidDataSourceGenerator.java | 54 ++ .../FileTransactionStoreManager.java | 60 +- .../services/io.seata.core.lock.Locker | 2 + ...io.seata.core.store.db.DataSourceGenerator | 2 + .../io.seata.server.session.SessionManager | 3 + ...seata.server.store.TransactionStoreManager | 2 + server/src/main/resources/db_store.sql | 52 ++ server/src/main/resources/file.conf | 47 +- server/src/main/resources/logback.xml | 2 +- server/src/main/resources/nacos-config.txt | 24 +- server/src/main/resources/registry.conf | 5 +- .../test/java/WriteStoreMultithreadTest.java | 5 +- server/src/test/java/WriteStoreTest.java | 14 +- .../coordinator/DefaultCoordinatorTest.java | 23 +- .../server/coordinator/DefaultCoreTest.java | 42 +- .../io/seata/server/lock/LockManagerTest.java | 11 +- .../lock/db/DataBaseLockManagerImplTest.java | 301 ++++++++ .../lock/memory/MemoryLockManagerForTest.java | 32 + .../MemoryLockManagerImplTest.java} | 14 +- .../session/DefaultSessionManagerTest.java | 11 +- .../session/FileBasedSessionManagerTest.java | 21 +- .../db/DataBaseSessionManagerTest.java | 565 +++++++++++++++ .../seata/server/store/SessionStoreTest.java | 108 +-- .../java/io/seata/rm/tcc/TwoPhaseResult.java | 3 - .../seata/rm/tcc/remoting/RemotingParser.java | 2 - .../parser/LocalTCCRemotingParser.java | 1 - .../parser/SofaRpcRemotingParser.java | 2 - .../seata/core/rpc/netty/TmRpcClientTest.java | 3 - test/src/test/resources/file.conf | 4 + test/src/test/resources/registry.conf | 7 +- .../io/seata/tm/TransactionManagerHolder.java | 6 - .../tm/api/DefaultGlobalTransaction.java | 1 - 137 files changed, 8733 insertions(+), 845 deletions(-) create mode 100644 common/src/main/java/io/seata/common/util/DurationUtil.java create mode 100644 config/seata-config-etcd3/pom.xml create mode 100644 config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java create mode 100644 config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java create mode 100644 config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider create mode 100644 core/src/main/java/io/seata/core/constants/DBType.java create mode 100644 core/src/main/java/io/seata/core/lock/AbstractLocker.java create mode 100644 core/src/main/java/io/seata/core/lock/LocalDBLocker.java create mode 100644 core/src/main/java/io/seata/core/lock/LockMode.java create mode 100644 core/src/main/java/io/seata/core/lock/Locker.java create mode 100644 core/src/main/java/io/seata/core/lock/RowLock.java create mode 100644 core/src/main/java/io/seata/core/store/BranchTransactionDO.java create mode 100644 core/src/main/java/io/seata/core/store/GlobalTransactionDO.java create mode 100644 core/src/main/java/io/seata/core/store/LockDO.java create mode 100644 core/src/main/java/io/seata/core/store/LockStore.java create mode 100644 core/src/main/java/io/seata/core/store/LogStore.java create mode 100644 core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java create mode 100644 core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java create mode 100644 core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java create mode 100644 core/src/main/java/io/seata/core/store/db/LockStoreSqls.java create mode 100644 core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java create mode 100644 core/src/main/java/io/seata/core/store/db/LogStoreSqls.java create mode 100644 core/src/main/resources/META-INF/services/io.seata.core.store.LockStore create mode 100644 core/src/main/resources/META-INF/services/io.seata.core.store.LogStore create mode 100644 core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java create mode 100644 core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java create mode 100644 core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java create mode 100644 discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java create mode 100644 rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java create mode 100644 server/src/main/java/io/seata/server/lock/AbstractLockManager.java create mode 100644 server/src/main/java/io/seata/server/lock/DefaultLockManager.java delete mode 100644 server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java create mode 100644 server/src/main/java/io/seata/server/lock/LockerFactory.java create mode 100644 server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java create mode 100644 server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java create mode 100644 server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java rename server/src/main/java/io/seata/server/session/{ => file}/FileBasedSessionManager.java (71%) create mode 100644 server/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java rename server/src/main/java/io/seata/server/{lock/LockManagerFactory.java => store/ReloadableStore.java} (54%) create mode 100644 server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java create mode 100644 server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java create mode 100644 server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java rename server/src/main/java/io/seata/server/store/{ => file}/FileTransactionStoreManager.java (92%) create mode 100644 server/src/main/resources/META-INF/services/io.seata.core.lock.Locker create mode 100644 server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator create mode 100644 server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager create mode 100644 server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager create mode 100644 server/src/main/resources/db_store.sql create mode 100644 server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java create mode 100644 server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java rename server/src/test/java/io/seata/server/lock/{DefaultLockManagerImplTest.java => memory/MemoryLockManagerImplTest.java} (87%) create mode 100644 server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java diff --git a/.gitignore b/.gitignore index e34b7b267cd..44b06f93f74 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ target/ *.tar.gz *.class .flattened-pom.xml +dependency-reduced-pom.xml # eclipse ignore .settings/ @@ -36,4 +37,4 @@ target/ # system ignore .DS_Store Thumbs.db -*.orig \ No newline at end of file +*.orig diff --git a/README.md b/README.md index a4676b789b6..766f5739690 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ For more details about principle and design, please go to [Seata wiki page](http ## Maven dependency ```xml -0.5.1 +0.5.2 io.seata diff --git a/all/pom.xml b/all/pom.xml index 8f092f4971d..e05b28dcc51 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -21,7 +21,7 @@ io.seata seata-all - 0.5.2 + 0.6.0 Seata All-in-one ${project.version} http://seata.io @@ -112,6 +112,11 @@ seata-config-consul ${project.version} + + io.seata + seata-config-etcd3 + ${project.version} + io.seata seata-core @@ -423,7 +428,7 @@ true false false - false + true io.seata:seata-common @@ -433,6 +438,7 @@ io.seata:seata-config-nacos io.seata:seata-config-zk io.seata:seata-config-consul + io.seata:seata-config-etcd3 io.seata:seata-discovery-core io.seata:seata-discovery-consul io.seata:seata-discovery-eureka @@ -473,6 +479,12 @@ registry.conf + + *:* + + META-INF/maven/** + + @@ -497,20 +509,12 @@ maven-javadoc-plugin 2.10.4 - ${project.build.sourceEncoding} - true - true - false - true - true - true - - io.seata:seata-* - + ${project.build.sourceEncoding} + false - attach-javadocs + package jar diff --git a/bom/pom.xml b/bom/pom.xml index dc5ca5ed57d..76b370961a0 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -20,7 +20,7 @@ io.seata seata-bom - 0.5.2 + 0.6.0 4.0.0 pom @@ -30,29 +30,28 @@ 4.3.23.RELEASE 4.1.24.Final - 4.12 2.7.0 2.6.5 5.5.3 - 1.2.48 + 1.2.58 1.2.1 1.7.22 1.2.0 2.6 2.4.2 1.6 + 1.3 3.1 1.0 0.10 2.9.1 1.0.2 - 6.4 0.8.3 1.1.0 2.9.0 1.9.5 1.4.2 - 0.9.1 + 1.0.0 0.3.0 1.11.2 27.0.1-jre @@ -63,6 +62,9 @@ 4.4.11 1.1.12 2.7.0 + 10.2.0.3.0 + 5.1.30 + 1.4.181 @@ -270,6 +272,21 @@ caffeine ${caffeine.version} + + commons-dbcp + commons-dbcp + ${commons-dbcp.version} + + + com.h2database + h2 + ${h2.version} + + + mysql + mysql-connector-java + ${mysql.client.version} + diff --git a/common/src/main/java/io/seata/common/Constants.java b/common/src/main/java/io/seata/common/Constants.java index a76bacb155d..e39d856f5b9 100644 --- a/common/src/main/java/io/seata/common/Constants.java +++ b/common/src/main/java/io/seata/common/Constants.java @@ -15,6 +15,8 @@ */ package io.seata.common; +import java.nio.charset.Charset; + /** * The type Constants. * @@ -97,4 +99,13 @@ public class Constants { */ public final static String TCC_ACTION_CONTEXT = "actionContext"; + /** + * default charset name + */ + public static final String DEFAULT_CHARSET_NAME = "UTF-8"; + + /** + * default charset is utf-8 + */ + public static final Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_CHARSET_NAME); } diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index d10d95999bc..4c80b9c59f3 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -18,6 +18,8 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -27,6 +29,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import io.seata.common.Constants; import io.seata.common.executor.Initialize; import io.seata.common.util.CollectionUtils; @@ -102,12 +105,48 @@ public static S load(Class service, String activateName, ClassLoader load return loadFile(service, activateName, loader); } + /** + * Load s. + * + * @param the type parameter + * @param service the service + * @param activateName the activate name + * @param args the args + * @return the s + * @throws EnhancedServiceNotFoundException the enhanced service not found exception + */ + public static S load(Class service, String activateName, Object[] args) throws EnhancedServiceNotFoundException { + Class[] argsType = null; + if(args != null && args.length > 0){ + argsType = new Class[args.length]; + for(int i = 0; i < args.length; i ++){ + argsType[i] = args[i].getClass(); + } + } + return loadFile(service, activateName, findClassLoader(), argsType, args); + } + + /** + * Load s. + * + * @param the type parameter + * @param service the service + * @param activateName the activate name + * @param argsType the args type + * @param args the args + * @return the s + * @throws EnhancedServiceNotFoundException the enhanced service not found exception + */ + public static S load(Class service, String activateName, Class[] argsType, Object[] args) throws EnhancedServiceNotFoundException { + return loadFile(service, activateName, findClassLoader(), argsType, args); + } + /** * get all implements * * @param the type parameter * @param service the service - * @return list + * @return list list */ public static List loadAll(Class service) { List allInstances = new ArrayList<>(); @@ -117,7 +156,7 @@ public static List loadAll(Class service) { } try { for (Class clazz : allClazzs) { - allInstances.add(initInstance(service, clazz)); + allInstances.add(initInstance(service, clazz, null, null)); } } catch (Throwable t) { throw new EnhancedServiceNotFoundException(t); @@ -150,8 +189,12 @@ public static List getAllExtensionClass(Class service, ClassLoader return findAllExtensionClass(service, null, loader); } - @SuppressWarnings("rawtypes") private static S loadFile(Class service, String activateName, ClassLoader loader) { + return loadFile(service, activateName, loader, null, null); + } + + @SuppressWarnings("rawtypes") + private static S loadFile(Class service, String activateName, ClassLoader loader, Class[] argTypes, Object[] args) { try { boolean foundFromCache = true; List extensions = providers.get(service); @@ -173,7 +216,7 @@ private static S loadFile(Class service, String activateName, ClassLoader Class clz = extensions.get(i); @SuppressWarnings("unchecked") LoadLevel activate = (LoadLevel)clz.getAnnotation(LoadLevel.class); - if (activate != null && activateName.equals(activate.name())) { + if (activate != null && activateName.equalsIgnoreCase(activate.name())) { activateExtensions.add(clz); } } @@ -187,7 +230,7 @@ private static S loadFile(Class service, String activateName, ClassLoader + "] and classloader : " + ObjectUtils.toString(loader)); } Class extension = extensions.get(extensions.size() - 1); - S result = initInstance(service, extension); + S result = initInstance(service, extension, argTypes, args); if (!foundFromCache && LOGGER.isInfoEnabled()) { LOGGER.info("load " + service.getSimpleName() + "[" + activateName + "] extension by class[" + extension .getName() + "]"); @@ -259,7 +302,7 @@ private static void loadFile(Class service, String dir, ClassLoader classLoad java.net.URL url = urls.nextElement(); BufferedReader reader = null; try { - reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8")); + reader = new BufferedReader(new InputStreamReader(url.openStream(), Constants.DEFAULT_CHARSET)); String line = null; while ((line = reader.readLine()) != null) { final int ci = line.indexOf('#'); @@ -292,13 +335,26 @@ private static void loadFile(Class service, String dir, ClassLoader classLoad * @param the type parameter * @param service the service * @param implClazz the impl clazz - * @return s - * @throws IllegalAccessException the illegal access exception - * @throws InstantiationException the instantiation exception + * @param argTypes the arg types + * @param args the args + * @return s s + * @throws IllegalAccessException the illegal access exception + * @throws InstantiationException the instantiation exception + * @throws NoSuchMethodException the no such method exception + * @throws InvocationTargetException the invocation target exception */ - protected static S initInstance(Class service, Class implClazz) - throws IllegalAccessException, InstantiationException { - S s = service.cast(implClazz.newInstance()); + protected static S initInstance(Class service, Class implClazz, Class[] argTypes, Object[] args) + throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { + S s = null; + if(argTypes != null && args != null){ + // Constructor with arguments + Constructor constructor = implClazz.getDeclaredConstructor(argTypes); + constructor.setAccessible(true); + s = service.cast(constructor.newInstance(args)); + }else { + // default Constructor + s = service.cast(implClazz.newInstance()); + } if (s instanceof Initialize) { ((Initialize)s).init(); } diff --git a/common/src/main/java/io/seata/common/loader/LoadLevel.java b/common/src/main/java/io/seata/common/loader/LoadLevel.java index b01ebf76c74..b887ed509b0 100644 --- a/common/src/main/java/io/seata/common/loader/LoadLevel.java +++ b/common/src/main/java/io/seata/common/loader/LoadLevel.java @@ -43,5 +43,5 @@ * * @return the int */ - int order(); + int order() default 0; } diff --git a/common/src/main/java/io/seata/common/util/BlobUtils.java b/common/src/main/java/io/seata/common/util/BlobUtils.java index 3eb62aa0c28..60ddc7eaabc 100644 --- a/common/src/main/java/io/seata/common/util/BlobUtils.java +++ b/common/src/main/java/io/seata/common/util/BlobUtils.java @@ -15,19 +15,18 @@ */ package io.seata.common.util; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.sql.Blob; import javax.sql.rowset.serial.SerialBlob; -import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.Constants; import io.seata.common.exception.ShouldNeverHappenException; /** * The type Blob utils. * * @author jimin.jm @alibaba-inc.com + * @author Geng Zhang */ public class BlobUtils { @@ -47,7 +46,7 @@ public static Blob string2blob(String str) { } try { - return new SerialBlob(str.getBytes()); + return new SerialBlob(str.getBytes(Constants.DEFAULT_CHARSET)); } catch (Exception e) { throw new ShouldNeverHappenException(e); } @@ -65,26 +64,43 @@ public static String blob2string(Blob blob) { } try { - return new String(blob.getBytes((long)1, (int)blob.length())); + return new String(blob.getBytes((long) 1, (int) blob.length()), Constants.DEFAULT_CHARSET); } catch (Exception e) { throw new ShouldNeverHappenException(e); } } /** - * Input stream 2 string string. + * Byte array to blob * - * @param is the is - * @return the string + * @param bytes the byte array + * @return the blob + */ + public static Blob bytes2Blob(byte[] bytes) { + if (bytes == null) { + return null; + } + + try { + return new SerialBlob(bytes); + } catch (Exception e) { + throw new ShouldNeverHappenException(e); + } + } + + /** + * Blob to byte array. + * + * @param blob the blob + * @return the byte array */ - public static String inputStream2String(InputStream is) { + public static byte[] blob2Bytes(Blob blob) { + if (blob == null) { + return null; + } + try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int i = -1; - while ((i = is.read()) != -1) { - baos.write(i); - } - return baos.toString(); + return blob.getBytes((long) 1, (int) blob.length()); } catch (Exception e) { throw new ShouldNeverHappenException(e); } diff --git a/common/src/main/java/io/seata/common/util/CollectionUtils.java b/common/src/main/java/io/seata/common/util/CollectionUtils.java index 76126fc4cf4..d56b80eb1ec 100644 --- a/common/src/main/java/io/seata/common/util/CollectionUtils.java +++ b/common/src/main/java/io/seata/common/util/CollectionUtils.java @@ -16,6 +16,7 @@ package io.seata.common.util; import java.util.Collection; +import java.util.Iterator; /** * The type Collection utils. @@ -45,6 +46,49 @@ public static boolean isNotEmpty(Collection col){ return col != null && col.size() > 0; } + /** + * Is empty boolean. + * + * @param array the array + * @return the boolean + */ + public static boolean isEmpty(Object[] array){ + return !isNotEmpty(array); + } + + /** + * Is not empty boolean. + * + * @param array the array + * @return the boolean + */ + public static boolean isNotEmpty(Object[] array){ + return array != null && array.length > 0; + } + + /** + * To string string. + * + * @param col the col + * @return the string + */ + public static String toString(Collection col){ + if(isEmpty(col)){ + return ""; + } + StringBuffer sb = new StringBuffer(); + sb.append("["); + Iterator it = col.iterator(); + while (it.hasNext()){ + Object obj = it.next(); + sb.append(StringUtils.toString(obj)); + sb.append(","); + } + sb.deleteCharAt(sb.length() - 1); + sb.append("]"); + return sb.toString(); + } + /** * Is size equals boolean. * diff --git a/common/src/main/java/io/seata/common/util/DurationUtil.java b/common/src/main/java/io/seata/common/util/DurationUtil.java new file mode 100644 index 00000000000..567fc85e3f5 --- /dev/null +++ b/common/src/main/java/io/seata/common/util/DurationUtil.java @@ -0,0 +1,74 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.common.util; + +import java.time.Duration; + +/** + * @author XCXCXCXCX + */ +public class DurationUtil { + + public static final Duration DEFAULT_DURATION = Duration.ofMillis(-1); + + public static final String DAY_UNIT = "d"; + public static final String HOUR_UNIT = "h"; + public static final String MINIUTE_UNIT = "m"; + public static final String SECOND_UNIT = "s"; + public static final String MILLIS_SECOND_UNIT = "ms"; + + public static Duration parse(String str) { + if(StringUtils.isBlank(str)){ + return DEFAULT_DURATION; + } + + if (str.contains(MILLIS_SECOND_UNIT)) { + Long value = doParse(MILLIS_SECOND_UNIT, str); + return value == null ? null : Duration.ofMillis(value); + } else if (str.contains(DAY_UNIT)) { + Long value = doParse(DAY_UNIT, str); + return value == null ? null : Duration.ofDays(value); + } else if (str.contains(HOUR_UNIT)) { + Long value = doParse(HOUR_UNIT, str); + return value == null ? null : Duration.ofHours(value); + } else if (str.contains(MINIUTE_UNIT)) { + Long value = doParse(MINIUTE_UNIT, str); + return value == null ? null : Duration.ofMinutes(value); + } else if (str.contains(SECOND_UNIT)) { + Long value = doParse(SECOND_UNIT, str); + return value == null ? null : Duration.ofSeconds(value); + } + try { + int millis = Integer.parseInt(str); + return Duration.ofMillis(millis); + }catch (Exception e){ + throw new UnsupportedOperationException(str + " can't parse to duration", e); + } + } + + private static Long doParse(String unit, String str) { + str = str.replace(unit, ""); + if ("".equals(str)) { + return null; + } + try { + return Long.parseLong(str); + } catch (NumberFormatException e) { + throw new UnsupportedOperationException("\"" + str + "\" can't parse to Duration", e); + } + } + +} diff --git a/common/src/main/java/io/seata/common/util/StringUtils.java b/common/src/main/java/io/seata/common/util/StringUtils.java index 217538aae17..e6a1714e78b 100644 --- a/common/src/main/java/io/seata/common/util/StringUtils.java +++ b/common/src/main/java/io/seata/common/util/StringUtils.java @@ -15,19 +15,17 @@ */ package io.seata.common.util; +import io.seata.common.Constants; +import io.seata.common.exception.ShouldNeverHappenException; + import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; -import java.sql.Blob; -import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.Map; -import javax.sql.rowset.serial.SerialBlob; - /** * The type String utils. * @@ -37,7 +35,6 @@ public class StringUtils { private StringUtils() { - } /** @@ -54,7 +51,7 @@ public static boolean isNullOrEmpty(String str) { * Is blank string ? * * @param str the str - * @return boolean + * @return boolean boolean */ public static boolean isBlank(String str) { int length; @@ -74,7 +71,7 @@ public static boolean isBlank(String str) { * Is Not blank string ? * * @param str the str - * @return boolean + * @return boolean boolean */ public static boolean isNotBlank(String str) { int length; @@ -91,56 +88,83 @@ public static boolean isNotBlank(String str) { return false; } + /** + * Equals boolean. + * + * @param a the a + * @param b the b + * @return boolean + */ + public static boolean equals(String a, String b) { + if (a == null) { + return b == null; + } + return a.equals(b); + } + /** - * String 2 blob blob. + * Equals ignore case boolean. * - * @param str the str - * @return the blob - * @throws SQLException the sql exception + * @param a the a + * @param b the b + * @return the boolean */ - public static Blob string2blob(String str) throws SQLException { - if (str == null) { - return null; + public static boolean equalsIgnoreCase(String a, String b) { + if (a == null) { + return b == null; } - return new SerialBlob(str.getBytes()); + return a.equalsIgnoreCase(b); } /** - * Blob 2 string string. + * Input stream 2 string string. * - * @param blob the blob + * @param is the is * @return the string - * @throws SQLException the sql exception */ - public static String blob2string(Blob blob) throws SQLException { - if (blob == null) { + public static String inputStream2String(InputStream is) { + if (is == null) { return null; } - - return new String(blob.getBytes((long)1, (int)blob.length())); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int i = -1; + while ((i = is.read()) != -1) { + baos.write(i); + } + return baos.toString(Constants.DEFAULT_CHARSET_NAME); + } catch (Exception e) { + throw new ShouldNeverHappenException(e); + } } /** - * Input stream 2 string string. + * Input stream to byte array * * @param is the is - * @return the string - * @throws IOException the io exception + * @return the byte array */ - public static String inputStream2String(InputStream is) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int i = -1; - while ((i = is.read()) != -1) { - baos.write(i); + public static byte[] inputStream2Bytes(InputStream is) { + if (is == null) { + return null; + } + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int i = -1; + while ((i = is.read()) != -1) { + baos.write(i); + } + return baos.toByteArray(); + } catch (Exception e) { + throw new ShouldNeverHappenException(e); } - return baos.toString(); } /** * Object.toString() * * @param obj the obj - * @return string + * @return string string */ public static String toString(Object obj){ if (obj == null){ @@ -197,32 +221,4 @@ public static String toString(Object obj){ } return sb.toString(); } - - /** - * Equals boolean. - * - * @param a the a - * @param b the b - * @return boolean - */ - public static boolean equals(String a, String b) { - if (a == null) { - return b == null; - } - return a.equals(b); - } - - /** - * Equals ignore case boolean. - * - * @param a the a - * @param b the b - * @return the boolean - */ - public static boolean equalsIgnoreCase(String a, String b) { - if (a == null) { - return b == null; - } - return a.equalsIgnoreCase(b); - } } diff --git a/common/src/test/java/io/seata/common/util/BlobUtilsTest.java b/common/src/test/java/io/seata/common/util/BlobUtilsTest.java index 53a0a6217ae..f643ad49caa 100644 --- a/common/src/test/java/io/seata/common/util/BlobUtilsTest.java +++ b/common/src/test/java/io/seata/common/util/BlobUtilsTest.java @@ -15,21 +15,22 @@ */ package io.seata.common.util; -import java.io.InputStream; -import java.nio.charset.Charset; +import java.io.UnsupportedEncodingException; import java.sql.SQLException; import javax.sql.rowset.serial.SerialBlob; -import org.junit.jupiter.api.Disabled; +import io.seata.common.Constants; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNull; /** * The type Blob utils test. * * @author Otis.z + * @author Geng Zhang * @date 2019 /2/26 */ public class BlobUtilsTest { @@ -41,8 +42,9 @@ public class BlobUtilsTest { */ @Test public void testString2blob() throws SQLException { + assertNull(BlobUtils.string2blob(null)); assertThat(BlobUtils.string2blob("123abc")).isEqualTo( - new SerialBlob("123abc".getBytes(Charset.forName("UTF-8")))); + new SerialBlob("123abc".getBytes(Constants.DEFAULT_CHARSET))); } /** @@ -52,19 +54,24 @@ public void testString2blob() throws SQLException { */ @Test public void testBlob2string() throws SQLException { - assertThat(BlobUtils.blob2string(new SerialBlob("123absent".getBytes(Charset.forName("UTF-8"))))).isEqualTo( + assertNull(BlobUtils.blob2string(null)); + assertThat(BlobUtils.blob2string(new SerialBlob("123absent".getBytes(Constants.DEFAULT_CHARSET)))).isEqualTo( "123absent"); } - /** - * Test input stream 2 string. - */ @Test - @Disabled - public void testInputStream2String() { - InputStream inputStream = BlobUtilsTest.class.getClassLoader().getResourceAsStream("test.txt"); - assertThat(BlobUtils.inputStream2String(inputStream)).isEqualTo("abc\n" - + ":\"klsdf\n" - + "2ks,x:\".,-3sd˚ø≤ø¬≥"); + void bytes2Blob() throws UnsupportedEncodingException, SQLException { + assertNull(BlobUtils.bytes2Blob(null)); + byte[] bs = "xxa哈哈dd".getBytes(Constants.DEFAULT_CHARSET_NAME); + assertThat(BlobUtils.bytes2Blob(bs)).isEqualTo( + new SerialBlob(bs)); + } + + @Test + void blob2Bytes() throws UnsupportedEncodingException, SQLException { + assertNull(BlobUtils.blob2Bytes(null)); + byte[] bs = "xxa哈哈dd".getBytes(Constants.DEFAULT_CHARSET_NAME); + assertThat(BlobUtils.blob2Bytes(new SerialBlob(bs))).isEqualTo( + bs); } } diff --git a/common/src/test/java/io/seata/common/util/StringUtilsTest.java b/common/src/test/java/io/seata/common/util/StringUtilsTest.java index 1eae80462bf..c816c0358cb 100644 --- a/common/src/test/java/io/seata/common/util/StringUtilsTest.java +++ b/common/src/test/java/io/seata/common/util/StringUtilsTest.java @@ -15,17 +15,15 @@ */ package io.seata.common.util; +import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; -import java.sql.SQLException; - -import javax.sql.rowset.serial.SerialBlob; +import io.seata.common.Constants; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNull; /** * The type String utils test. @@ -48,43 +46,25 @@ public void testIsNullOrEmpty() { assertThat(StringUtils.isNullOrEmpty(" ")).isFalse(); } - /** - * Test string 2 blob. - * - * @throws SQLException the sql exception - */ @Test - public void testString2blob() throws SQLException { - assertThat(StringUtils.string2blob(null)).isNull(); - String[] strs = new String[] {"abc", "", " "}; - for (String str : strs) { - assertThat(StringUtils.string2blob(str)).isEqualTo(new SerialBlob(str.getBytes())); - } - } - - /** - * Test blob 2 string. - * - * @throws SQLException the sql exception - */ - @Test - public void testBlob2string() throws SQLException { - String[] strs = new String[] {"abc", " "}; - for (String str : strs) { - assertThat(StringUtils.blob2string(new SerialBlob(str.getBytes()))).isEqualTo(str); - - } + public void testInputStream2String() throws IOException { + assertNull(StringUtils.inputStream2String(null)); + String data = "abc\n" + + ":\"klsdf\n" + + "2ks,x:\".,-3sd˚ø≤ø¬≥"; + ByteArrayInputStream inputStream = new ByteArrayInputStream(data.getBytes(Constants.DEFAULT_CHARSET)); + assertThat(StringUtils.inputStream2String(inputStream)).isEqualTo(data); } - /** - * Test input stream 2 string. - */ @Test - @Disabled - public void testInputStream2String() throws IOException { - InputStream inputStream = StringUtilsTest.class.getClassLoader().getResourceAsStream("test.txt"); - assertThat(StringUtils.inputStream2String(inputStream)) - .isEqualTo("abc\n" + ":\"klsdf\n" + "2ks,x:\".,-3sd˚ø≤ø¬≥"); + void inputStream2Bytes() { + assertNull(StringUtils.inputStream2Bytes(null)); + String data = "abc\n" + + ":\"klsdf\n" + + "2ks,x:\".,-3sd˚ø≤ø¬≥"; + byte[] bs = data.getBytes(Constants.DEFAULT_CHARSET); + ByteArrayInputStream inputStream = new ByteArrayInputStream(data.getBytes(Constants.DEFAULT_CHARSET)); + assertThat(StringUtils.inputStream2Bytes(inputStream)).isEqualTo(bs); } @Test diff --git a/config/pom.xml b/config/pom.xml index cfdf735708d..36b384ebda6 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -32,6 +32,7 @@ seata-config-nacos seata-config-zk seata-config-all + seata-config-etcd3 seata-config-consul diff --git a/config/seata-config-all/pom.xml b/config/seata-config-all/pom.xml index 3cf62928e1b..46da42a13db 100644 --- a/config/seata-config-all/pom.xml +++ b/config/seata-config-all/pom.xml @@ -41,6 +41,11 @@ seata-config-nacos ${project.version} + + ${project.groupId} + seata-config-etcd3 + ${project.version} + ${project.groupId} seata-config-consul diff --git a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java index 7cd509eccdd..0092f4f36ac 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java @@ -15,6 +15,11 @@ */ package io.seata.config; + +import io.seata.common.util.DurationUtil; + +import java.time.Duration; + /** * The type Abstract configuration. * @@ -61,6 +66,22 @@ public long getLong(String dataId) { return getLong(dataId, 0L); } + @Override + public Duration getDuration(String dataId) { + return getDuration(dataId, Duration.ZERO); + } + + @Override + public Duration getDuration(String dataId, Duration defaultValue) { + return getDuration(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + } + + @Override + public Duration getDuration(String dataId, Duration defaultValue, long timeoutMills) { + String result = getConfig(dataId, String.valueOf(defaultValue.toMillis() + "ms"), timeoutMills); + return DurationUtil.parse(result); + } + @Override public boolean getBoolean(String dataId, boolean defaultValue, long timeoutMills) { String result = getConfig(dataId, String.valueOf(defaultValue), timeoutMills); diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java index 866fddb8d67..6f8cf55a4ed 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java @@ -41,7 +41,11 @@ public enum ConfigType { /** * Consul config type */ - Consul; + Consul, + /** + * Etcd3 config type + */ + Etcd3; /** * Gets type. diff --git a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java index bb3e1a7c18c..67ec8679191 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java @@ -15,6 +15,7 @@ */ package io.seata.config; +import java.time.Duration; import java.util.List; /** @@ -80,6 +81,33 @@ public interface Configuration { */ long getLong(String dataId); + /** + * Gets duration. + * + * @param dataId + * @return the duration + */ + Duration getDuration(String dataId); + + /** + * Gets duration. + * + * @param dataId + * @param defaultValue + * @return the duration + */ + Duration getDuration(String dataId, Duration defaultValue); + + /** + * Gets duration. + * + * @param dataId + * @param defaultValue + * @param timeoutMills + * @return he duration + */ + Duration getDuration(String dataId, Duration defaultValue, long timeoutMills); + /** * Gets boolean. * diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java index 0b802b3d344..cd5ea345d5c 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java @@ -17,8 +17,6 @@ import io.seata.common.exception.NotSupportYetException; import io.seata.common.loader.EnhancedServiceLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Objects; @@ -26,10 +24,9 @@ * The type Configuration factory. * * @author jimin.jm @alibaba-inc.com - * @date 2018 /12/24 + * @author Geng Zhang */ public final class ConfigurationFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationFactory.class); private static final String REGISTRY_CONF = "registry.conf"; /** * The constant FILE_INSTANCE. @@ -38,20 +35,33 @@ public final class ConfigurationFactory { private static final String NAME_KEY = "name"; private static final String FILE_TYPE = "file"; + private static volatile Configuration CONFIG_INSTANCE = null; + /** * Gets instance. * * @return the instance */ public static Configuration getInstance() { + if (CONFIG_INSTANCE == null) { + synchronized (Configuration.class) { + if (CONFIG_INSTANCE == null) { + CONFIG_INSTANCE = buildConfiguration(); + } + } + } + return CONFIG_INSTANCE; + } + + private static Configuration buildConfiguration() { ConfigType configType = null; String configTypeName = null; try { configTypeName = FILE_INSTANCE.getConfig(ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + ConfigurationKeys.FILE_ROOT_TYPE); configType = ConfigType.getType(configTypeName); - } catch (Exception exx) { - throw new NotSupportYetException("not support register type: " + configTypeName); + } catch (Exception e) { + throw new NotSupportYetException("not support register type: " + configTypeName, e); } if (ConfigType.File == configType) { String pathDataId = ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR diff --git a/config/seata-config-core/src/main/resources/file.conf b/config/seata-config-core/src/main/resources/file.conf index dc09514d367..a166f8d5c5c 100644 --- a/config/seata-config-core/src/main/resources/file.conf +++ b/config/seata-config-core/src/main/resources/file.conf @@ -69,4 +69,8 @@ client { retry.times = 30 } report.retry.count = 5 -} \ No newline at end of file +} + +transaction { + undo.data.validation = true +} diff --git a/config/seata-config-core/src/main/resources/registry.conf b/config/seata-config-core/src/main/resources/registry.conf index 1d6c3598256..5115876d916 100644 --- a/config/seata-config-core/src/main/resources/registry.conf +++ b/config/seata-config-core/src/main/resources/registry.conf @@ -45,7 +45,7 @@ registry { } config { - # file、nacos 、apollo、zk、consul + # file、nacos 、apollo、zk、consul、etcd3 type = "file" nacos { @@ -65,6 +65,9 @@ config { session.timeout = 6000 connect.timeout = 2000 } + etcd3 { + serverAddr = "http://localhost:2379" + } file { name = "file.conf" } diff --git a/config/seata-config-etcd3/pom.xml b/config/seata-config-etcd3/pom.xml new file mode 100644 index 00000000000..beb590dfffe --- /dev/null +++ b/config/seata-config-etcd3/pom.xml @@ -0,0 +1,49 @@ + + + + + io.seata + seata-config + ${revision} + + 4.0.0 + seata-config-etcd3 + seata-config-etcd3 ${project.version} + + + + io.seata + seata-config-core + ${project.parent.version} + + + io.etcd + jetcd-core + + + com.google.guava + guava + + + + + com.google.guava + guava + + + diff --git a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java new file mode 100644 index 00000000000..6eed7d53035 --- /dev/null +++ b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java @@ -0,0 +1,318 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.config.etcd; + +import io.etcd.jetcd.ByteSequence; +import io.etcd.jetcd.Client; +import io.etcd.jetcd.KeyValue; +import io.etcd.jetcd.Watch; +import io.etcd.jetcd.kv.DeleteResponse; +import io.etcd.jetcd.kv.GetResponse; +import io.etcd.jetcd.kv.PutResponse; +import io.etcd.jetcd.kv.TxnResponse; +import io.etcd.jetcd.op.Cmp; +import io.etcd.jetcd.op.CmpTarget; +import io.etcd.jetcd.op.Op; +import io.etcd.jetcd.options.PutOption; +import io.etcd.jetcd.watch.WatchResponse; +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.thread.NamedThreadFactory; +import io.seata.common.util.CollectionUtils; +import io.seata.config.AbstractConfiguration; +import io.seata.config.ConfigChangeListener; +import io.seata.config.ConfigFuture; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static io.netty.util.CharsetUtil.UTF_8; +import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; +import static io.seata.config.ConfigurationKeys.FILE_ROOT_CONFIG; + +/** + * @author xingfudeshi@gmail.com + * @date 2019/05/10 + */ +public class EtcdConfiguration extends AbstractConfiguration { + private static final Logger LOGGER = LoggerFactory.getLogger(EtcdConfiguration.class); + private static volatile EtcdConfiguration instance; + private static volatile Client client; + + private static final Configuration FILE_CONFIG = ConfigurationFactory.FILE_INSTANCE; + private static final String SERVER_ADDR_KEY = "serverAddr"; + private static final String CONFIG_TYPE = "etcd3"; + private static final String FILE_CONFIG_KEY_PREFIX = FILE_ROOT_CONFIG + FILE_CONFIG_SPLIT_CHAR + CONFIG_TYPE + FILE_CONFIG_SPLIT_CHAR; + private static final int THREAD_POOL_NUM = 1; + private static final int MAP_INITIAL_CAPACITY = 8; + private static ExecutorService etcdConfigExecutor = null; + private static ExecutorService etcdNotifierExecutor = null; + private static ConcurrentMap> configListenersMap = null; + private static ConcurrentHashMap> configChangeNotifiersMap = null; + + private static final long VERSION_NOT_EXIST = 0; + + private EtcdConfiguration() { + } + + /** + * get instance + * + * @return + */ + public static EtcdConfiguration getInstance() { + if (null == instance) { + synchronized (EtcdConfiguration.class) { + if (null == instance) { + etcdConfigExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM, + Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("etcd-config-executor", THREAD_POOL_NUM)); + etcdNotifierExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM, + Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("etcd-config-notifier-executor", THREAD_POOL_NUM)); + configListenersMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); + configChangeNotifiersMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); + instance = new EtcdConfiguration(); + } + } + } + return instance; + } + + + @Override + public String getTypeName() { + return CONFIG_TYPE; + } + + @Override + public String getConfig(String dataId, String defaultValue, long timeoutMills) { + ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigFuture.ConfigOperation.GET, timeoutMills); + etcdConfigExecutor.execute(() -> { + complete(getClient().getKVClient().get(ByteSequence.from(dataId, UTF_8)), configFuture); + }); + return (String) configFuture.get(); + } + + @Override + public boolean putConfig(String dataId, String content, long timeoutMills) { + ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigFuture.ConfigOperation.PUT, timeoutMills); + etcdConfigExecutor.execute(() -> { + complete(getClient().getKVClient().put(ByteSequence.from(dataId, UTF_8), ByteSequence.from(content, UTF_8)), configFuture); + }); + return (Boolean) configFuture.get(); + } + + @Override + public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) { + ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigFuture.ConfigOperation.PUTIFABSENT, timeoutMills); + etcdConfigExecutor.execute(() -> { + //use etcd transaction to ensure the atomic operation + complete(client.getKVClient().txn() + //whether the key exists + .If(new Cmp(ByteSequence.from(dataId, UTF_8), Cmp.Op.EQUAL, CmpTarget.version(VERSION_NOT_EXIST))) + //not exist,then will create + .Then(Op.put(ByteSequence.from(dataId, UTF_8), ByteSequence.from(content, UTF_8), PutOption.DEFAULT)) + .commit(), configFuture); + }); + return (Boolean) configFuture.get(); + } + + @Override + public boolean removeConfig(String dataId, long timeoutMills) { + ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigFuture.ConfigOperation.REMOVE, timeoutMills); + etcdConfigExecutor.execute(() -> { + complete(getClient().getKVClient().delete(ByteSequence.from(dataId, UTF_8)), configFuture); + }); + return (Boolean) configFuture.get(); + } + + @Override + public void addConfigListener(String dataId, ConfigChangeListener listener) { + configListenersMap.putIfAbsent(dataId, new ArrayList<>()); + configChangeNotifiersMap.putIfAbsent(dataId, new ArrayList<>()); + ConfigChangeNotifier configChangeNotifier = new ConfigChangeNotifier(dataId, listener); + configChangeNotifiersMap.get(dataId).add(configChangeNotifier); + if (null != listener.getExecutor()) { + listener.getExecutor().submit(configChangeNotifier); + } else { + etcdNotifierExecutor.submit(configChangeNotifier); + } + } + + @Override + public void removeConfigListener(String dataId, ConfigChangeListener listener) { + List configChangeListeners = getConfigListeners(dataId); + if (configChangeListeners == null) { + return; + } + List newChangeListenerList = new ArrayList<>(); + for (ConfigChangeListener changeListener : configChangeListeners) { + if (!changeListener.equals(listener)) { + newChangeListenerList.add(changeListener); + } + } + configListenersMap.put(dataId, newChangeListenerList); + if (null != listener.getExecutor()) { + listener.getExecutor().shutdownNow(); + } + //remove and stop the configChangeNotifier + List configChangeNotifiers = configChangeNotifiersMap.get(dataId); + List newConfigChangeNotifiers = new ArrayList<>(); + for (ConfigChangeNotifier configChangeNotifier : configChangeNotifiers) { + if (!listener.equals(configChangeNotifier.getListener())) { + newConfigChangeNotifiers.add(configChangeNotifier); + } else { + configChangeNotifier.stop(); + } + } + configChangeNotifiersMap.put(dataId, newConfigChangeNotifiers); + } + + @Override + public List getConfigListeners(String dataId) { + return configListenersMap.get(dataId); + } + + /** + * get client + * + * @return client + */ + private static Client getClient() { + if (null == client) { + synchronized (EtcdConfiguration.class) { + if (null == client) { + client = Client.builder().endpoints(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)).build(); + } + } + } + return client; + } + + /** + * complete the future + * + * @param completableFuture + * @param configFuture + * @param + */ + private void complete(CompletableFuture completableFuture, ConfigFuture configFuture) { + try { + T response = completableFuture.get(); + if (response instanceof GetResponse) { + List keyValues = ((GetResponse) response).getKvs(); + if (CollectionUtils.isNotEmpty(keyValues)) { + ByteSequence value = keyValues.get(0).getValue(); + if (null != value) { + configFuture.setResult(value.toString(UTF_8)); + } + } + } else if (response instanceof PutResponse) { + configFuture.setResult(Boolean.TRUE); + } else if (response instanceof TxnResponse) { + boolean result = ((TxnResponse) response).isSucceeded(); + //create key if file does not exist) + if (result) { + configFuture.setResult(Boolean.TRUE); + } + } else if (response instanceof DeleteResponse) { + configFuture.setResult(Boolean.TRUE); + } else { + throw new ShouldNeverHappenException("unsupported response type"); + } + } catch (Exception e) { + LOGGER.error("error occurred while completing the future{}", e.getMessage()); + } + } + + /** + * the type config change notifier + */ + private static class ConfigChangeNotifier implements Runnable { + private final String dataId; + private final ConfigChangeListener listener; + private Watch.Watcher watcher; + + ConfigChangeNotifier(String dataId, ConfigChangeListener listener) { + this.dataId = dataId; + this.listener = listener; + } + + /** + * get the listener + * + * @return ConfigChangeListener + */ + ConfigChangeListener getListener() { + return this.listener; + } + + @Override + public void run() { + Watch watchClient = getClient().getWatchClient(); + watcher = watchClient.watch(ByteSequence.from(dataId, UTF_8), new Watch.Listener() { + @Override + public void onNext(WatchResponse response) { + notifyListeners(); + } + + @Override + public void onError(Throwable throwable) { + + } + + @Override + public void onCompleted() { + + } + }); + } + + /** + * notify listeners + */ + private void notifyListeners() { + try { + GetResponse getResponse = getClient().getKVClient().get(ByteSequence.from(dataId, UTF_8)).get(); + List keyValues = getResponse.getKvs(); + if (CollectionUtils.isNotEmpty(keyValues)) { + for (ConfigChangeListener listener : configListenersMap.get(this.dataId)) { + listener.receiveConfigInfo(keyValues.get(0).getValue().toString(UTF_8)); + } + } + } catch (Exception e) { + LOGGER.error("error occurred while getting value{}", e.getMessage()); + } + } + + + /** + * stop the notifier + */ + public void stop() { + this.watcher.close(); + } + } +} diff --git a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java new file mode 100644 index 00000000000..acb7e28db96 --- /dev/null +++ b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.config.etcd; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationProvider; + +/** + * @author xingfudeshi@gmail.com + * @date 2019/04/12 + */ +@LoadLevel(name = "Etcd3", order = 1) +public class EtcdConfigurationProvider implements ConfigurationProvider { + @Override + public Configuration provide() { + return EtcdConfiguration.getInstance(); + } +} diff --git a/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider new file mode 100644 index 00000000000..ce01ac19760 --- /dev/null +++ b/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider @@ -0,0 +1 @@ +io.seata.config.etcd.EtcdConfigurationProvider \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml index a6a71f8e60d..9670f9fd495 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -55,6 +55,17 @@ commons-pool commons-pool + + commons-dbcp + commons-dbcp + test + + + com.h2database + h2 + test + + diff --git a/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java b/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java index 4df7b3f11c6..dc6f93fef8c 100644 --- a/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java +++ b/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java @@ -92,4 +92,111 @@ public class ConfigurationKeys { * The constant CLIENT_REPORT_RETRY_COUNT. */ public static final String CLIENT_REPORT_RETRY_COUNT = CLIENT_PREFIX + "report.retry.count"; + + /** + * The constant STORE_DB_GLOBAL_TABLE. + */ + public static final String STORE_DB_GLOBAL_TABLE = "store.db.global.table"; + + /** + * The constant STORE_DB_BRANCH_TABLE. + */ + public static final String STORE_DB_BRANCH_TABLE = "store.db.branch.table"; + + /** + * The constant STORE_DB_GLOBAL_DEFAULT_TABLE. + */ + public static final String STORE_DB_GLOBAL_DEFAULT_TABLE = "global_table"; + + /** + * The constant STORE_DB_BRANCH_DEFAULT_TABLE. + */ + public static final String STORE_DB_BRANCH_DEFAULT_TABLE = "branch_table"; + + /** + * The constant STORE_DB_DATASOURCE_TYPE. + */ + public static final String STORE_DB_DATASOURCE_TYPE = "store.db.datasource"; + + + /** + * The constant STORE_DB_TYPE. + */ + public static final String STORE_DB_TYPE = "store.db.db-type"; + + /** + * The constant STORE_DB_URL. + */ + public static final String STORE_DB_URL = "store.db.url"; + + /** + * The constant STORE_DB_USER. + */ + public static final String STORE_DB_USER = "store.db.user"; + + /** + * The constant STORE_DB_PASSWORD. + */ + public static final String STORE_DB_PASSWORD = "store.db.password"; + + /** + * The constant STORE_DB_MIN_CONN. + */ + public static final String STORE_DB_MIN_CONN = "store.db.min-conn"; + + /** + * The constant STORE_DB_MAX_CONN. + */ + public static final String STORE_DB_MAX_CONN = "store.db.max-conn"; + + /** + * The constant STORE_DB_LOG_QUERY_LIMIT. + */ + public static final String STORE_DB_LOG_QUERY_LIMIT = "store.db.query-limit"; + + /** + * The constant LOCK_MODE. + */ + public static final String LOCK_MODE = "lock.mode"; + + /** + * The constant LOCK_DB_TABLE. + */ + public static final String LOCK_DB_TABLE = "lock.db.lock-table"; + + /** + * The constant LOCK_DB_DEFAULT_TABLE. + */ + public static final String LOCK_DB_DEFAULT_TABLE = "lock_table"; + + /** + * The constant COMMITING_RETRY_DELAY. + */ + public static final String COMMITING_RETRY_DELAY = "recovery.committing-retry-delay"; + + /** + * The constant ASYN_COMMITING_RETRY_DELAY. + */ + public static final String ASYN_COMMITING_RETRY_DELAY = "recovery.asyn-committing-retry-delay"; + + /** + * The constant ROLLBACKING_RETRY_DELAY. + */ + public static final String ROLLBACKING_RETRY_DELAY = "recovery.rollbacking-retry-delay"; + + /** + * The constant TIMEOUT_RETRY_DELAY. + */ + public static final String TIMEOUT_RETRY_DELAY = "recovery.timeout-retry-delay"; + + + /** + * The constant TRANSACTION_PREFIX. + */ + public static final String TRANSACTION_PREFIX = "transaction."; + + /** + * The constant RM_DATASOURCE_UNOD_VALIDATION. + */ + public static final String TRANSACTION_UNOD_DATA_VALIDATION = TRANSACTION_PREFIX + "undo.data.validation"; } diff --git a/core/src/main/java/io/seata/core/constants/DBType.java b/core/src/main/java/io/seata/core/constants/DBType.java new file mode 100644 index 00000000000..cdb0174b985 --- /dev/null +++ b/core/src/main/java/io/seata/core/constants/DBType.java @@ -0,0 +1,93 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.constants; + +import io.seata.common.util.StringUtils; + +/** + * database type + * + * @author zhangsen + * @data 2019 /4/2 + */ +public enum DBType { + + /** + * Mysql db type. + */ + MYSQL, + + /** + * Oracle db type. + */ + ORACLE, + + /** + * Db 2 db type. + */ + DB2, + + /** + * Sqlserver db type. + */ + SQLSERVER, + + /** + * Sybaee db type. + */ + SYBAEE, + + /** + * H2 db type. + */ + H2, + + /** + * Sqlite db type. + */ + SQLITE, + + /** + * Access db type. + */ + ACCESS, + + /** + * Postgresql db type. + */ + POSTGRESQL, + + /** + * Oceanbase db type. + */ + OCEANBASE; + + /** + * Valueof db type. + * + * @param dbType the db type + * @return the db type + */ + public static DBType valueof (String dbType){ + for(DBType dt : values()){ + if(StringUtils.equalsIgnoreCase(dt.name(),dbType)){ + return dt; + } + } + throw new IllegalArgumentException("unknown dbtype:" + dbType); + } + +} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java index 9aa741dd28d..a8501be705a 100644 --- a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java +++ b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java @@ -15,6 +15,8 @@ */ package io.seata.core.exception; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; import io.seata.core.protocol.ResultCode; import io.seata.core.protocol.transaction.AbstractTransactionRequest; import io.seata.core.protocol.transaction.AbstractTransactionResponse; @@ -26,6 +28,11 @@ */ public abstract class AbstractExceptionHandler { + /** + * The constant CONFIG. + */ + protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + /** * The interface Callback. * diff --git a/core/src/main/java/io/seata/core/lock/AbstractLocker.java b/core/src/main/java/io/seata/core/lock/AbstractLocker.java new file mode 100644 index 00000000000..ddb0dd073ef --- /dev/null +++ b/core/src/main/java/io/seata/core/lock/AbstractLocker.java @@ -0,0 +1,85 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.lock; + +import io.seata.common.util.CollectionUtils; +import io.seata.core.store.LockDO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type Abstract locker. + * + * @author zhangsen + * @data 2019 -05-15 + */ +public abstract class AbstractLocker implements Locker { + + /** + * The constant LOGGER. + */ + protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractLocker.class); + + /** + * The constant LOCK_SPLIT. + */ + protected static final String LOCK_SPLIT = "^^^"; + + /** + * Convert to lock do list. + * + * @param locks the locks + * @return the list + */ + protected List convertToLockDO(List locks){ + List lockDOs = new ArrayList<>(); + if(CollectionUtils.isEmpty(locks)){ + return lockDOs; + } + for(RowLock rowLock : locks){ + LockDO lockDO = new LockDO(); + lockDO.setBranchId(rowLock.getBranchId()); + lockDO.setPk(rowLock.getPk()); + lockDO.setResourceId(rowLock.getResourceId()); + lockDO.setRowKey(getRowKey(rowLock.getResourceId(), rowLock.getTableName(), rowLock.getPk())); + lockDO.setXid(rowLock.getXid()); + lockDO.setTransactionId(rowLock.getTransactionId()); + lockDO.setTableName(rowLock.getTableName()); + lockDOs.add(lockDO); + } + return lockDOs; + } + + /** + * Get row key string. + * + * @param resourceId the resource id + * @param tableName the table name + * @param pk the pk + * @return the string + */ + protected String getRowKey(String resourceId, String tableName, String pk){ + return new StringBuilder().append(resourceId).append(LOCK_SPLIT).append(tableName).append(LOCK_SPLIT).append(pk).toString(); + } + + @Override + public void cleanAllLocks() { + + } +} diff --git a/core/src/main/java/io/seata/core/lock/LocalDBLocker.java b/core/src/main/java/io/seata/core/lock/LocalDBLocker.java new file mode 100644 index 00000000000..c342e8f6ecf --- /dev/null +++ b/core/src/main/java/io/seata/core/lock/LocalDBLocker.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.lock; + +import java.util.List; + +/** + * The type Local db locker. + * + * @author zhangsen + * @data 2019 -05-15 + */ +public class LocalDBLocker extends AbstractLocker { + + @Override + public boolean acquireLock(List rowLock) { + return false; + } + + @Override + public boolean releaseLock(List rowLock) { + return false; + } + + @Override + public boolean isLockable(List rowLock) { + return false; + } +} diff --git a/core/src/main/java/io/seata/core/lock/LockMode.java b/core/src/main/java/io/seata/core/lock/LockMode.java new file mode 100644 index 00000000000..f1a11d0b9ea --- /dev/null +++ b/core/src/main/java/io/seata/core/lock/LockMode.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.lock; + +/** + * lock mode + * + * @author zhangsen + * @data 2019 /4/25 + */ +public enum LockMode { + + /** + * store the lock in memory of server + */ + MEMORY, + + /** + * store the lock in db of server + */ + DB; + + +} diff --git a/core/src/main/java/io/seata/core/lock/Locker.java b/core/src/main/java/io/seata/core/lock/Locker.java new file mode 100644 index 00000000000..8990699d317 --- /dev/null +++ b/core/src/main/java/io/seata/core/lock/Locker.java @@ -0,0 +1,59 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.lock; + +import java.util.List; + +/** + * The interface Locker. + * + * @author zhangsen + * @data 2019 -05-15 + */ +public interface Locker { + + /** + * Acquire lock boolean. + * + * @param rowLock the row lock + * @return the boolean + */ + boolean acquireLock(List rowLock) ; + + /** + * Un lock boolean. + * + * @param rowLock the row lock + * @return the boolean + */ + boolean releaseLock(List rowLock); + + /** + * Is lockable boolean. + * + * @param rowLock the row lock + * @return the boolean + */ + boolean isLockable(List rowLock); + + /** + * Clean all locks boolean. + * + * @return the boolean + */ + void cleanAllLocks(); +} + diff --git a/core/src/main/java/io/seata/core/lock/RowLock.java b/core/src/main/java/io/seata/core/lock/RowLock.java new file mode 100644 index 00000000000..9675cb9011d --- /dev/null +++ b/core/src/main/java/io/seata/core/lock/RowLock.java @@ -0,0 +1,193 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.lock; + +import io.seata.common.util.StringUtils; + +/** + * The type Row lock. + * + * @author zhangsen + * @data 2019 -05-15 + */ +public class RowLock { + + private String xid; + + private Long transactionId; + + private Long branchId; + + private String resourceId; + + private String tableName; + + private String pk; + + private String rowKey; + + private String feature; + + /** + * Gets xid. + * + * @return the xid + */ + public String getXid() { + return xid; + } + + /** + * Sets xid. + * + * @param xid the xid + */ + public void setXid(String xid) { + this.xid = xid; + } + + /** + * Gets transaction id. + * + * @return the transaction id + */ + public Long getTransactionId() { + return transactionId; + } + + /** + * Sets transaction id. + * + * @param transactionId the transaction id + */ + public void setTransactionId(Long transactionId) { + this.transactionId = transactionId; + } + + /** + * Gets branch id. + * + * @return the branch id + */ + public Long getBranchId() { + return branchId; + } + + /** + * Sets branch id. + * + * @param branchId the branch id + */ + public void setBranchId(Long branchId) { + this.branchId = branchId; + } + + /** + * Gets resource id. + * + * @return the resource id + */ + public String getResourceId() { + return resourceId; + } + + /** + * Sets resource id. + * + * @param resourceId the resource id + */ + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + /** + * Gets table name. + * + * @return the table name + */ + public String getTableName() { + return tableName; + } + + /** + * Sets table name. + * + * @param tableName the table name + */ + public void setTableName(String tableName) { + this.tableName = tableName; + } + + /** + * Gets pk. + * + * @return the pk + */ + public String getPk() { + return pk; + } + + /** + * Sets pk. + * + * @param pk the pk + */ + public void setPk(String pk) { + this.pk = pk; + } + + /** + * Gets row key. + * + * @return the row key + */ + public String getRowKey() { + return rowKey; + } + + /** + * Sets row key. + * + * @param rowKey the row key + */ + public void setRowKey(String rowKey) { + this.rowKey = rowKey; + } + + /** + * Gets feature. + * + * @return the feature + */ + public String getFeature() { + return feature; + } + + /** + * Sets feature. + * + * @param feature the feature + */ + public void setFeature(String feature) { + this.feature = feature; + } + + @Override + public String toString(){ + return StringUtils.toString(this); + } +} + diff --git a/core/src/main/java/io/seata/core/protocol/AbstractMessage.java b/core/src/main/java/io/seata/core/protocol/AbstractMessage.java index e6f3dd07e09..60ec91b978d 100644 --- a/core/src/main/java/io/seata/core/protocol/AbstractMessage.java +++ b/core/src/main/java/io/seata/core/protocol/AbstractMessage.java @@ -18,6 +18,7 @@ import java.io.Serializable; import java.nio.charset.Charset; +import io.seata.common.Constants; import io.seata.core.protocol.transaction.BranchCommitRequest; import io.seata.core.protocol.transaction.BranchCommitResponse; import io.seata.core.protocol.transaction.BranchRegisterRequest; @@ -152,7 +153,7 @@ public abstract class AbstractMessage implements MessageCodec, Serializable { /** * The constant UTF8. */ - protected static final Charset UTF8 = Charset.forName("utf-8"); + protected static final Charset UTF8 = Constants.DEFAULT_CHARSET; /** * The Ctx. */ diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java index 3f5a40470e7..de8dcf726bd 100644 --- a/core/src/main/java/io/seata/core/protocol/Version.java +++ b/core/src/main/java/io/seata/core/protocol/Version.java @@ -31,7 +31,7 @@ public class Version { /** * The constant CURRENT. */ - public static final String CURRENT = "0.5.2"; + public static final String CURRENT = "0.6.0"; /** * The constant VERSION_MAP. diff --git a/core/src/main/java/io/seata/core/rpc/ChannelManager.java b/core/src/main/java/io/seata/core/rpc/ChannelManager.java index d63086ea251..9de2904e93e 100644 --- a/core/src/main/java/io/seata/core/rpc/ChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/ChannelManager.java @@ -29,7 +29,6 @@ import io.seata.core.protocol.RegisterRMRequest; import io.seata.core.protocol.RegisterTMRequest; import io.seata.core.protocol.Version; -import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; import io.netty.channel.Channel; import io.seata.core.rpc.netty.NettyPoolKey; diff --git a/core/src/main/java/io/seata/core/rpc/RpcContext.java b/core/src/main/java/io/seata/core/rpc/RpcContext.java index b605b72d067..6ba531eb16a 100644 --- a/core/src/main/java/io/seata/core/rpc/RpcContext.java +++ b/core/src/main/java/io/seata/core/rpc/RpcContext.java @@ -23,7 +23,6 @@ import java.util.concurrent.ConcurrentMap; import io.seata.common.Constants; -import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; import io.netty.channel.Channel; import io.seata.core.rpc.netty.NettyPoolKey; diff --git a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java b/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java index 44c33d31fdf..d5bf8625ca7 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java +++ b/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java @@ -35,12 +35,7 @@ import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.FrameworkException; import io.seata.common.thread.NamedThreadFactory; -import io.seata.core.protocol.HeartbeatMessage; -import io.seata.core.protocol.MergeMessage; -import io.seata.core.protocol.MessageFuture; -import io.seata.core.protocol.RpcMessage; -import io.seata.core.rpc.Disposable; import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelFuture; diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java index 2ae97ced878..24c7a0f7c51 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java @@ -15,8 +15,6 @@ */ package io.seata.core.rpc.netty; -import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; - import io.netty.channel.Channel; /** diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java b/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java index db29b780465..9d69006f9fb 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java @@ -21,7 +21,6 @@ import io.seata.common.util.NetUtil; import io.seata.core.protocol.RegisterRMResponse; import io.seata.core.protocol.RegisterTMResponse; -import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; import io.netty.channel.Channel; import org.apache.commons.pool.KeyedPoolableObjectFactory; diff --git a/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java b/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java index d078a4df0da..ef0afc75f63 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java @@ -15,8 +15,6 @@ */ package io.seata.core.rpc.netty; -import io.seata.core.protocol.RegisterRMRequest; -import io.seata.core.protocol.RegisterTMRequest; import io.seata.core.protocol.RegisterRMRequest; import io.seata.core.protocol.RegisterTMRequest; diff --git a/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java b/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java index 42a9eedbac5..98ba76fad03 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java @@ -15,8 +15,6 @@ */ package io.seata.core.rpc.netty; -import io.seata.core.protocol.AbstractMessage; - import io.netty.channel.Channel; import io.seata.core.protocol.AbstractMessage; diff --git a/core/src/main/java/io/seata/core/store/BranchTransactionDO.java b/core/src/main/java/io/seata/core/store/BranchTransactionDO.java new file mode 100644 index 00000000000..63c784daf6c --- /dev/null +++ b/core/src/main/java/io/seata/core/store/BranchTransactionDO.java @@ -0,0 +1,277 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store; + + +import io.seata.common.util.StringUtils; +import io.seata.core.model.BranchStatus; + +import java.util.Date; + +/** + * branch transaction data object + * + * @author zhangsen + * @data 2019 /3/26 + */ +public class BranchTransactionDO { + + private String xid; + + private long transactionId; + + private long branchId; + + private String resourceGroupId; + + private String resourceId; + + private String lockKey; + + private String branchType; + + private int status = BranchStatus.Unknown.getCode(); + + private String clientId; + + private String applicationData; + + private Date gmtCreate; + + private Date gmtModified; + + /** + * Gets xid. + * + * @return the xid + */ + public String getXid() { + return xid; + } + + /** + * Sets xid. + * + * @param xid the xid + */ + public void setXid(String xid) { + this.xid = xid; + } + + /** + * Gets transaction id. + * + * @return the transaction id + */ + public long getTransactionId() { + return transactionId; + } + + /** + * Sets transaction id. + * + * @param transactionId the transaction id + */ + public void setTransactionId(long transactionId) { + this.transactionId = transactionId; + } + + /** + * Gets branch id. + * + * @return the branch id + */ + public long getBranchId() { + return branchId; + } + + /** + * Sets branch id. + * + * @param branchId the branch id + */ + public void setBranchId(long branchId) { + this.branchId = branchId; + } + + /** + * Gets resource group id. + * + * @return the resource group id + */ + public String getResourceGroupId() { + return resourceGroupId; + } + + /** + * Sets resource group id. + * + * @param resourceGroupId the resource group id + */ + public void setResourceGroupId(String resourceGroupId) { + this.resourceGroupId = resourceGroupId; + } + + /** + * Gets resource id. + * + * @return the resource id + */ + public String getResourceId() { + return resourceId; + } + + /** + * Sets resource id. + * + * @param resourceId the resource id + */ + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + /** + * Gets lock key. + * + * @return the lock key + */ + public String getLockKey() { + return lockKey; + } + + /** + * Sets lock key. + * + * @param lockKey the lock key + */ + public void setLockKey(String lockKey) { + this.lockKey = lockKey; + } + + /** + * Gets branch type. + * + * @return the branch type + */ + public String getBranchType() { + return branchType; + } + + /** + * Sets branch type. + * + * @param branchType the branch type + */ + public void setBranchType(String branchType) { + this.branchType = branchType; + } + + /** + * Gets status. + * + * @return the status + */ + public int getStatus() { + return status; + } + + /** + * Sets status. + * + * @param status the status + */ + public void setStatus(int status) { + this.status = status; + } + + /** + * Gets client id. + * + * @return the client id + */ + public String getClientId() { + return clientId; + } + + /** + * Sets client id. + * + * @param clientId the client id + */ + public void setClientId(String clientId) { + this.clientId = clientId; + } + + /** + * Gets application data. + * + * @return the application data + */ + public String getApplicationData() { + return applicationData; + } + + /** + * Sets application data. + * + * @param applicationData the application data + */ + public void setApplicationData(String applicationData) { + this.applicationData = applicationData; + } + + /** + * Gets gmt create. + * + * @return the gmt create + */ + public Date getGmtCreate() { + return gmtCreate; + } + + /** + * Sets gmt create. + * + * @param gmtCreate the gmt create + */ + public void setGmtCreate(Date gmtCreate) { + this.gmtCreate = gmtCreate; + } + + /** + * Gets gmt modified. + * + * @return the gmt modified + */ + public Date getGmtModified() { + return gmtModified; + } + + /** + * Sets gmt modified. + * + * @param gmtModified the gmt modified + */ + public void setGmtModified(Date gmtModified) { + this.gmtModified = gmtModified; + } + + @Override + public String toString(){ + return StringUtils.toString(this); + } + +} diff --git a/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java b/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java new file mode 100644 index 00000000000..74c5e9ae13f --- /dev/null +++ b/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java @@ -0,0 +1,256 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store; + + +import io.seata.common.util.StringUtils; + +import java.util.Date; + +/** + * Global Transaction data object + * + * @author zhangsen + * @data 2019 /3/26 + */ +public class GlobalTransactionDO { + + private String xid; + + private long transactionId; + + private int status; + + private String applicationId; + + private String transactionServiceGroup; + + private String transactionName; + + private int timeout; + + private long beginTime; + + private String applicationData; + + private Date gmtCreate; + + private Date gmtModified; + + /** + * Gets xid. + * + * @return the xid + */ + public String getXid() { + return xid; + } + + /** + * Sets xid. + * + * @param xid the xid + */ + public void setXid(String xid) { + this.xid = xid; + } + + /** + * Gets status. + * + * @return the status + */ + public int getStatus() { + return status; + } + + /** + * Sets status. + * + * @param status the status + */ + public void setStatus(int status) { + this.status = status; + } + + /** + * Gets application id. + * + * @return the application id + */ + public String getApplicationId() { + return applicationId; + } + + /** + * Sets application id. + * + * @param applicationId the application id + */ + public void setApplicationId(String applicationId) { + this.applicationId = applicationId; + } + + /** + * Gets transaction service group. + * + * @return the transaction service group + */ + public String getTransactionServiceGroup() { + return transactionServiceGroup; + } + + /** + * Sets transaction service group. + * + * @param transactionServiceGroup the transaction service group + */ + public void setTransactionServiceGroup(String transactionServiceGroup) { + this.transactionServiceGroup = transactionServiceGroup; + } + + /** + * Gets transaction name. + * + * @return the transaction name + */ + public String getTransactionName() { + return transactionName; + } + + /** + * Sets transaction name. + * + * @param transactionName the transaction name + */ + public void setTransactionName(String transactionName) { + this.transactionName = transactionName; + } + + /** + * Gets timeout. + * + * @return the timeout + */ + public int getTimeout() { + return timeout; + } + + /** + * Sets timeout. + * + * @param timeout the timeout + */ + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + /** + * Gets begin time. + * + * @return the begin time + */ + public long getBeginTime() { + return beginTime; + } + + /** + * Sets begin time. + * + * @param beginTime the begin time + */ + public void setBeginTime(long beginTime) { + this.beginTime = beginTime; + } + + /** + * Gets transaction id. + * + * @return the transaction id + */ + public long getTransactionId() { + return transactionId; + } + + /** + * Sets transaction id. + * + * @param transactionId the transaction id + */ + public void setTransactionId(long transactionId) { + this.transactionId = transactionId; + } + + /** + * Gets application data. + * + * @return the application data + */ + public String getApplicationData() { + return applicationData; + } + + /** + * Sets application data. + * + * @param applicationData the application data + */ + public void setApplicationData(String applicationData) { + this.applicationData = applicationData; + } + + /** + * Gets gmt create. + * + * @return the gmt create + */ + public Date getGmtCreate() { + return gmtCreate; + } + + /** + * Sets gmt create. + * + * @param gmtCreate the gmt create + */ + public void setGmtCreate(Date gmtCreate) { + this.gmtCreate = gmtCreate; + } + + /** + * Gets gmt modified. + * + * @return the gmt modified + */ + public Date getGmtModified() { + return gmtModified; + } + + /** + * Sets gmt modified. + * + * @param gmtModified the gmt modified + */ + public void setGmtModified(Date gmtModified) { + this.gmtModified = gmtModified; + } + + @Override + public String toString(){ + return StringUtils.toString(this); + } + +} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/LockDO.java b/core/src/main/java/io/seata/core/store/LockDO.java new file mode 100644 index 00000000000..51b242de627 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/LockDO.java @@ -0,0 +1,178 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store; + +import io.seata.common.util.StringUtils; + +/** + * The type Lock do. + * + * @author zhangsen + * @data 2019 /4/25 + */ +public class LockDO { + + private String xid; + + private Long transactionId; + + private Long branchId; + + private String resourceId; + + private String tableName; + + private String pk; + + private String rowKey; + + /** + * Instantiates a new Lock do. + */ + public LockDO() { + } + + /** + * Gets xid. + * + * @return the xid + */ + public String getXid() { + return xid; + } + + /** + * Sets xid. + * + * @param xid the xid + */ + public void setXid(String xid) { + this.xid = xid; + } + + /** + * Gets transaction id. + * + * @return the transaction id + */ + public Long getTransactionId() { + return transactionId; + } + + /** + * Sets transaction id. + * + * @param transactionId the transaction id + */ + public void setTransactionId(Long transactionId) { + this.transactionId = transactionId; + } + + /** + * Gets resource id. + * + * @return the resource id + */ + public String getResourceId() { + return resourceId; + } + + /** + * Sets resource id. + * + * @param resourceId the resource id + */ + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + /** + * Gets row key. + * + * @return the row key + */ + public String getRowKey() { + return rowKey; + } + + /** + * Sets row key. + * + * @param rowKey the row key + */ + public void setRowKey(String rowKey) { + this.rowKey = rowKey; + } + + /** + * Gets table name. + * + * @return the table name + */ + public String getTableName() { + return tableName; + } + + /** + * Sets table name. + * + * @param tableName the table name + */ + public void setTableName(String tableName) { + this.tableName = tableName; + } + + /** + * Gets pk. + * + * @return the pk + */ + public String getPk() { + return pk; + } + + /** + * Sets pk. + * + * @param pk the pk + */ + public void setPk(String pk) { + this.pk = pk; + } + + /** + * Gets branch id. + * + * @return the branch id + */ + public Long getBranchId() { + return branchId; + } + + /** + * Sets branch id. + * + * @param branchId the branch id + */ + public void setBranchId(Long branchId) { + this.branchId = branchId; + } + + @Override + public String toString() { + return StringUtils.toString(this); + } +} diff --git a/core/src/main/java/io/seata/core/store/LockStore.java b/core/src/main/java/io/seata/core/store/LockStore.java new file mode 100644 index 00000000000..49e92e6ab10 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/LockStore.java @@ -0,0 +1,68 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store; + +import java.util.List; + +/** + * The interface Lock store. + * + * @author zhangsen + * @data 2019 /4/25 + */ +public interface LockStore { + + /** + * Acquire lock boolean. + * + * @param lockDO the lock do + * @return the boolean + */ + boolean acquireLock(LockDO lockDO); + + + /** + * Acquire lock boolean. + * + * @param lockDOs the lock d os + * @return the boolean + */ + boolean acquireLock(List lockDOs); + + /** + * Un lock boolean. + * + * @param lockDO the lock do + * @return the boolean + */ + boolean unLock(LockDO lockDO); + + /** + * Un lock boolean. + * + * @param lockDOs the lock d os + * @return the boolean + */ + boolean unLock(List lockDOs); + + /** + * Is lockable boolean. + * + * @param lockDOs the lock do + * @return the boolean + */ + boolean isLockable(List lockDOs); +} diff --git a/core/src/main/java/io/seata/core/store/LogStore.java b/core/src/main/java/io/seata/core/store/LogStore.java new file mode 100644 index 00000000000..f02b0ddc6d2 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/LogStore.java @@ -0,0 +1,110 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store; + + +import java.util.List; + +/** + * the transaction log store + * + * @author zhangsen + * @data 2019 /3/26 + */ +public interface LogStore { + + /** + * Query global transaction do global transaction do. + * + * @param xid the xid + * @return the global transaction do + */ + GlobalTransactionDO queryGlobalTransactionDO(String xid); + + /** + * Query global transaction do global transaction do. + * + * @param transactionId the transaction id + * @return the global transaction do + */ + GlobalTransactionDO queryGlobalTransactionDO(long transactionId); + + /** + * Query global transaction do list. + * + * @param status the status + * @param limit the limit + * @return the list + */ + List queryGlobalTransactionDO(int[] status, int limit); + + /** + * Insert global transaction do boolean. + * + * @param globalTransactionDO the global transaction do + * @return the boolean + */ + boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO); + + /** + * Update global transaction do boolean. + * + * @param globalTransactionDO the global transaction do + * @return the boolean + */ + boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO); + + /** + * Delete global transaction do boolean. + * + * @param globalTransactionDO the global transaction do + * @return the boolean + */ + boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO); + + /** + * Query branch transaction do boolean. + * + * @param xid the xid + * @return the boolean + */ + List queryBranchTransactionDO(String xid); + + /** + * Insert branch transaction do boolean. + * + * @param branchTransactionDO the branch transaction do + * @return the boolean + */ + boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO); + + /** + * Update branch transaction do boolean. + * + * @param branchTransactionDO the branch transaction do + * @return the boolean + */ + boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO); + + /** + * Delete branch transaction do boolean. + * + * @param branchTransactionDO the branch transaction do + * @return the boolean + */ + boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO); + +} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java b/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java new file mode 100644 index 00000000000..2cdbcb00ce6 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java @@ -0,0 +1,148 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + +import io.seata.common.exception.StoreException; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.constants.DBType; + +/** + * The type Abstract data source generator. + * + * @author zhangsen + * @data 2019 /4/24 + */ +public abstract class AbstractDataSourceGenerator implements DataSourceGenerator { + + /** + * The constant CONFIG. + */ + protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + + /** + * Get db type db type. + * + * @return the db type + */ + protected DBType getDBType(){ + return DBType.valueof(CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE)); + } + + /** + * Get url string. + * + * @return the string + */ + protected String getUrl(){ + String url = CONFIG.getConfig(ConfigurationKeys.STORE_DB_URL); + if(StringUtils.isBlank(url)){ + throw new StoreException("the {store.db.url} can't empty."); + } + return url; + } + + /** + * Get user string. + * + * @return the string + */ + protected String getUser(){ + String user = CONFIG.getConfig(ConfigurationKeys.STORE_DB_USER); + if(StringUtils.isBlank(user)){ + throw new StoreException("the {store.db.user} can't empty."); + } + return user; + } + + /** + * Get password string. + * + * @return the string + */ + protected String getPassword(){ + String password = CONFIG.getConfig(ConfigurationKeys.STORE_DB_PASSWORD); + return password; + } + + /** + * Get min conn int. + * + * @return the int + */ + protected int getMinConn(){ + int minConn = CONFIG.getInt(ConfigurationKeys.STORE_DB_MIN_CONN); + return minConn<0?0:minConn; + } + + /** + * Get max conn int. + * + * @return the int + */ + protected int getMaxConn(){ + int maxConn = CONFIG.getInt(ConfigurationKeys.STORE_DB_MAX_CONN); + return maxConn<0?1:maxConn; + } + + + /** + * Get driver name string. + * + * @param dbType the db type + * @return the string + */ + protected static String getDriverName(DBType dbType){ + if(DBType.H2.equals(dbType)){ + return "org.h2.Driver"; + }else if(DBType.MYSQL.equals(dbType)){ + return "com.mysql.jdbc.Driver"; + }else if(DBType.ORACLE.equals(dbType)){ + return "oracle.jdbc.OracleDriver"; + }else if(DBType.SYBAEE.equals(dbType)){ + return "com.sybase.jdbc2.jdbc.SybDriver"; + }else if(DBType.SQLSERVER.equals(dbType)){ + return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + }else if(DBType.SQLITE.equals(dbType)){ + return "org.sqlite.JDBC"; + }else if(DBType.POSTGRESQL.equals(dbType)){ + return "org.postgresql.Driver"; + }else if(DBType.ACCESS.equals(dbType)){ + return "com.hxtt.sql.access.AccessDriver"; + }else if(DBType.DB2.equals(dbType)){ + return "com.ibm.db2.jcc.DB2Driver"; + }else { + throw new StoreException("Unsupported database type, dbType:" + dbType); + } + } + + /** + * Get validation query string. + * + * @param dbType the db type + * @return the string + */ + protected String getValidationQuery(DBType dbType){ + if(DBType.ORACLE.equals(dbType)){ + return "select sysdate from dual"; + }else { + return "select 1"; + } + } + +} diff --git a/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java b/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java new file mode 100644 index 00000000000..5687513969b --- /dev/null +++ b/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + +import javax.sql.DataSource; + +/** + * The interface Data source generator. + * + * @author zhangsen + * @data 2019 /4/24 + */ +public interface DataSourceGenerator { + + /** + * create DataSource from config + * + * @return data source + */ + DataSource generateDataSource(); + +} diff --git a/core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java b/core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java new file mode 100644 index 00000000000..b1aac288814 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java @@ -0,0 +1,356 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + +import io.seata.common.exception.StoreException; +import io.seata.common.executor.Initialize; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.store.LockDO; +import io.seata.core.store.LockStore; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * The type Data base lock store. + * + * @author zhangsen + * @data 2019 /4/25 + */ +@LoadLevel(name = "db") +public class LockStoreDataBaseDAO implements LockStore, Initialize { + + /** + * The constant CONFIG. + */ + protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + + /** + * The Log store data source. + */ + protected DataSource logStoreDataSource = null; + + /** + * The Lock table. + */ + protected String lockTable; + + /** + * The Db type. + */ + protected String dbType; + + /** + * Instantiates a new Data base lock store dao. + * + * @param logStoreDataSource the log store data source + */ + public LockStoreDataBaseDAO(DataSource logStoreDataSource) { + this.logStoreDataSource = logStoreDataSource; + } + + @Override + public void init() { + lockTable = CONFIG.getConfig(ConfigurationKeys.LOCK_DB_TABLE, ConfigurationKeys.LOCK_DB_DEFAULT_TABLE); + dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); + if (StringUtils.isBlank(dbType)) { + throw new StoreException("there must be db type."); + } + if (logStoreDataSource == null) { + throw new StoreException("there must be logStoreDataSource."); + } + } + + @Override + public boolean acquireLock(LockDO lockDO) { + List locks = new ArrayList<>(); + locks.add(lockDO); + return acquireLock(locks); + } + + @Override + public boolean acquireLock(List lockDOs) { + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(false); + + //check lock + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < lockDOs.size(); i++){ + sb.append("?"); + if( i != (lockDOs.size() - 1)){ + sb.append(", "); + } + } + boolean canLock = true, isReLock = false; + //query + String checkLockSQL = LockStoreSqls.getCheckLockableSql(lockTable, sb.toString(), dbType); + ps = conn.prepareStatement(checkLockSQL); + for (int i = 0; i < lockDOs.size(); i++){ + ps.setString(i+1, lockDOs.get(i).getRowKey()); + } + rs = ps.executeQuery(); + while (rs.next()) { + if(StringUtils.equals(rs.getString("xid"), lockDOs.get(0).getXid())){ + isReLock = true; + }else { + canLock &= false; + } + } + + if(!canLock){ + conn.rollback(); + return false; + } + + if(isReLock){ + conn.rollback(); + return true; + } + + //lock + for(LockDO lockDO : lockDOs){ + if(!doAcquireLock(conn, lockDO)) { + conn.rollback(); + return false; + } + } + conn.commit(); + return true; + } catch (SQLException e) { + throw new StoreException(e); + } finally { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + } + } + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + } + } + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean unLock(LockDO lockDO) { + List locks = new ArrayList<>(); + locks.add(lockDO); + return unLock(locks); + } + + @Override + public boolean unLock(List lockDOs) { + Connection conn = null; + PreparedStatement ps = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + + StringBuilder sb = new StringBuilder(); + for(int i = 0; i< lockDOs.size(); i++){ + sb.append("?"); + if(i != (lockDOs.size() - 1)){ + sb.append(", "); + } + } + //batch release lock + String batchDeleteSQL = LockStoreSqls.getBatchDeleteLockSql(lockTable, sb.toString(), dbType); + ps = conn.prepareStatement(batchDeleteSQL); + ps.setString(1, lockDOs.get(0).getXid()); + for(int i = 0; i< lockDOs.size(); i++){ + ps.setString(i+2, lockDOs.get(i).getRowKey()); + } + return ps.executeUpdate() > 0; + } catch (SQLException e) { + throw new StoreException(e); + } finally { + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean isLockable(List lockDOs) { + Connection conn = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + if(!checkLockable(conn, lockDOs)){ + return false; + } + return true; + } catch (SQLException e) { + throw new StoreException(e); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + /** + * Do acquire lock boolean. + * + * @param conn the conn + * @param lockDO the lock do + * @return the boolean + */ + protected boolean doAcquireLock(Connection conn, LockDO lockDO) { + PreparedStatement ps = null; + ResultSet rs = null; + try { + //insert + String insertLockSQL = LockStoreSqls.getInsertLockSQL(lockTable, dbType); + ps = conn.prepareStatement(insertLockSQL); + ps.setString(1, lockDO.getXid()); + ps.setLong(2, lockDO.getTransactionId()); + ps.setLong(3, lockDO.getBranchId()); + ps.setString(4, lockDO.getResourceId()); + ps.setString(5, lockDO.getTableName()); + ps.setString(6, lockDO.getPk()); + ps.setString(7, lockDO.getRowKey()); + return ps.executeUpdate() > 0; + } catch (SQLException e) { + throw new StoreException(e); + } finally { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + } + } + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + } + } + } + } + + /** + * Check lock boolean. + * + * @param conn the conn + * @param lockDOs the lock do + * @return the boolean + */ + protected boolean checkLockable(Connection conn, List lockDOs){ + PreparedStatement ps = null; + ResultSet rs = null; + try { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < lockDOs.size(); i++){ + sb.append("?"); + if( i != (lockDOs.size() - 1)){ + sb.append(", "); + } + } + + //query + String checkLockSQL = LockStoreSqls.getCheckLockableSql(lockTable, sb.toString(), dbType); + ps = conn.prepareStatement(checkLockSQL); + for (int i = 0; i < lockDOs.size(); i++){ + ps.setString(i+1, lockDOs.get(i).getRowKey()); + } + rs = ps.executeQuery(); + while (rs.next()) { + String xid = rs.getString("xid"); + if(!StringUtils.equals(xid, lockDOs.get(0).getXid())){ + return false; + } + } + return true; + }catch (SQLException e) { + throw new StoreException(e); + } finally { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + } + } + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + } + } + } + } + + /** + * Sets lock table. + * + * @param lockTable the lock table + */ + public void setLockTable(String lockTable) { + this.lockTable = lockTable; + } + + /** + * Sets db type. + * + * @param dbType the db type + */ + public void setDbType(String dbType) { + this.dbType = dbType; + } + + /** + * Sets log store data source. + * + * @param logStoreDataSource the log store data source + */ + public void setLogStoreDataSource(DataSource logStoreDataSource) { + this.logStoreDataSource = logStoreDataSource; + } +} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/db/LockStoreSqls.java b/core/src/main/java/io/seata/core/store/db/LockStoreSqls.java new file mode 100644 index 00000000000..7c95473e269 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/db/LockStoreSqls.java @@ -0,0 +1,143 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + +import io.seata.common.exception.NotSupportYetException; +import io.seata.core.constants.DBType; + +/** + * The type Lock store sqls. + * + * @author zhangsen + * @data 2019 /4/26 + */ +public class LockStoreSqls { + + /** + * The constant LOCK_TABLE_PLACEHOLD. + */ + public static final String LOCK_TABLE_PLACEHOLD = " #lock_table# "; + + /** + * The constant IN_PARAMS_PLACEHOLD. + */ + public static final String IN_PARAMS_PLACEHOLD = " #in_params# "; + + /** + * The constant ALL_COLUMNS. + */ + public static final String ALL_COLUMNS = "xid, transaction_id, branch_id, resource_id, table_name, pk, row_key, gmt_create, gmt_modified"; + + /** + * The constant INSERT_LOCK_SQL_MYSQL. + */ + public static final String INSERT_LOCK_SQL_MYSQL = "insert into " + LOCK_TABLE_PLACEHOLD + "("+ ALL_COLUMNS +")" + + "values (?, ?, ?, ?, ?, ?, ?, now(), now())"; + + /** + * The constant INSERT_LOCK_SQL_ORACLE. + */ + public static final String INSERT_LOCK_SQL_ORACLE = "insert into " + LOCK_TABLE_PLACEHOLD + "("+ ALL_COLUMNS +")" + + "values (?, ?, ?, ?, ?, ?, ?, sysdate, sysdate)"; + + /** + * The constant DELETE_LOCK_SQL. + */ + public static final String DELETE_LOCK_SQL = "delete from " + LOCK_TABLE_PLACEHOLD + " where row_key = ? and xid = ?"; + + /** + * The constant BATCH_DELETE_LOCK_SQL. + */ + public static final String BATCH_DELETE_LOCK_SQL = "delete from " + LOCK_TABLE_PLACEHOLD + " where xid = ? and row_key in ("+ IN_PARAMS_PLACEHOLD +") "; + + /** + * The constant QUERY_LOCK_SQL. + */ + public static final String QUERY_LOCK_SQL = "select " + ALL_COLUMNS + " from " + LOCK_TABLE_PLACEHOLD + + " where row_key = ? "; + + /** + * The constant CHECK_LOCK_SQL. + */ + public static final String CHECK_LOCK_SQL = "select " + ALL_COLUMNS + " from " + LOCK_TABLE_PLACEHOLD + + " where row_key in ("+ IN_PARAMS_PLACEHOLD +")" ; + + /** + * Get insert lock sql string. + * + * @param lockTable the lock table + * @param dbType the db type + * @return the string + */ + public static String getInsertLockSQL(String lockTable, String dbType){ + if(DBType.MYSQL.name().equalsIgnoreCase(dbType) + || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) + || DBType.H2.name().equalsIgnoreCase(dbType)){ + return INSERT_LOCK_SQL_MYSQL.replace(LOCK_TABLE_PLACEHOLD, lockTable); + }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ + return INSERT_LOCK_SQL_ORACLE.replace(LOCK_TABLE_PLACEHOLD, lockTable); + }else{ + throw new NotSupportYetException("unknown dbType:" + dbType); + } + } + + /** + * Get delete lock sql string. + * + * @param lockTable the lock table + * @param dbType the db type + * @return the string + */ + public static String getDeleteLockSql(String lockTable, String dbType){ + return DELETE_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable); + } + + /** + * Get batch delete lock sql string. + * + * @param lockTable the lock table + * @param paramPlaceHold the param place hold + * @param dbType the db type + * @return the string + */ + public static String getBatchDeleteLockSql(String lockTable, String paramPlaceHold, String dbType){ + return BATCH_DELETE_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable).replace(IN_PARAMS_PLACEHOLD, paramPlaceHold); + } + + /** + * Get query lock sql string. + * + * @param lockTable the lock table + * @param dbType the db type + * @return the string + */ + public static String getQueryLockSql(String lockTable, String dbType){ + return QUERY_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable); + } + + /** + * Get check lock sql string. + * + * @param lockTable the lock table + * @param paramPlaceHold the param place hold + * @param dbType the db type + * @return the string + */ + public static String getCheckLockableSql(String lockTable, String paramPlaceHold, String dbType){ + return CHECK_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable).replace(IN_PARAMS_PLACEHOLD, paramPlaceHold); + } + +} diff --git a/core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java b/core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java new file mode 100644 index 00000000000..4248ce45929 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java @@ -0,0 +1,533 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + +import io.seata.common.exception.StoreException; +import io.seata.common.executor.Initialize; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.store.BranchTransactionDO; +import io.seata.core.store.GlobalTransactionDO; +import io.seata.core.store.LogStore; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * The type Log store data base dao. + * + * @author zhangsen + * @data 2019 /4/2 + */ +@LoadLevel(name = "db") +public class LogStoreDataBaseDAO implements LogStore, Initialize { + + /** + * The constant CONFIG. + */ + protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + + /** + * The Log store data source. + */ + protected DataSource logStoreDataSource = null; + + /** + * The Global table. + */ + protected String globalTable; + + /** + * The Brach table. + */ + protected String brachTable; + + private String dbType; + + /** + * Instantiates a new Log store data base dao. + */ + public LogStoreDataBaseDAO(){ + } + + /** + * Instantiates a new Log store data base dao. + * + * @param logStoreDataSource the log store data source + */ + public LogStoreDataBaseDAO(DataSource logStoreDataSource) { + this.logStoreDataSource = logStoreDataSource; + } + + @Override + public void init() { + globalTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, ConfigurationKeys.STORE_DB_GLOBAL_DEFAULT_TABLE); + brachTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, ConfigurationKeys.STORE_DB_BRANCH_DEFAULT_TABLE); + dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); + if(StringUtils.isBlank(dbType)){ + throw new StoreException("there must be db type."); + } + if(logStoreDataSource == null){ + throw new StoreException("there must be logStoreDataSource."); + } + } + + @Override + public GlobalTransactionDO queryGlobalTransactionDO(String xid) { + String sql = LogStoreSqls.getQueryGlobalTransactionSQL(globalTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setString(1, xid); + rs = ps.executeQuery(); + if(rs.next()){ + return convertGlobalTransactionDO(rs); + }else { + return null; + } + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(rs != null){ + try { + rs.close(); + } catch (SQLException e) { + } + } + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + + @Override + public GlobalTransactionDO queryGlobalTransactionDO(long transactionId){ + String sql = LogStoreSqls.getQueryGlobalTransactionSQLByTransactionId(globalTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setLong(1, transactionId); + rs = ps.executeQuery(); + if(rs.next()){ + return convertGlobalTransactionDO(rs); + }else { + return null; + } + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(rs != null){ + try { + rs.close(); + } catch (SQLException e) { + } + } + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public List queryGlobalTransactionDO(int[] statuses, int limit) { + List ret = new ArrayList(); + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < statuses.length; i ++){ + sb.append("?"); + if(i != (statuses.length -1)){ + sb.append(", "); + } + } + + String sql = LogStoreSqls.getQueryGlobalTransactionSQLByStatus(globalTable, dbType, sb.toString()); + ps = conn.prepareStatement(sql); + for(int i = 0; i < statuses.length; i ++){ + int status = statuses[i]; + ps.setInt(i+1, status); + } + ps.setInt(statuses.length +1, limit); + rs = ps.executeQuery(); + while(rs.next()){ + ret.add(convertGlobalTransactionDO(rs)); + } + return ret; + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(rs != null){ + try { + rs.close(); + } catch (SQLException e) { + } + } + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { + String sql = LogStoreSqls.getInsertGlobalTransactionSQL(globalTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + try{ + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setString(1, globalTransactionDO.getXid()); + ps.setLong(2, globalTransactionDO.getTransactionId()); + ps.setInt(3, globalTransactionDO.getStatus()); + ps.setString(4, globalTransactionDO.getApplicationId()); + ps.setString(5, globalTransactionDO.getTransactionServiceGroup()); + ps.setString(6, globalTransactionDO.getTransactionName()); + ps.setInt(7, globalTransactionDO.getTimeout()); + ps.setLong(8, globalTransactionDO.getBeginTime()); + ps.setString(9, globalTransactionDO.getApplicationData()); + return ps.executeUpdate() > 0; + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { + String sql = LogStoreSqls.getUpdateGlobalTransactionStatusSQL(globalTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + try{ + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setInt(1, globalTransactionDO.getStatus()); + ps.setString(2, globalTransactionDO.getXid()); + return ps.executeUpdate() > 0; + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { + String sql = LogStoreSqls.getDeleteGlobalTransactionSQL(globalTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + try{ + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setString(1, globalTransactionDO.getXid()); + return ps.executeUpdate() > 0; + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public List queryBranchTransactionDO(String xid) { + List rets = new ArrayList<>(); + String sql = LogStoreSqls.getQureyBranchTransaction(brachTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + + ps = conn.prepareStatement(sql); + ps.setString(1, xid); + + ResultSet rs = ps.executeQuery(); + while(rs.next()){ + rets.add(convertBranchTransactionDO(rs)); + } + return rets; + } catch (SQLException e) { + throw new StoreException(e); + } finally { + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + } + } + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO) { + String sql = LogStoreSqls.getInsertBranchTransactionSQL(brachTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + try { + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setString(1, branchTransactionDO.getXid()); + ps.setLong(2, branchTransactionDO.getTransactionId()); + ps.setLong(3, branchTransactionDO.getBranchId()); + ps.setString(4, branchTransactionDO.getResourceGroupId()); + ps.setString(5, branchTransactionDO.getResourceId()); + ps.setString(6, branchTransactionDO.getLockKey()); + ps.setString(7, branchTransactionDO.getBranchType()); + ps.setInt(8, branchTransactionDO.getStatus()); + ps.setString(9, branchTransactionDO.getClientId()); + ps.setString(10, branchTransactionDO.getApplicationData()); + return ps.executeUpdate() > 0; + } catch (SQLException e) { + throw new StoreException(e); + } finally { + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + } + } + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO) { + String sql = LogStoreSqls.getUpdateBranchTransactionStatusSQL(brachTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + try{ + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setInt(1, branchTransactionDO.getStatus()); + ps.setString(2, branchTransactionDO.getXid()); + ps.setLong(3, branchTransactionDO.getBranchId()); + return ps.executeUpdate() > 0; + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Override + public boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO) { + String sql = LogStoreSqls.getDeleteBranchTransactionByBranchIdSQL(brachTable, dbType); + Connection conn = null; + PreparedStatement ps = null; + try{ + conn = logStoreDataSource.getConnection(); + conn.setAutoCommit(true); + ps = conn.prepareStatement(sql); + ps.setString(1, branchTransactionDO.getXid()); + ps.setLong(2, branchTransactionDO.getBranchId()); + return ps.executeUpdate() > 0; + }catch (SQLException e){ + throw new StoreException(e); + }finally { + if(ps != null){ + try { + ps.close(); + } catch (SQLException e) { + } + } + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + + private GlobalTransactionDO convertGlobalTransactionDO(ResultSet rs) throws SQLException { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid(rs.getString("xid")); + globalTransactionDO.setStatus(rs.getInt("status")); + globalTransactionDO.setApplicationId(rs.getString("application_id")); + globalTransactionDO.setBeginTime(rs.getLong("begin_time")); + globalTransactionDO.setTimeout(rs.getInt("timeout")); + globalTransactionDO.setTransactionId(rs.getLong("transaction_id")); + globalTransactionDO.setTransactionName(rs.getString("transaction_name")); + globalTransactionDO.setTransactionServiceGroup(rs.getString("transaction_service_group")); + globalTransactionDO.setApplicationData(rs.getString("application_data")); + globalTransactionDO.setGmtCreate(rs.getTimestamp("gmt_create")); + globalTransactionDO.setGmtModified(rs.getTimestamp("gmt_modified")); + return globalTransactionDO; + } + + private BranchTransactionDO convertBranchTransactionDO(ResultSet rs) throws SQLException { + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setResourceGroupId(rs.getString("resource_group_id")); + branchTransactionDO.setStatus(rs.getInt("status")); + branchTransactionDO.setApplicationData(rs.getString("application_data")); + branchTransactionDO.setClientId(rs.getString("client_id")); + branchTransactionDO.setLockKey(rs.getString("lock_key")); + branchTransactionDO.setXid(rs.getString("xid")); + branchTransactionDO.setResourceId(rs.getString("resource_id")); + branchTransactionDO.setBranchId(rs.getLong("branch_id")); + branchTransactionDO.setBranchType(rs.getString("branch_type")); + branchTransactionDO.setTransactionId(rs.getLong("transaction_id")); + branchTransactionDO.setGmtCreate(rs.getTimestamp("gmt_create")); + branchTransactionDO.setGmtModified(rs.getTimestamp("gmt_modified")); + return branchTransactionDO; + } + + /** + * Sets log store data source. + * + * @param logStoreDataSource the log store data source + */ + public void setLogStoreDataSource(DataSource logStoreDataSource) { + this.logStoreDataSource = logStoreDataSource; + } + + /** + * Sets global table. + * + * @param globalTable the global table + */ + public void setGlobalTable(String globalTable) { + this.globalTable = globalTable; + } + + /** + * Sets brach table. + * + * @param brachTable the brach table + */ + public void setBrachTable(String brachTable) { + this.brachTable = brachTable; + } + + /** + * Sets db type. + * + * @param dbType the db type + */ + public void setDbType(String dbType) { + this.dbType = dbType; + } +} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/db/LogStoreSqls.java b/core/src/main/java/io/seata/core/store/db/LogStoreSqls.java new file mode 100644 index 00000000000..69308324d63 --- /dev/null +++ b/core/src/main/java/io/seata/core/store/db/LogStoreSqls.java @@ -0,0 +1,323 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + + +import io.seata.common.exception.NotSupportYetException; +import io.seata.core.constants.DBType; + +/** + * database log store SQLs + * + * @author zhangsen + * @data 2019 /4/2 + */ +public class LogStoreSqls { + + /** + * The constant GLOBAL_TABLE_PLACEHOLD. + */ + public static final String GLOBAL_TABLE_PLACEHOLD = " #global_table# "; + + /** + * The constant BRANCH_TABLE_PLACEHOLD. + */ + public static final String BRANCH_TABLE_PLACEHOLD = " #branch_table# "; + + + /** + * The constant PRAMETER_PLACEHOLD. + */ + public static final String PRAMETER_PLACEHOLD = " #PRAMETER_PLACEHOLD# "; + + /** + * The constant ALL_GLOBAL_COLUMNS. + */ + public static final String ALL_GLOBAL_COLUMNS = "xid, transaction_id, status, application_id, transaction_service_group, transaction_name, timeout, begin_time, application_data, gmt_create, gmt_modified "; + + /** + * The constant ALL_BRANCH_COLUMNS. + */ + protected static final String ALL_BRANCH_COLUMNS = "xid, transaction_id, branch_id, resource_group_id, resource_id, lock_key, branch_type, status, client_id, application_data, gmt_create, gmt_modified "; + + /** + * The constant INSERT_GLOBAL_TRANSACTION_MYSQL. + */ + public static final String INSERT_GLOBAL_TRANSACTION_MYSQL = "insert into " + GLOBAL_TABLE_PLACEHOLD + "("+ ALL_GLOBAL_COLUMNS +")" + + "values(?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now()) "; + + /** + * The constant INSERT_GLOBAL_TRANSACTION_ORACLE. + */ + public static final String INSERT_GLOBAL_TRANSACTION_ORACLE = "insert into " + GLOBAL_TABLE_PLACEHOLD + "("+ ALL_GLOBAL_COLUMNS +")" + + "values(?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate, sysdate) "; + + /** + * The constant UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL. + */ + public static final String UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL = "update "+ GLOBAL_TABLE_PLACEHOLD + " set status = ?, gmt_modified = now() where xid = ?"; + + /** + * The constant UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE. + */ + public static final String UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE = "update "+ GLOBAL_TABLE_PLACEHOLD + " set status = ?, gmt_modified = sysdate where xid = ?"; + + /** + * The constant DELETE_GLOBAL_TRANSACTION. + */ + public static final String DELETE_GLOBAL_TRANSACTION = "delete from " + GLOBAL_TABLE_PLACEHOLD + " where xid = ?"; + + /** + * The constant QUERY_GLOBAL_TRANSACTION. + */ + public static final String QUERY_GLOBAL_TRANSACTION = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where xid = ?"; + + + /** + * The constant QUERY_GLOBAL_TRANSACTION_ID. + */ + public static final String QUERY_GLOBAL_TRANSACTION_BY_ID = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where transaction_id = ?"; + + + /** + * The constant QUERY_GLOBAL_TRANSACTION_BY_STATUS. + */ + public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + + " where status in (" + PRAMETER_PLACEHOLD + ") order by gmt_modified limit ?"; + /** + * The constant QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL. + */ + public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where status in (" + + "0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14) order by gmt_modified limit ?"; + + /** + * The constant QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE. + */ + public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE = "select A.* from ( select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where status in (" + + "0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14) order by gmt_modified ) A where ROWNUM <= ?" ; + + + /** + * The constant INSERT_BRANCH_TRANSACTION_MYSQL. + */ + public static final String INSERT_BRANCH_TRANSACTION_MYSQL = "insert into " + BRANCH_TABLE_PLACEHOLD + "("+ ALL_BRANCH_COLUMNS +")" + + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now())"; + + /** + * The constant INSERT_BRANCH_TRANSACTION_ORACLE. + */ + public static final String INSERT_BRANCH_TRANSACTION_ORACLE = "insert into " + BRANCH_TABLE_PLACEHOLD + "("+ ALL_BRANCH_COLUMNS +")" + + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate, sysdate)"; + + /** + * The constant UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL. + */ + public static final String UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL = "update "+ BRANCH_TABLE_PLACEHOLD + " set status = ?, gmt_modified = now() where xid = ? and branch_id = ?"; + + /** + * The constant UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE. + */ + public static final String UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE = "update "+ BRANCH_TABLE_PLACEHOLD + " set status = ?, gmt_modified = sysdate where xid = ? and branch_id = ?" ; + + /** + * The constant DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID. + */ + public static final String DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID = "delete from " + BRANCH_TABLE_PLACEHOLD + " where xid = ? and branch_id = ?"; + + /** + * The constant DELETE_BRANCH_TRANSACTION_BY_XID. + */ + public static final String DELETE_BRANCH_TRANSACTION_BY_XID = "delete from " + BRANCH_TABLE_PLACEHOLD + " where xid = ?"; + + /** + * The constant QUREY_BRANCH_TRANSACTION. + */ + public static final String QUREY_BRANCH_TRANSACTION = "select "+ALL_BRANCH_COLUMNS+" from " + BRANCH_TABLE_PLACEHOLD + " where xid = ?"; + + /** + * Get insert global transaction sql string. + * + * @param globalTable the global table + * @param dbType the db type + * @return the string + */ + public static String getInsertGlobalTransactionSQL(String globalTable, String dbType){ + if(DBType.MYSQL.name().equalsIgnoreCase(dbType) + || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) + || DBType.H2.name().equalsIgnoreCase(dbType)){ + return INSERT_GLOBAL_TRANSACTION_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ + return INSERT_GLOBAL_TRANSACTION_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + }else{ + throw new NotSupportYetException("unknown dbType:" + dbType); + } + } + + /** + * Get update global transaction status sql string. + * + * @param globalTable the global table + * @param dbType the db type + * @return the string + */ + public static String getUpdateGlobalTransactionStatusSQL(String globalTable, String dbType){ + if(DBType.MYSQL.name().equalsIgnoreCase(dbType) + || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) + || DBType.H2.name().equalsIgnoreCase(dbType)){ + return UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ + return UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + }else{ + throw new NotSupportYetException("unknown dbType:" + dbType); + } + } + + /** + * Get delete global transaction sql string. + * + * @param globalTable the global table + * @param dbType the db type + * @return the string + */ + public static String getDeleteGlobalTransactionSQL(String globalTable, String dbType){ + return DELETE_GLOBAL_TRANSACTION.replace(GLOBAL_TABLE_PLACEHOLD, globalTable ); + } + + /** + * Get query global transaction sql string. + * + * @param globalTable the global table + * @param dbType the db type + * @return the string + */ + public static String getQueryGlobalTransactionSQL(String globalTable, String dbType){ + return QUERY_GLOBAL_TRANSACTION.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + } + + /** + * Get query global transaction sql by transaction id string. + * + * @param globalTable the global table + * @param dbType the db type + * @return the string + */ + public static String getQueryGlobalTransactionSQLByTransactionId(String globalTable, String dbType){ + return QUERY_GLOBAL_TRANSACTION_BY_ID.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + } + + + /** + * Get query global transaction sql by status string. + * + * @param globalTable the global table + * @param dbType the db type + * @param paramsPlaceHolder the params place holder + * @return the string + */ + public static String getQueryGlobalTransactionSQLByStatus(String globalTable, String dbType, String paramsPlaceHolder){ + return QUERY_GLOBAL_TRANSACTION_BY_STATUS.replace(GLOBAL_TABLE_PLACEHOLD, globalTable).replace(PRAMETER_PLACEHOLD, paramsPlaceHolder); + } + + /** + * Get query global transaction for recovery sql string. + * + * @param globalTable the global table + * @param dbType the db type + * @return the string + */ + public static String getQueryGlobalTransactionForRecoverySQL(String globalTable, String dbType){ + if(DBType.MYSQL.name().equalsIgnoreCase(dbType) + || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) + || DBType.H2.name().equalsIgnoreCase(dbType)){ + return QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ + return QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); + }else{ + throw new NotSupportYetException("unknown dbType:" + dbType); + } + } + + /** + * Get insert branch transaction sql string. + * + * @param branchTable the branch table + * @param dbType the db type + * @return the string + */ + public static String getInsertBranchTransactionSQL(String branchTable, String dbType){ + if(DBType.MYSQL.name().equalsIgnoreCase(dbType) + || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) + || DBType.H2.name().equalsIgnoreCase(dbType)){ + return INSERT_BRANCH_TRANSACTION_MYSQL.replace(BRANCH_TABLE_PLACEHOLD, branchTable); + }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ + return INSERT_BRANCH_TRANSACTION_ORACLE.replace(BRANCH_TABLE_PLACEHOLD, branchTable); + }else{ + throw new NotSupportYetException("unknown dbType:" + dbType); + } + } + + /** + * Get update branch transaction status sql string. + * + * @param branchTable the branch table + * @param dbType the db type + * @return the string + */ + public static String getUpdateBranchTransactionStatusSQL(String branchTable, String dbType){ + if(DBType.MYSQL.name().equalsIgnoreCase(dbType) + || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) + || DBType.H2.name().equalsIgnoreCase(dbType)){ + return UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL.replace(BRANCH_TABLE_PLACEHOLD, branchTable); + }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ + return UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE.replace(BRANCH_TABLE_PLACEHOLD, branchTable); + }else{ + throw new NotSupportYetException("unknown dbType:" + dbType); + } + } + + /** + * Get delete branch transaction by branch id sql string. + * + * @param branchTable the branch table + * @param dbType the db type + * @return the string + */ + public static String getDeleteBranchTransactionByBranchIdSQL(String branchTable, String dbType){ + return DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID.replace(BRANCH_TABLE_PLACEHOLD, branchTable); + } + + /** + * Get delete branch transaction by x id string. + * + * @param branchTable the branch table + * @param dbType the db type + * @return the string + */ + public static String getDeleteBranchTransactionByXId(String branchTable, String dbType){ + return DELETE_BRANCH_TRANSACTION_BY_XID.replace(BRANCH_TABLE_PLACEHOLD, branchTable); + } + + /** + * Get qurey branch transaction string. + * + * @param branchTable the branch table + * @param dbType the db type + * @return the string + */ + public static String getQureyBranchTransaction(String branchTable, String dbType){ + return QUREY_BRANCH_TRANSACTION.replace(BRANCH_TABLE_PLACEHOLD, branchTable); + } +} \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/io.seata.core.store.LockStore b/core/src/main/resources/META-INF/services/io.seata.core.store.LockStore new file mode 100644 index 00000000000..bd6ff3d994a --- /dev/null +++ b/core/src/main/resources/META-INF/services/io.seata.core.store.LockStore @@ -0,0 +1 @@ +io.seata.core.store.db.LockStoreDataBaseDAO \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/io.seata.core.store.LogStore b/core/src/main/resources/META-INF/services/io.seata.core.store.LogStore new file mode 100644 index 00000000000..f95309566f9 --- /dev/null +++ b/core/src/main/resources/META-INF/services/io.seata.core.store.LogStore @@ -0,0 +1 @@ +io.seata.core.store.db.LogStoreDataBaseDAO \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java b/core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java new file mode 100644 index 00000000000..d76a6c79dc4 --- /dev/null +++ b/core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java @@ -0,0 +1,192 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.protocol; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import io.netty.buffer.ByteBuf; +import static io.netty.buffer.Unpooled.buffer; + +/** + * RegisterTMRequest Test + * + * @author kaitithoma + * @author Danaykap + * + * @date 2019/05/13 + * + */ + +public class RegisterTMRequestTest { + + private static RegisterTMRequest registerTMRequest; + private static AbstractIdentifyRequest air; + private static final String APP_ID = "applicationId"; + private static final String TSG = "transactionServiceGroup"; + private static final String ED = "extraData"; + private static final short TYPE_CODE = 101; + private static final ByteBuf BB = buffer(128); + + /** Constructor without arguments **/ + @BeforeAll + public static void setupNull() { + registerTMRequest = new RegisterTMRequest(); + air = Mockito.mock( + AbstractIdentifyRequest.class, + Mockito.CALLS_REAL_METHODS); + } + + /** Constructor with arguments **/ + @BeforeAll + public static void setupWithValues() { + registerTMRequest = new RegisterTMRequest(APP_ID, TSG, ED); + air = Mockito.mock( + AbstractIdentifyRequest.class, + Mockito.CALLS_REAL_METHODS); + } + + /** Test get type code **/ + @Test + public void testGetTypeCode() { + Assertions.assertEquals(TYPE_CODE, registerTMRequest.getTypeCode()); + } + + /** + * Test toString having all the parameters initialized to null + */ + @Test + public void testToStringNullValues() { + Assertions.assertEquals("RegisterTMRequest{" + "applicationId='" + null + '\'' + ", transactionServiceGroup='" + + null + '\'' + '}', registerTMRequest.toString()); + } + + /** + * Test decode method with empty parameter + */ + @Test + public void testDecodeEmpty() { + BB.clear(); + Assertions.assertFalse(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeLessThanTwo() { + BB.clear(); + for (int i = 0; i < 2; i++) { + BB.writeShort(i); + } + Assertions.assertFalse(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeMoreThanThree() { + BB.clear(); + for (int i = 0; i < 3; i++) { + BB.writeShort(i); + } + Assertions.assertFalse(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeLessThanFour() { + BB.clear(); + for (int i = 0; i < 4; i++) { + BB.writeShort(i); + } + Assertions.assertFalse(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeMoreLessThanOne() { + BB.clear(); + for (int i = 0; i < 1; i++) { + BB.writeShort(i); + } + Assertions.assertFalse(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeMoreLessThanFourWithZero() { + BB.clear(); + for (int i = 0; i < 4; i++) { + BB.writeZero(i); + } + Assertions.assertFalse(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeFalseLessThanTwoWithDifferentReadable() { + BB.clear(); + for (int i = 0; i < 1; i++) { + BB.writeZero(i); + } + for (int i = 1; i < 2; i++) { + BB.writeShort(i); + } + Assertions.assertFalse(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeTrueLessThanFive() { + BB.clear(); + for (int i = 0; i < 4; i++) { + BB.writeZero(i); + } + for (int i = 4; i < 5; i++) { + BB.writeShort(i); + } + Assertions.assertTrue(air.decode(BB)); + } + + /** + * Test decode method with initialized parameter + */ + @Test + public void testDecodeTrueLessThanSixteen() { + BB.clear(); + for (int i = 0; i < 15; i++) { + BB.writeZero(i); + } + for (int i = 15; i < 16; i++) { + BB.writeShort(i); + } + Assertions.assertTrue(air.decode(BB)); + } + +} diff --git a/core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java b/core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java new file mode 100644 index 00000000000..eee248eb8cd --- /dev/null +++ b/core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java @@ -0,0 +1,300 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + +import io.seata.core.store.LockDO; +import org.apache.commons.dbcp.BasicDataSource; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +/** + * @author zhangsen + * @data 2019/4/26 + */ +public class DataBaseLockStoreDAOTest { + + static LockStoreDataBaseDAO dataBaseLockStoreDAO = null; + + static BasicDataSource dataSource = null; + + @BeforeAll + public static void start(){ + dataSource = new BasicDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUrl("jdbc:h2:./db_store/lock"); + dataSource.setUsername("sa"); + dataSource.setPassword(""); + + dataBaseLockStoreDAO = new LockStoreDataBaseDAO(dataSource); + dataBaseLockStoreDAO.setDbType("h2"); + dataBaseLockStoreDAO.setLockTable("lock_table"); + + prepareTable(dataSource); + } + + private static void prepareTable(BasicDataSource dataSource) { + Connection conn = null; + try { + conn = dataSource.getConnection(); + Statement s = conn.createStatement(); + try { + s.execute("drop table lock_table"); + } catch (Exception e) { + } + s.execute("CREATE TABLE lock_table ( xid varchar(96) , transaction_id long , branch_id long, resource_id varchar(32) ,table_name varchar(32) ,pk varchar(32) , row_key varchar(128) primary key not null, gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); + System.out.println("create table lock_table success."); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + + @Test + public void test_acquireLocks() throws SQLException { + List lockDOs = new ArrayList<>(); + for(int i = 0; i < 3; i++){ + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-123:123"); + lock.setTransactionId(123L); + lock.setBranchId((long) i); + lock.setRowKey("abc-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs.add(lock); + } + + boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); + Assertions.assertTrue(ret); + + String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + + Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); + + } + + + @Test + public void test_re_acquireLocks() throws SQLException { + List lockDOs = new ArrayList<>(); + for(int i = 0; i < 3; i++){ + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-123:123"); + lock.setTransactionId(123L); + lock.setBranchId((long) i); + lock.setRowKey("abc-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs.add(lock); + } + + boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); + Assertions.assertTrue(ret); + + String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + + //lock again + Assertions.assertTrue(dataBaseLockStoreDAO.acquireLock(lockDOs)); + + Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); + + } + + @Test + public void tes_unLocks() throws SQLException { + List lockDOs = new ArrayList<>(); + for(int i = 0; i < 3; i++){ + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-456:123"); + lock.setTransactionId(123L); + lock.setBranchId((long) i); + lock.setRowKey("abc-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs.add(lock); + } + + boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); + Assertions.assertTrue(ret); + + String sql = "select * from lock_table where xid = 'abc-456:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + rs.close(); + + //unlock + Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); + + rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(false); + }else { + Assertions.assertTrue(true); + } + + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + + + } + + + @Test + public void test_isLockable_can(){ + List lockDOs = new ArrayList<>(); + for(int i = 0; i < 3; i++){ + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-678:123"); + lock.setTransactionId(123L); + lock.setBranchId((long) i); + lock.setRowKey("abc-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs.add(lock); + } + + boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); + Assertions.assertTrue(ret); + + //unlock + Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); + } + + @Test + public void test_isLockable_cannot() throws SQLException { + List lockDOs = new ArrayList<>(); + for(int i = 0; i < 3; i++){ + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-123:222"); + lock.setTransactionId(222L); + lock.setBranchId((long) i); + lock.setRowKey("abc-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs.add(lock); + } + + boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); + Assertions.assertTrue(ret); + + String sql = "select * from lock_table where xid = 'abc-123:222' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + + List lockDOs_2 = new ArrayList<>(); + for(int i = 0; i < 3; i++){ + LockDO lock = new LockDO(); + lock.setResourceId("abc"); + lock.setXid("abc-123:333"); + lock.setTransactionId(333L); + lock.setBranchId((long) i); + lock.setRowKey("abc-"+i); + lock.setPk(String.valueOf(i)); + lock.setTableName("t"); + lockDOs_2.add(lock); + } + + boolean ret2 = dataBaseLockStoreDAO.acquireLock(lockDOs_2); + Assertions.assertTrue(!ret2); + + } + + + +} \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java b/core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java new file mode 100644 index 00000000000..12aaf5259ea --- /dev/null +++ b/core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java @@ -0,0 +1,659 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.core.store.db; + +import io.seata.common.util.CollectionUtils; +import io.seata.core.store.BranchTransactionDO; +import io.seata.core.store.GlobalTransactionDO; +import org.apache.commons.dbcp.BasicDataSource; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + + +/** + * @author zhangsen + * @data 2019/4/26 + */ +public class LogStoreDataBaseDAOTest { + + static LogStoreDataBaseDAO logStoreDataBaseDAO = null; + + static BasicDataSource dataSource = null; + + @BeforeAll + public static void start(){ + dataSource = new BasicDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUrl("jdbc:h2:./db_store/log"); + dataSource.setUsername("sa"); + dataSource.setPassword(""); + + logStoreDataBaseDAO = new LogStoreDataBaseDAO(dataSource); + logStoreDataBaseDAO.setDbType("h2"); + logStoreDataBaseDAO.setGlobalTable("global_table"); + logStoreDataBaseDAO.setBrachTable("branch_table"); + + prepareTable(dataSource); + } + + private static void prepareTable(BasicDataSource dataSource) { + Connection conn = null; + try { + conn = dataSource.getConnection(); + Statement s = conn.createStatement(); + try { + s.execute("drop table global_table"); + } catch (Exception e) { + } +// xid, transaction_id, status, application_id, transaction_service_group, transaction_name, timeout, begin_time, application_data, gmt_create, gmt_modified + s.execute("CREATE TABLE global_table ( xid varchar(96) primary key, transaction_id long , STATUS int, application_id varchar(32), transaction_service_group varchar(32) ,transaction_name varchar(32) ,timeout int, begin_time long, application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); + System.out.println("create table global_table success."); + + try { + s.execute("drop table branch_table"); + } catch (Exception e) { + } +// xid, transaction_id, branch_id, resource_group_id, resource_id, lock_key, branch_type, status, client_id, application_data, gmt_create, gmt_modified + s.execute("CREATE TABLE branch_table ( xid varchar(96), transaction_id long , branch_id long primary key, resource_group_id varchar(32), resource_id varchar(32) ,lock_key varchar(64) ,branch_type varchar(32) , status int , client_id varchar(128), application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); + System.out.println("create table branch_table success."); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + + @Test + public void queryGlobalTransactionDO_by_xid() throws SQLException { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:978786"); + globalTransactionDO.setApplicationData("abc=87867978"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(143546567); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + + + GlobalTransactionDO globalTransactionDO_db = logStoreDataBaseDAO.queryGlobalTransactionDO("abc-123:978786"); + Assertions.assertNotNull(globalTransactionDO_db); + + Assertions.assertEquals(globalTransactionDO_db.getBeginTime(), globalTransactionDO_db.getBeginTime()); + Assertions.assertEquals(globalTransactionDO_db.getTransactionName(), globalTransactionDO_db.getTransactionName()); + Assertions.assertEquals(globalTransactionDO_db.getTransactionId(), globalTransactionDO_db.getTransactionId()); + Assertions.assertEquals(globalTransactionDO_db.getStatus(), globalTransactionDO_db.getStatus()); + Assertions.assertEquals(globalTransactionDO_db.getTimeout(), globalTransactionDO_db.getTimeout()); + Assertions.assertEquals(globalTransactionDO_db.getTransactionServiceGroup(), globalTransactionDO_db.getTransactionServiceGroup()); + Assertions.assertEquals(globalTransactionDO_db.getApplicationId(), globalTransactionDO_db.getApplicationId()); + Assertions.assertNotNull(globalTransactionDO_db.getGmtCreate()); + Assertions.assertNotNull(globalTransactionDO_db.getGmtModified()); + + + String delSql = "delete from global_table where xid= 'abc-123:978786'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + //delete + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + + } + + @Test + public void queryGlobalTransactionDO_by_transaction_id() throws SQLException { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:676787978"); + globalTransactionDO.setApplicationData("abc=234356"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(867978970); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + + GlobalTransactionDO globalTransactionDO_db = logStoreDataBaseDAO.queryGlobalTransactionDO(867978970L); + Assertions.assertNotNull(globalTransactionDO_db); + + Assertions.assertEquals(globalTransactionDO_db.getXid(), globalTransactionDO_db.getXid()); + Assertions.assertEquals(globalTransactionDO_db.getBeginTime(), globalTransactionDO_db.getBeginTime()); + Assertions.assertEquals(globalTransactionDO_db.getTransactionName(), globalTransactionDO_db.getTransactionName()); + Assertions.assertEquals(globalTransactionDO_db.getTransactionId(), globalTransactionDO_db.getTransactionId()); + Assertions.assertEquals(globalTransactionDO_db.getStatus(), globalTransactionDO_db.getStatus()); + Assertions.assertEquals(globalTransactionDO_db.getTimeout(), globalTransactionDO_db.getTimeout()); + Assertions.assertEquals(globalTransactionDO_db.getTransactionServiceGroup(), globalTransactionDO_db.getTransactionServiceGroup()); + Assertions.assertEquals(globalTransactionDO_db.getApplicationId(), globalTransactionDO_db.getApplicationId()); + Assertions.assertNotNull(globalTransactionDO_db.getGmtCreate()); + Assertions.assertNotNull(globalTransactionDO_db.getGmtModified()); + + String delSql = "delete from global_table where xid= 'abc-123:978786'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + //delete + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + + } + + @Test + public void queryGlobalTransactionDO_by_statuses() throws SQLException { + { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:1267"); + globalTransactionDO.setApplicationData("abc=234356"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(867978970); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + Assertions.assertTrue(logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO)); + } + { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:6978"); + globalTransactionDO.setApplicationData("abc=87867978"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(143546567); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(2); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + } + { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:5657"); + globalTransactionDO.setApplicationData("abc=5454"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(12345); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + } + + List globalTransactionDOs = logStoreDataBaseDAO.queryGlobalTransactionDO(new int[]{1}, 10); + Assertions.assertNotNull(globalTransactionDOs); + Assertions.assertEquals(2, globalTransactionDOs.size()); + + if("abc-123:5657".equals(globalTransactionDOs.get(0).getXid()) && "abc-123:1267".equals(globalTransactionDOs.get(1).getXid())){ + Assertions.assertTrue(true); + }else if("abc-123:5657".equals(globalTransactionDOs.get(1).getXid()) && "abc-123:1267".equals(globalTransactionDOs.get(0).getXid())){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + + String delSql = "delete from global_table where xid in ('abc-123:1267', 'abc-123:6978', 'abc-123:5657')"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void queryGlobalTransactionDO_by_statuses_limit() throws SQLException { + { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:1267"); + globalTransactionDO.setApplicationData("abc=234356"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(867978970); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + Assertions.assertTrue(logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO)); + } + { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:6978"); + globalTransactionDO.setApplicationData("abc=87867978"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(143546567); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(2); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + } + { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:5657"); + globalTransactionDO.setApplicationData("abc=5454"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(12345); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + } + + List globalTransactionDOs = logStoreDataBaseDAO.queryGlobalTransactionDO(new int[]{1}, 1); + Assertions.assertNotNull(globalTransactionDOs); + Assertions.assertEquals(1, globalTransactionDOs.size()); + + if("abc-123:1267".equals(globalTransactionDOs.get(0).getXid())){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + + String delSql = "delete from global_table where xid in ('abc-123:1267', 'abc-123:6978', 'abc-123:5657')"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + + } + + @Test + public void insertGlobalTransactionDO() throws SQLException { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:333"); + globalTransactionDO.setApplicationData("abc=5454"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(12345); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + + String sql = "select * from global_table where xid= 'abc-123:333'"; + String delSql = "delete from global_table where xid= 'abc-123:333'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else{ + Assertions.assertTrue(false); + } + + conn.createStatement().execute(delSql); + + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void updateGlobalTransactionDO() throws SQLException { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:222"); + globalTransactionDO.setApplicationData("abc=5454"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(12345); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + + String sql = "select * from global_table where xid= 'abc-123:222'"; + String delSql = "delete from global_table where xid= 'abc-123:222'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + Assertions.assertEquals(1, rs.getInt("status")); + }else{ + Assertions.assertTrue(false); + } + rs.close(); + + //update + globalTransactionDO.setStatus(2); + Assertions.assertTrue(logStoreDataBaseDAO.updateGlobalTransactionDO(globalTransactionDO)); + + rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + Assertions.assertEquals(2, rs.getInt("status")); + }else{ + Assertions.assertTrue(false); + } + rs.close(); + + //delete + conn.createStatement().execute(delSql); + + }finally { + if(conn != null){ + conn.close(); + } + } + + } + + @Test + public void deleteGlobalTransactionDO() throws SQLException { + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid("abc-123:555"); + globalTransactionDO.setApplicationData("abc=5454"); + globalTransactionDO.setTransactionServiceGroup("abc"); + globalTransactionDO.setTransactionName("test"); + globalTransactionDO.setTransactionId(12345); + globalTransactionDO.setTimeout(20); + globalTransactionDO.setBeginTime(System.currentTimeMillis()); + globalTransactionDO.setApplicationId("test"); + globalTransactionDO.setStatus(1); + + boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); + Assertions.assertTrue(ret); + + //delete + Assertions.assertTrue(logStoreDataBaseDAO.deleteGlobalTransactionDO(globalTransactionDO)); + + //check + + String sql = "select * from global_table where xid= 'abc-123:555'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(false); + }else{ + Assertions.assertTrue(true); + } + rs.close(); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void queryBranchTransactionDO() throws SQLException { + { + //creata data for test + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setResourceId("qqqq"); + branchTransactionDO.setXid("abc-123:6789"); + branchTransactionDO.setTransactionId(24234235); + branchTransactionDO.setBranchId(345465676); + branchTransactionDO.setBranchType("TCC"); + branchTransactionDO.setResourceGroupId("abc"); + branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); + branchTransactionDO.setResourceGroupId("a"); + branchTransactionDO.setClientId("1.1.1.1"); + branchTransactionDO.setStatus(1); + branchTransactionDO.setApplicationData("abc=123"); + branchTransactionDO.setResourceGroupId("test"); + + boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); + Assertions.assertTrue(ret); + } + { + //creata data for test + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setResourceId("qqqq"); + branchTransactionDO.setXid("abc-123:6789"); + branchTransactionDO.setTransactionId(24234235); + branchTransactionDO.setBranchId(78563453); + branchTransactionDO.setBranchType("TCC"); + branchTransactionDO.setResourceGroupId("abc"); + branchTransactionDO.setLockKey("t:6;t2:7"); + branchTransactionDO.setResourceGroupId("a"); + branchTransactionDO.setClientId("1.1.1.1"); + branchTransactionDO.setStatus(1); + branchTransactionDO.setApplicationData("abc=123"); + branchTransactionDO.setResourceGroupId("test"); + + boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); + Assertions.assertTrue(ret); + } + + List rets = logStoreDataBaseDAO.queryBranchTransactionDO("abc-123:6789"); + Assertions.assertTrue(CollectionUtils.isNotEmpty(rets)); + Assertions.assertEquals(2, rets.size()); + + if(78563453 == rets.get(0).getBranchId() && 345465676 == rets.get(1).getBranchId()){ + Assertions.assertTrue(true); + }else if(78563453 == rets.get(1).getBranchId() && 345465676 == rets.get(0).getBranchId()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + + String delSql = "delete from branch_table where xid= 'abc-123:6789' "; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + + conn.createStatement().execute(delSql); + + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void insertBranchTransactionDO() throws SQLException { + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setResourceId("qqqq"); + branchTransactionDO.setXid("abc-123:7777"); + branchTransactionDO.setTransactionId(1285343); + branchTransactionDO.setBranchId(1234508); + branchTransactionDO.setBranchType("TCC"); + branchTransactionDO.setResourceGroupId("abc"); + branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); + branchTransactionDO.setResourceGroupId("a"); + branchTransactionDO.setClientId("1.1.1.1"); + branchTransactionDO.setStatus(1); + branchTransactionDO.setApplicationData("abc=123"); + branchTransactionDO.setResourceGroupId("test"); + + boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); + Assertions.assertTrue(ret); + + + String sql = "select * from branch_table where xid= 'abc-123:7777' and branch_id = 1234508"; + String delSql = "delete from branch_table where xid= 'abc-123:7777' and branch_id = 1234508"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + + } + + @Test + public void updateBranchTransactionDO() throws SQLException { + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setResourceId("qqqq"); + branchTransactionDO.setXid("abc-123:8888"); + branchTransactionDO.setTransactionId(1285343); + branchTransactionDO.setBranchId(343434318); + branchTransactionDO.setBranchType("TCC"); + branchTransactionDO.setResourceGroupId("abc"); + branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); + branchTransactionDO.setResourceGroupId("a"); + branchTransactionDO.setClientId("1.1.1.1"); + branchTransactionDO.setStatus(1); + branchTransactionDO.setApplicationData("abc=123"); + branchTransactionDO.setResourceGroupId("test"); + + boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); + Assertions.assertTrue(ret); + + branchTransactionDO.setStatus(3); + Assertions.assertTrue(logStoreDataBaseDAO.updateBranchTransactionDO(branchTransactionDO)); + + String sql = "select * from branch_table where xid= 'abc-123:8888' and branch_id = 343434318"; + String delSql = "delete from branch_table where xid= 'abc-123:8888' and branch_id = 343434318"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + Assertions.assertEquals(3, rs.getInt("status")); + }else { + Assertions.assertTrue(false); + } + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void deleteBranchTransactionDO() throws SQLException { + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setResourceId("qqqq"); + branchTransactionDO.setXid("abc-123:9999"); + branchTransactionDO.setTransactionId(1285343); + branchTransactionDO.setBranchId(34567798); + branchTransactionDO.setBranchType("TCC"); + branchTransactionDO.setResourceGroupId("abc"); + branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); + branchTransactionDO.setResourceGroupId("a"); + branchTransactionDO.setClientId("1.1.1.1"); + branchTransactionDO.setStatus(1); + branchTransactionDO.setApplicationData("abc=123"); + branchTransactionDO.setResourceGroupId("test"); + + boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); + Assertions.assertTrue(ret); + + + String sql = "select * from branch_table where xid= 'abc-123:9999' and branch_id = 34567798"; + String delSql = "delete from branch_table where xid= 'abc-123:9999' and branch_id = 34567798"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + rs.close(); + + //delete + logStoreDataBaseDAO.deleteBranchTransactionDO(branchTransactionDO); + + rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(false); + }else { + Assertions.assertTrue(true); + } + rs.close(); + + }finally { + if(conn != null){ + conn.close(); + } + } + } + +} \ No newline at end of file diff --git a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java new file mode 100644 index 00000000000..663234beea1 --- /dev/null +++ b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.config; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * @author Geng Zhang + */ +class ConfigurationFactoryTest { + + @Test + void getInstance() { + Configuration configuration = ConfigurationFactory.getInstance(); + // check singleton + Assertions.assertEquals(configuration, ConfigurationFactory.getInstance()); + } +} \ No newline at end of file diff --git a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java index 8687246b90f..ceedb26bd64 100644 --- a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java +++ b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java @@ -16,7 +16,6 @@ package io.seata.discovery.registry.eureka; import io.seata.common.loader.LoadLevel; -import io.seata.discovery.registry.RegistryProvider; import io.seata.discovery.registry.RegistryService; import io.seata.discovery.registry.RegistryProvider; diff --git a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java index 1acd0db7f7e..d201ce29c22 100644 --- a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java +++ b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java @@ -16,7 +16,6 @@ package io.seata.discovery.registry.nacos; import io.seata.common.loader.LoadLevel; -import io.seata.discovery.registry.RegistryProvider; import io.seata.discovery.registry.RegistryService; import io.seata.discovery.registry.RegistryProvider; diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java index 4585a45b092..10bd29dcae9 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java @@ -18,8 +18,6 @@ import io.seata.common.loader.LoadLevel; import io.seata.discovery.registry.RegistryProvider; import io.seata.discovery.registry.RegistryService; -import io.seata.discovery.registry.RegistryProvider; -import io.seata.discovery.registry.RegistryService; /** * @author xingfudeshi@gmail.com diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java index 9c1d87a8810..1ea76541b20 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java @@ -34,7 +34,6 @@ import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; -import io.seata.discovery.registry.RegistryService; import io.seata.discovery.registry.RegistryService; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; diff --git a/pom.xml b/pom.xml index e3628dda535..d657ed812a4 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ - 0.5.2 + 0.6.0 1.8 @@ -107,6 +107,7 @@ 2.23.4 3.12.2 1.4.2 + @@ -142,7 +143,6 @@ test - diff --git a/rm-datasource/pom.xml b/rm-datasource/pom.xml index 8ab21440bb4..3b1a0435f45 100644 --- a/rm-datasource/pom.xml +++ b/rm-datasource/pom.xml @@ -48,6 +48,17 @@ caffeine + + commons-dbcp + commons-dbcp + test + + + com.h2database + h2 + test + + diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java index b835dc354ab..40adc924fa6 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java @@ -37,7 +37,6 @@ import java.util.Calendar; import java.util.List; -import io.seata.rm.datasource.sql.struct.Null; import io.seata.rm.datasource.sql.struct.Null; /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java index f6076f88204..dd5f1baa2c3 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java @@ -178,7 +178,7 @@ private void doBranchCommits() { int maxSize = xids.size() > branchIds.size() ? xids.size() : branchIds.size(); if(maxSize == UNDOLOG_DELETE_LIMIT_SIZE){ try { - UndoLogManager.batchDeleteUndoLog(xids, branchIds, UNDOLOG_DELETE_LIMIT_SIZE, conn); + UndoLogManager.batchDeleteUndoLog(xids, branchIds, conn); } catch (Exception ex) { LOGGER.warn("Failed to batch delete undo log [" + branchIds + "/" + xids + "]", ex); } @@ -192,7 +192,7 @@ private void doBranchCommits() { } try { - UndoLogManager.batchDeleteUndoLog(xids, branchIds, UNDOLOG_DELETE_LIMIT_SIZE, conn); + UndoLogManager.batchDeleteUndoLog(xids, branchIds, conn); }catch (Exception ex) { LOGGER.warn("Failed to batch delete undo log [" + branchIds + "/" + xids + "]", ex); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java index 5279ad772d7..492d59be5f2 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java @@ -20,8 +20,6 @@ import java.sql.SQLException; import java.util.ArrayList; -import io.seata.rm.datasource.exec.ExecuteTemplate; -import io.seata.rm.datasource.exec.StatementCallback; import io.seata.rm.datasource.exec.ExecuteTemplate; import io.seata.rm.datasource.exec.StatementCallback; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java index e0b1eb7ab68..955fc81c058 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java @@ -19,8 +19,6 @@ import java.sql.SQLException; import java.sql.Statement; -import io.seata.rm.datasource.exec.ExecuteTemplate; -import io.seata.rm.datasource.exec.StatementCallback; import io.seata.rm.datasource.exec.ExecuteTemplate; import io.seata.rm.datasource.exec.StatementCallback; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java index 6a3f3f848b5..26507eb74f3 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java @@ -29,8 +29,6 @@ import io.seata.rm.datasource.sql.SQLRecognizer; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; -import io.seata.rm.datasource.undo.KeywordChecker; -import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.rm.datasource.undo.KeywordChecker; import io.seata.rm.datasource.undo.KeywordCheckerFactory; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java index be6537bfe12..26d87cd1d38 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java @@ -17,7 +17,6 @@ import java.util.ArrayList; -import io.seata.rm.datasource.ParametersHolder; import io.seata.rm.datasource.ParametersHolder; /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java index 779da87c8d1..36f14f97203 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java @@ -15,16 +15,25 @@ */ package io.seata.rm.datasource.undo; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; - +import com.alibaba.fastjson.JSON; +import io.seata.common.util.StringUtils; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; import io.seata.rm.datasource.DataCompareUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; import io.seata.rm.datasource.sql.struct.Row; +import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; /** * The type Abstract undo executor. @@ -34,6 +43,24 @@ */ public abstract class AbstractUndoExecutor { + /** + * Logger for AbstractUndoExecutor + **/ + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractUndoExecutor.class); + + /** + * template of check sql + * + * TODO support multiple primary key + */ + private static final String CHECK_SQL_TEMPLATE = "SELECT * FROM %s WHERE %s in (%s)"; + + /** + * Switch of undo data validation + */ + public static final boolean IS_UNDO_DATA_VALIDATION_ENABLE = ConfigurationFactory.getInstance() + .getBoolean(ConfigurationKeys.TRANSACTION_UNOD_DATA_VALIDATION, true); + /** * The Sql undo log. */ @@ -72,11 +99,10 @@ public SQLUndoLog getSqlUndoLog() { */ public void executeOn(Connection conn) throws SQLException { - // no need undo if the before data snapshot is equivalent to the after data snapshot. - if (DataCompareUtils.isRecordsEquals(sqlUndoLog.getBeforeImage(), sqlUndoLog.getAfterImage())) { + if (IS_UNDO_DATA_VALIDATION_ENABLE && !dataValidationAndGoOn(conn)) { return; } - dataValidation(conn); + try { String undoSQL = buildUndoSQL(); @@ -145,9 +171,125 @@ protected void undoPrepare(PreparedStatement undoPST, ArrayList undoValue * Data validation. * * @param conn the conn - * @throws SQLException the sql exception + * @return return true if data validation is ok and need continue undo, and return false if no need continue undo. + * @throws SQLException the sql exception such as has dirty data */ - protected void dataValidation(Connection conn) throws SQLException { + protected boolean dataValidationAndGoOn(Connection conn) throws SQLException { + + TableRecords beforeRecords = sqlUndoLog.getBeforeImage(); + TableRecords afterRecords = sqlUndoLog.getAfterImage(); + + // Compare current data with before data + // No need undo if the before data snapshot is equivalent to the after data snapshot. + if (DataCompareUtils.isRecordsEquals(beforeRecords, afterRecords)) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Stop rollback because there is no data change " + + "between the before data snapshot and the after data snapshot."); + } + // no need continue undo. + return false; + } + // Validate if data is dirty. + TableRecords currentRecords = queryCurrentRecords(conn); + // compare with current data and after image. + if (!DataCompareUtils.isRecordsEquals(afterRecords, currentRecords)) { + + // If current data is not equivalent to the after data, then compare the current data with the before + // data, too. No need continue to undo if current data is equivalent to the before data snapshot + if (DataCompareUtils.isRecordsEquals(beforeRecords, currentRecords)) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Stop rollback because there is no data change " + + "between the before data snapshot and the current data snapshot."); + } + // no need continue undo. + return false; + } else { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("check dirty datas failed, old and new data are not equal," + + "tableName:[" + sqlUndoLog.getTableName() + "]," + + "oldRows:[" + JSON.toJSONString(afterRecords.getRows()) + "]," + + "newRows:[" + JSON.toJSONString(currentRecords.getRows()) + "]."); + } + throw new SQLException("Has dirty records when undo."); + } + } + return true; + } + + /** + * Query current records. + * + * @param conn the conn + * @return the table records + * @throws SQLException the sql exception + */ + protected TableRecords queryCurrentRecords(Connection conn) throws SQLException { + TableRecords undoRecords = getUndoRows(); + TableMeta tableMeta = undoRecords.getTableMeta(); + String pkName = tableMeta.getPkName(); + int pkType = tableMeta.getColumnMeta(pkName).getDataType(); + + // pares pk values + Object[] pkValues = parsePkValues(getUndoRows()); + if (pkValues.length == 0) { + return TableRecords.empty(tableMeta); + } + StringBuffer replace = new StringBuffer(); + for (int i = 0; i < pkValues.length; i++) { + replace.append("?,"); + } + // build check sql + String checkSQL = String.format(CHECK_SQL_TEMPLATE, sqlUndoLog.getTableName(), pkName, + replace.substring(0, replace.length() - 1)); + + PreparedStatement statement = null; + ResultSet checkSet = null; + TableRecords currentRecords; + try { + statement = conn.prepareStatement(checkSQL); + for (int i = 1; i <= pkValues.length; i++) { + statement.setObject(i, pkValues[i - 1], pkType); + } + checkSet = statement.executeQuery(); + currentRecords = TableRecords.buildRecords(tableMeta, checkSet); + } finally { + if (checkSet != null) { + try { + checkSet.close(); + } catch (Exception e) { + } + } + if (statement != null) { + try { + statement.close(); + } catch (Exception e) { + } + } + } + return currentRecords; + } + + /** + * Parse pk values object [ ]. + * + * @param records the records + * @return the object [ ] + */ + protected Object[] parsePkValues(TableRecords records) { + String pkName = records.getTableMeta().getPkName(); + List undoRows = records.getRows(); + Object[] pkValues = new Object[undoRows.size()]; + for (int i = 0; i < undoRows.size(); i++) { + List fields = undoRows.get(i).getFields(); + if (fields != null) { + for (Field field : fields) { + if (StringUtils.equalsIgnoreCase(pkName, field.getName())) { + pkValues[i] = field.getValue(); + } + } + } + } + return pkValues; } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java index ab278f2e71f..deadf563778 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java @@ -18,7 +18,6 @@ import com.alibaba.druid.util.JdbcConstants; import io.seata.common.exception.NotSupportYetException; import io.seata.common.util.BlobUtils; -import io.seata.common.util.StringUtils; import io.seata.core.exception.TransactionException; import io.seata.rm.datasource.ConnectionContext; import io.seata.rm.datasource.ConnectionProxy; @@ -161,7 +160,7 @@ public static void undo(DataSourceProxy dataSourceProxy, String xid, long branch } Blob b = rs.getBlob("rollback_info"); - String rollbackInfo = StringUtils.blob2string(b); + String rollbackInfo = BlobUtils.blob2string(b); BranchUndoLog branchUndoLog = UndoLogParserFactory.getInstance().decode(rollbackInfo); for (SQLUndoLog sqlUndoLog : branchUndoLog.getSqlUndoLogs()) { @@ -234,13 +233,12 @@ public static void undo(DataSourceProxy dataSourceProxy, String xid, long branch * * @param xids * @param branchIds - * @param limitSize * @param conn */ - public static void batchDeleteUndoLog(Set xids, Set branchIds, int limitSize, Connection conn) throws SQLException { + public static void batchDeleteUndoLog(Set xids, Set branchIds, Connection conn) throws SQLException { int xidSize = xids.size(); int branchIdSize = branchIds.size(); - String batchDeleteSql = toBatchDeleteUndoLogSql(xidSize, branchIdSize,limitSize); + String batchDeleteSql = toBatchDeleteUndoLogSql(xidSize, branchIdSize); PreparedStatement deletePST = null; try { deletePST = conn.prepareStatement(batchDeleteSql); @@ -268,15 +266,14 @@ public static void batchDeleteUndoLog(Set xids, Set branchIds, int } - protected static String toBatchDeleteUndoLogSql(int xidSize, int branchIdSize,int limitSize) { + protected static String toBatchDeleteUndoLogSql(int xidSize, int branchIdSize) { StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.append("DELETE FROM ") .append(UNDO_LOG_TABLE_NAME) .append(" WHERE branch_id IN "); - appendInParam(xidSize, sqlBuilder); - sqlBuilder.append(" AND xid IN "); appendInParam(branchIdSize, sqlBuilder); - sqlBuilder.append(" LIMIT ").append(limitSize); + sqlBuilder.append(" AND xid IN "); + appendInParam(xidSize, sqlBuilder); return sqlBuilder.toString(); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java new file mode 100644 index 00000000000..0d79fa178d0 --- /dev/null +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java @@ -0,0 +1,316 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.rm.datasource.undo; + +import io.seata.rm.datasource.sql.SQLType; +import io.seata.rm.datasource.sql.struct.ColumnMeta; +import io.seata.rm.datasource.sql.struct.Field; +import io.seata.rm.datasource.sql.struct.Row; +import io.seata.rm.datasource.sql.struct.TableMeta; +import io.seata.rm.datasource.sql.struct.TableRecords; +import org.apache.commons.dbcp.BasicDataSource; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Geng Zhang + */ +public class AbstractUndoExecutorTest extends BaseExecutorTest { + + static BasicDataSource dataSource = null; + + static Connection connection = null; + + static TableMeta tableMeta = null; + + @BeforeAll + public static void start() throws SQLException { + dataSource = new BasicDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUrl("jdbc:h2:./db_store/test_undo"); + dataSource.setUsername("sa"); + dataSource.setPassword(""); + + connection = dataSource.getConnection(); + + tableMeta = mockTableMeta(); + } + + @AfterAll + public static void stop() { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + } + } + if (dataSource != null) { + try { + dataSource.close(); + } catch (SQLException e) { + } + } + } + + @BeforeEach + private void prepareTable() { + execSQL("DROP TABLE table_name"); + execSQL("CREATE TABLE table_name ( `id` int(8), `name` varchar(64), PRIMARY KEY (`id`))"); + } + + @Test + public void dataValidationUpdate() throws SQLException { + execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); + execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); + + TableRecords beforeImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + + execSQL("update table_name set name = 'xxx' where id in (12345, 12346);"); + + TableRecords afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + + SQLUndoLog sqlUndoLog = new SQLUndoLog(); + sqlUndoLog.setSqlType(SQLType.UPDATE); + sqlUndoLog.setTableMeta(tableMeta); + sqlUndoLog.setTableName("table_name"); + sqlUndoLog.setBeforeImage(beforeImage); + sqlUndoLog.setAfterImage(afterImage); + + TestUndoExecutor spy = new TestUndoExecutor(sqlUndoLog, false); + + // case1: normal case before:aaa -> after:xxx -> current:xxx + Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); + + // case2: dirty data before:aaa -> after:xxx -> current:yyy + execSQL("update table_name set name = 'yyy' where id in (12345, 12346);"); + try { + spy.dataValidationAndGoOn(connection); + Assertions.fail(); + } catch (Exception e) { + Assertions.assertTrue(e instanceof SQLException); + } + + // case 3: before == current before:aaa -> after:xxx -> current:aaa + execSQL("update table_name set name = 'aaa' where id in (12345, 12346);"); + Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); + + // case 4: before == after before:aaa -> after:aaa + afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + sqlUndoLog.setAfterImage(afterImage); + Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); + } + + @Test + public void dataValidationInsert() throws SQLException { + TableRecords beforeImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + + execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); + execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); + + TableRecords afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + + SQLUndoLog sqlUndoLog = new SQLUndoLog(); + sqlUndoLog.setSqlType(SQLType.INSERT); + sqlUndoLog.setTableMeta(tableMeta); + sqlUndoLog.setTableName("table_name"); + sqlUndoLog.setBeforeImage(beforeImage); + sqlUndoLog.setAfterImage(afterImage); + + TestUndoExecutor spy = new TestUndoExecutor(sqlUndoLog, false); + + // case1: normal case before:0 -> after:2 -> current:2 + Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); + + // case2: dirty data before:0 -> after:2 -> current:2' + execSQL("update table_name set name = 'yyy' where id in (12345, 12346);"); + try { + Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); + Assertions.fail(); + } catch (Exception e) { + Assertions.assertTrue(e instanceof SQLException); + } + + // case3: before == current before:0 -> after:2 -> current:0 + execSQL("delete from table_name where id in (12345, 12346);"); + Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); + + // case 4: before == after before:0 -> after:0 + afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + sqlUndoLog.setAfterImage(afterImage); + Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); + } + + @Test + public void dataValidationDelete() throws SQLException { + execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); + execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); + + TableRecords beforeImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + + execSQL("delete from table_name where id in (12345, 12346);"); + + TableRecords afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + + SQLUndoLog sqlUndoLog = new SQLUndoLog(); + sqlUndoLog.setSqlType(SQLType.INSERT); + sqlUndoLog.setTableMeta(tableMeta); + sqlUndoLog.setTableName("table_name"); + sqlUndoLog.setBeforeImage(beforeImage); + sqlUndoLog.setAfterImage(afterImage); + + TestUndoExecutor spy = new TestUndoExecutor(sqlUndoLog, true); + + // case1: normal case before:2 -> after:0 -> current:0 + Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); + + // case2: dirty data before:2 -> after:0 -> current:1 + execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); + try { + Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); + Assertions.fail(); + } catch (Exception e) { + Assertions.assertTrue(e instanceof SQLException); + } + + // case3: before == current before:2 -> after:0 -> current:2 + execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); + Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); + + // case 4: before == after before:2 -> after:2 + afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); + sqlUndoLog.setAfterImage(afterImage); + Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); + } + + @Test + public void testParsePK() { + TableMeta tableMeta = Mockito.mock(TableMeta.class); + Mockito.when(tableMeta.getPkName()).thenReturn("id"); + Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); + + TableRecords beforeImage = new TableRecords(); + beforeImage.setTableName("table_name"); + beforeImage.setTableMeta(tableMeta); + + List beforeRows = new ArrayList<>(); + Row row0 = new Row(); + Field field01 = addField(row0, "id", 1, "12345"); + Field field02 = addField(row0, "age", 1, "2"); + beforeRows.add(row0); + Row row1 = new Row(); + Field field11 = addField(row1, "id", 1, "12346"); + Field field12 = addField(row1, "age", 1, "2"); + beforeRows.add(row1); + beforeImage.setRows(beforeRows); + + SQLUndoLog sqlUndoLog = new SQLUndoLog(); + sqlUndoLog.setSqlType(SQLType.UPDATE); + sqlUndoLog.setTableMeta(tableMeta); + sqlUndoLog.setTableName("table_name"); + sqlUndoLog.setBeforeImage(beforeImage); + sqlUndoLog.setAfterImage(null); + + TestUndoExecutor executor = new TestUndoExecutor(sqlUndoLog, true); + Object[] pkValues = executor.parsePkValues(beforeImage); + Assertions.assertEquals(2, pkValues.length); + } + + + private static TableMeta mockTableMeta() { + TableMeta tableMeta = Mockito.mock(TableMeta.class); + Mockito.when(tableMeta.getPkName()).thenReturn("ID"); + Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); + ColumnMeta meta0 = Mockito.mock(ColumnMeta.class); + Mockito.when(meta0.getDataType()).thenReturn(Types.INTEGER); + Mockito.when(meta0.getColumnName()).thenReturn("ID"); + Mockito.when(tableMeta.getColumnMeta("ID")).thenReturn(meta0); + ColumnMeta meta1 = Mockito.mock(ColumnMeta.class); + Mockito.when(meta1.getDataType()).thenReturn(Types.VARCHAR); + Mockito.when(meta1.getColumnName()).thenReturn("NAME"); + Mockito.when(tableMeta.getColumnMeta("NAME")).thenReturn(meta1); + return tableMeta; + } + + private void execSQL(String sql) { + Statement s = null; + try { + s = connection.createStatement(); + s.execute(sql); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (s != null) { + try { + s.close(); + } catch (SQLException e) { + } + } + } + } + + private TableRecords execQuery(TableMeta tableMeta, String sql) throws SQLException { + Statement s = null; + ResultSet set = null; + try { + s = connection.createStatement(); + set = s.executeQuery(sql); + return TableRecords.buildRecords(tableMeta, set); + } finally { + if (set != null) { + try { + set.close(); + } catch (Exception e) { + } + } + if (s != null) { + try { + s.close(); + } catch (SQLException e) { + } + } + } + } +} + +class TestUndoExecutor extends AbstractUndoExecutor { + private boolean isDelete; + public TestUndoExecutor(SQLUndoLog sqlUndoLog, boolean isDelete) { + super(sqlUndoLog); + this.isDelete = isDelete; + } + + @Override + protected String buildUndoSQL() { + return null; + } + + @Override + protected TableRecords getUndoRows() { + return isDelete ? sqlUndoLog.getBeforeImage() : sqlUndoLog.getAfterImage(); + } +} diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java index eb7a0324bb2..ae1174c8c5c 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java @@ -59,6 +59,7 @@ import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; /** * The type Undo executor test. @@ -88,7 +89,7 @@ public void testField() { * Test update. */ @Test - public void testUpdate() { + public void testUpdate() throws SQLException { SQLUndoLog SQLUndoLog = new SQLUndoLog(); SQLUndoLog.setTableName("my_test_table"); SQLUndoLog.setSqlType(SQLType.UPDATE); @@ -147,19 +148,18 @@ public void testUpdate() { SQLUndoLog.setAfterImage(afterImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - - try { - executor.executeOn(new MockConnection()); - } catch (SQLException e) { - e.printStackTrace(); - } + MockConnection connection = new MockConnection(); + AbstractUndoExecutor spy = Mockito.spy(executor); + // skip data validation + Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); + spy.executeOn(connection); } /** * Test insert. */ @Test - public void testInsert() { + public void testInsert() throws SQLException { SQLUndoLog SQLUndoLog = new SQLUndoLog(); SQLUndoLog.setTableName("my_test_table"); SQLUndoLog.setSqlType(SQLType.INSERT); @@ -217,19 +217,18 @@ public void testInsert() { SQLUndoLog.setAfterImage(afterImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - - try { - executor.executeOn(new MockConnection()); - } catch (SQLException e) { - e.printStackTrace(); - } + MockConnection connection = new MockConnection(); + AbstractUndoExecutor spy = Mockito.spy(executor); + // skip data validation + Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); + spy.executeOn(connection); } /** * Test delete. */ @Test - public void testDelete() { + public void testDelete() throws SQLException { SQLUndoLog SQLUndoLog = new SQLUndoLog(); SQLUndoLog.setTableName("my_test_table"); SQLUndoLog.setSqlType(SQLType.DELETE); @@ -287,12 +286,11 @@ public void testDelete() { SQLUndoLog.setBeforeImage(beforeImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - - try { - executor.executeOn(new MockConnection()); - } catch (SQLException e) { - e.printStackTrace(); - } + MockConnection connection = new MockConnection(); + AbstractUndoExecutor spy = Mockito.spy(executor); + // skip data validation + Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); + spy.executeOn(connection); } /** diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java index dcc8f5d4ddc..e8fe5504dc9 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java @@ -40,9 +40,10 @@ public class UndoLogManagerTest { private static final int APPEND_IN_SIZE = 10; - private static final int LIMIT_SIZE = 10; - private static final String THE_APPEND_IN_SIZE_PARAM_String = " (?,?,?,?,?,?,?,?,?,?) "; + private static final String THE_APPEND_IN_SIZE_PARAM_STRING = " (?,?,?,?,?,?,?,?,?,?) "; + + private static final String THE_DOUBLE_APPEND_IN_SIZE_PARAM_STRING = " (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; @Test public void testBatchDeleteUndoLog() throws Exception { @@ -57,7 +58,7 @@ public void testBatchDeleteUndoLog() throws Exception { Connection connection = mock(Connection.class); PreparedStatement preparedStatement = mock(PreparedStatement.class); when(connection.prepareStatement(anyString())).thenReturn(preparedStatement); - UndoLogManager.batchDeleteUndoLog(xids, branchIds, LIMIT_SIZE, connection); + UndoLogManager.batchDeleteUndoLog(xids, branchIds, connection); //verify for (int i = 1;i <= APPEND_IN_SIZE;i++){ @@ -72,11 +73,10 @@ public void testBatchDeleteUndoLog() throws Exception { @Test public void testToBatchDeleteUndoLogSql() { String expectedSqlString="DELETE FROM undo_log WHERE branch_id IN " + - THE_APPEND_IN_SIZE_PARAM_String + + THE_APPEND_IN_SIZE_PARAM_STRING + " AND xid IN " + - THE_APPEND_IN_SIZE_PARAM_String + - " LIMIT " + LIMIT_SIZE; - String batchDeleteUndoLogSql = UndoLogManager.toBatchDeleteUndoLogSql(APPEND_IN_SIZE, APPEND_IN_SIZE, LIMIT_SIZE); + THE_DOUBLE_APPEND_IN_SIZE_PARAM_STRING; + String batchDeleteUndoLogSql = UndoLogManager.toBatchDeleteUndoLogSql(APPEND_IN_SIZE * 2, APPEND_IN_SIZE); System.out.println(batchDeleteUndoLogSql); assertThat(batchDeleteUndoLogSql).isEqualTo(expectedSqlString); } @@ -85,7 +85,7 @@ public void testToBatchDeleteUndoLogSql() { public void testAppendInParam() { StringBuilder sqlBuilder = new StringBuilder(); UndoLogManager.appendInParam(APPEND_IN_SIZE, sqlBuilder); - assertThat(sqlBuilder.toString()).isEqualTo(THE_APPEND_IN_SIZE_PARAM_String); + assertThat(sqlBuilder.toString()).isEqualTo(THE_APPEND_IN_SIZE_PARAM_STRING); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java index 879b77a88cd..a3fd52afb1a 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java @@ -26,7 +26,6 @@ import io.seata.rm.datasource.undo.KeywordChecker; import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.rm.datasource.undo.SQLUndoLog; -import io.seata.rm.datasource.undo.UndoExecutorTest; import io.seata.rm.datasource.undo.mysql.MySQLUndoDeleteExecutor; import io.seata.rm.datasource.undo.mysql.MySQLUndoInsertExecutor; import io.seata.rm.datasource.undo.mysql.MySQLUndoUpdateExecutor; diff --git a/server/pom.xml b/server/pom.xml index 55290bec0ee..870f8187e7a 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -45,6 +45,24 @@ ${project.version} + + + com.alibaba + druid + + + commons-dbcp + commons-dbcp + + + com.h2database + h2 + + + mysql + mysql-connector-java + + diff --git a/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java b/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java index d6655196eee..89fcbe94740 100644 --- a/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java +++ b/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java @@ -15,7 +15,6 @@ */ package io.seata.server; -import io.seata.common.XID; import io.seata.core.exception.AbstractExceptionHandler; import io.seata.core.exception.TransactionException; import io.seata.core.model.GlobalStatus; @@ -106,8 +105,7 @@ public void execute(GlobalRollbackRequest request, GlobalRollbackResponse respon public void onTransactionException(GlobalRollbackRequest request, GlobalRollbackResponse response, TransactionException tex) { super.onTransactionException(request, response, tex); - GlobalSession globalSession = SessionHolder.findGlobalSession( - XID.getTransactionId(request.getXid())); + GlobalSession globalSession = SessionHolder.findGlobalSession(request.getXid()); if (globalSession != null) { response.setGlobalStatus(globalSession.getStatus()); } else { @@ -118,8 +116,7 @@ public void onTransactionException(GlobalRollbackRequest request, GlobalRollback @Override public void onException(GlobalRollbackRequest request, GlobalRollbackResponse response, Exception rex) { super.onException(request, response, rex); - GlobalSession globalSession = SessionHolder.findGlobalSession( - XID.getTransactionId(request.getXid())); + GlobalSession globalSession = SessionHolder.findGlobalSession(request.getXid()); if (globalSession != null) { response.setGlobalStatus(globalSession.getStatus()); } else { diff --git a/server/src/main/java/io/seata/server/Server.java b/server/src/main/java/io/seata/server/Server.java index 92273a3e68f..0cec9d18b87 100644 --- a/server/src/main/java/io/seata/server/Server.java +++ b/server/src/main/java/io/seata/server/Server.java @@ -42,7 +42,7 @@ public class Server { private static final int SERVER_DEFAULT_PORT = 8091; private static final ThreadPoolExecutor WORKING_THREADS = new ThreadPoolExecutor(MIN_SERVER_POOL_SIZE, MAX_SERVER_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, - new LinkedBlockingQueue(MAX_TASK_QUEUE_SIZE), + new LinkedBlockingQueue<>(MAX_TASK_QUEUE_SIZE), new NamedThreadFactory("ServerHandlerThread", MAX_SERVER_POOL_SIZE), new ThreadPoolExecutor.CallerRunsPolicy()); /** diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index 15063da2cb2..18c1e80395f 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -16,13 +16,17 @@ package io.seata.server.coordinator; import java.io.IOException; +import java.time.Duration; import java.util.Collection; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import io.seata.common.XID; import io.seata.common.thread.NamedThreadFactory; +import io.seata.common.util.CollectionUtils; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.common.util.DurationUtil; +import io.seata.config.ConfigurationFactory; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; @@ -78,6 +82,44 @@ public class DefaultCoordinator extends AbstractTCInboundHandler private static final int TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS = 5000; + /** + * The Committing retry delay. + */ + protected int committingRetryDelay = CONFIG.getInt(ConfigurationKeys.COMMITING_RETRY_DELAY, 5); + + /** + * The Asyn committing retry delay. + */ + protected int asynCommittingRetryDelay = CONFIG.getInt(ConfigurationKeys.ASYN_COMMITING_RETRY_DELAY, 5); + + /** + * The Rollbacking retry delay. + */ + protected int rollbackingRetryDelay = CONFIG.getInt(ConfigurationKeys.ROLLBACKING_RETRY_DELAY, 5); + + /** + * The Timeout retry delay. + */ + protected int timeoutRetryDelay = CONFIG.getInt(ConfigurationKeys.TIMEOUT_RETRY_DELAY, 5); + + private static final int ALWAYS_RETRY_BOUNDARY = 0; + + private static final Duration MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration(ConfigurationKeys.SERVICE_PREFIX + "max.commit.retry.timeout", DurationUtil.DEFAULT_DURATION, 100); + + private static final Duration MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration(ConfigurationKeys.SERVICE_PREFIX + "max.rollback.retry.timeout", DurationUtil.DEFAULT_DURATION, 100); + + private ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("RetryRollbacking", 1)); + + private ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("RetryCommitting", 1)); + + private ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("AsyncCommitting", 1)); + + private ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("TxTimeoutCheck", 1)); + private ServerMessageSender messageSender; private Core core = CoreFactory.get(); @@ -156,7 +198,7 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI request.setApplicationData(applicationData); request.setBranchType(branchType); - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); if(globalSession == null){ return BranchStatus.PhaseTwo_Committed; } @@ -165,9 +207,7 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI BranchCommitResponse response = (BranchCommitResponse)messageSender.sendSyncRequest(resourceId, branchSession.getClientId(), request); return response.getBranchStatus(); - } catch (IOException e) { - throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e); - } catch (TimeoutException e) { + } catch (IOException | TimeoutException e) { throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e); } } @@ -185,7 +225,7 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc request.setApplicationData(applicationData); request.setBranchType(branchType); - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); if(globalSession == null){ return BranchStatus.PhaseTwo_Rollbacked; } @@ -194,27 +234,34 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc BranchRollbackResponse response = (BranchRollbackResponse)messageSender.sendSyncRequest(resourceId, branchSession.getClientId(), request); return response.getBranchStatus(); - } catch (IOException e) { - throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e); - } catch (TimeoutException e) { + } catch (IOException | TimeoutException e) { throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e); } } - private void timeoutCheck() throws TransactionException { + /** + * Timeout check. + * + * @throws TransactionException the transaction exception + */ + protected void timeoutCheck() throws TransactionException { Collection allSessions = SessionHolder.getRootSessionManager().allSessions(); + if(CollectionUtils.isEmpty(allSessions)){ + return; + } if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) { LOGGER.debug("Transaction Timeout Check Begin: " + allSessions.size()); } for (GlobalSession globalSession : allSessions) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(globalSession.getTransactionId() + " " + globalSession.getStatus() + " " + + LOGGER.debug(globalSession.getXid() + " " + globalSession.getStatus() + " " + globalSession.getBeginTime() + " " + globalSession.getTimeout()); } boolean shouldTimeout = globalSession.lockAndExcute(() -> { if (globalSession.getStatus() != GlobalStatus.Begin || !globalSession.isTimeout()) { return false; } + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.close(); globalSession.changeStatus(GlobalStatus.TimeoutRollbacking); return true; @@ -223,7 +270,7 @@ private void timeoutCheck() throws TransactionException { continue; } LOGGER.info( - "Global transaction[" + globalSession.getTransactionId() + "] is timeout and will be rolled back."); + "Global transaction[" + globalSession.getXid() + "] is timeout and will be rolled back."); globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager()); SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession); @@ -235,107 +282,129 @@ private void timeoutCheck() throws TransactionException { } - private void handleRetryRollbacking() { + /** + * Handle retry rollbacking. + */ + protected void handleRetryRollbacking() { Collection rollbackingSessions = SessionHolder.getRetryRollbackingSessionManager().allSessions(); + if(CollectionUtils.isEmpty(rollbackingSessions)){ + return; + } + long now = System.currentTimeMillis(); for (GlobalSession rollbackingSession : rollbackingSessions) { try { + if(isRetryTimeout(now, MAX_ROLLBACK_RETRY_TIMEOUT.toMillis(), rollbackingSession.getBeginTime())){ + /** + * Prevent thread safety issues + */ + SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(rollbackingSession); + LOGGER.error("GlobalSession rollback retry timeout [{}]", rollbackingSession.getTransactionId()); + continue; + } + rollbackingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); core.doGlobalRollback(rollbackingSession, true); } catch (TransactionException ex) { LOGGER.info("Failed to retry rollbacking [{}] {} {}", - rollbackingSession.getTransactionId(), ex.getCode(), ex.getMessage()); + rollbackingSession.getXid(), ex.getCode(), ex.getMessage()); } } } - private void handleRetryCommitting() { + /** + * Handle retry committing. + */ + protected void handleRetryCommitting() { Collection committingSessions = SessionHolder.getRetryCommittingSessionManager().allSessions(); + if(CollectionUtils.isEmpty(committingSessions)){ + return; + } + long now = System.currentTimeMillis(); for (GlobalSession committingSession : committingSessions) { try { + if(isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT.toMillis(), committingSession.getBeginTime())){ + /** + * Prevent thread safety issues + */ + SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(committingSession); + LOGGER.error("GlobalSession commit retry timeout [{}]", committingSession.getTransactionId()); + continue; + } + committingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); core.doGlobalCommit(committingSession, true); } catch (TransactionException ex) { LOGGER.info("Failed to retry committing [{}] {} {}", - committingSession.getTransactionId(), ex.getCode(), ex.getMessage()); + committingSession.getXid(), ex.getCode(), ex.getMessage()); } } } - private void handleAsyncCommitting() { + private boolean isRetryTimeout(long now, long timeout, long beginTime){ + /** + * Start timing when the session begin + */ + if(timeout >= ALWAYS_RETRY_BOUNDARY && + now - beginTime > timeout){ + return true; + } + return false; + } + + /** + * Handle async committing. + */ + protected void handleAsyncCommitting() { Collection asyncCommittingSessions = SessionHolder.getAsyncCommittingSessionManager() .allSessions(); + if(CollectionUtils.isEmpty(asyncCommittingSessions)){ + return; + } for (GlobalSession asyncCommittingSession : asyncCommittingSessions) { try { + asyncCommittingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); core.doGlobalCommit(asyncCommittingSession, true); } catch (TransactionException ex) { LOGGER.info("Failed to async committing [{}] {} {}", - asyncCommittingSession.getTransactionId(), ex.getCode(), ex.getMessage()); + asyncCommittingSession.getXid(), ex.getCode(), ex.getMessage()); } } } - private ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("RetryRollbacking", 1)); - - private ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("RetryCommitting", 1)); - - private ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("AsyncCommitting", 1)); - - private ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("TxTimeoutCheck", 1)); /** * Init. */ public void init() { - retryRollbacking.scheduleAtFixedRate(new Runnable() { - - @Override - public void run() { - try { - handleRetryRollbacking(); - } catch (Exception e) { - LOGGER.info("Exception retry rollbacking ... ", e); - } - + retryRollbacking.scheduleAtFixedRate(() -> { + try { + handleRetryRollbacking(); + } catch (Exception e) { + LOGGER.info("Exception retry rollbacking ... ", e); } - }, 0, 5, TimeUnit.MILLISECONDS); - - retryCommitting.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - handleRetryCommitting(); - } catch (Exception e) { - LOGGER.info("Exception retry committing ... ", e); - } + }, 0, rollbackingRetryDelay, TimeUnit.SECONDS); + retryCommitting.scheduleAtFixedRate(() -> { + try { + handleRetryCommitting(); + } catch (Exception e) { + LOGGER.info("Exception retry committing ... ", e); } - }, 0, 5, TimeUnit.MILLISECONDS); - - asyncCommitting.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - handleAsyncCommitting(); - } catch (Exception e) { - LOGGER.info("Exception async committing ... ", e); - } + }, 0, committingRetryDelay, TimeUnit.SECONDS); + asyncCommitting.scheduleAtFixedRate(() -> { + try { + handleAsyncCommitting(); + } catch (Exception e) { + LOGGER.info("Exception async committing ... ", e); } - }, 0, 10, TimeUnit.MILLISECONDS); - - timeoutCheck.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - timeoutCheck(); - } catch (Exception e) { - LOGGER.info("Exception timeout checking ... ", e); - } + }, 0, asynCommittingRetryDelay, TimeUnit.SECONDS); + timeoutCheck.scheduleAtFixedRate(() -> { + try { + timeoutCheck(); + } catch (Exception e) { + LOGGER.info("Exception timeout checking ... ", e); } - }, 0, 2, TimeUnit.MILLISECONDS); + }, 0, timeoutRetryDelay, TimeUnit.SECONDS); } @Override @@ -369,14 +438,14 @@ public void destroy() { retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - } catch (InterruptedException ingore) { + } catch (InterruptedException ignore) { } - // 2. sencond close netty flow + // 2. second close netty flow if (messageSender instanceof RpcServer){ ((RpcServer) messageSender).destroy(); } - // 3. last destory SessionHolder + // 3. last destroy SessionHolder SessionHolder.destory(); } } diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCore.java b/server/src/main/java/io/seata/server/coordinator/DefaultCore.java index 1ba36763f1f..cd10d4281ba 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCore.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCore.java @@ -23,7 +23,7 @@ import io.seata.core.model.GlobalStatus; import io.seata.core.model.ResourceManagerInbound; import io.seata.server.lock.LockManager; -import io.seata.server.lock.LockManagerFactory; +import io.seata.server.lock.LockerFactory; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionHelper; @@ -46,7 +46,7 @@ public class DefaultCore implements Core { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCore.class); - private LockManager lockManager = LockManagerFactory.get(); + private LockManager lockManager = LockerFactory.getLockManager(); private ResourceManagerInbound resourceManagerInbound; @@ -58,7 +58,7 @@ public void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbo @Override public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid)); + GlobalSession globalSession = assertGlobalSessionNotNull(xid); return globalSession.lockAndExcute(() -> { if (!globalSession.isActive()) { throw new TransactionException(GlobalTransactionNotActive, "Current Status: " + globalSession.getStatus()); @@ -67,6 +67,7 @@ public Long branchRegister(BranchType branchType, String resourceId, String clie throw new TransactionException(GlobalTransactionStatusInvalid, globalSession.getStatus() + " while expecting " + GlobalStatus.Begin); } + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId, applicationData, lockKeys, clientId); if (!branchSession.lock()) { @@ -81,10 +82,10 @@ public Long branchRegister(BranchType branchType, String resourceId, String clie }); } - private GlobalSession assertGlobalSessionNotNull(long transactionId) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); + private GlobalSession assertGlobalSessionNotNull(String xid) throws TransactionException { + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); if (globalSession == null) { - throw new TransactionException(TransactionExceptionCode.GlobalTransactionNotExist, "" + transactionId + ""); + throw new TransactionException(TransactionExceptionCode.GlobalTransactionNotExist, "" + xid + ""); } return globalSession; } @@ -93,11 +94,12 @@ private GlobalSession assertGlobalSessionNotNull(long transactionId) throws Tran @Override public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, String applicationData) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid)); + GlobalSession globalSession = assertGlobalSessionNotNull(xid); BranchSession branchSession = globalSession.getBranch(branchId); if (branchSession == null) { throw new TransactionException(BranchTransactionNotExist); } + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.changeBranchStatus(branchSession, status); } @@ -105,7 +107,7 @@ public void branchReport(BranchType branchType, String xid, long branchId, Branc public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) throws TransactionException { if (branchType == BranchType.AT) { - return lockManager.isLockable(XID.getTransactionId(xid), resourceId, lockKeys); + return lockManager.isLockable(xid, resourceId, lockKeys); } else { return true; } @@ -121,17 +123,19 @@ public String begin(String applicationId, String transactionServiceGroup, String session.begin(); - return XID.generateXID(session.getTransactionId()); + return session.getXid(); } @Override public GlobalStatus commit(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); if (globalSession == null) { return GlobalStatus.Finished; } + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); // just lock changeStatus boolean shouldCommit = globalSession.lockAndExcute(() -> { + //the lock should release after branch commit globalSession.closeAndClean(); // Highlight: Firstly, close the session, then no more branch can be registered. if (globalSession.getStatus() == GlobalStatus.Begin) { globalSession.changeStatus(GlobalStatus.Committing); @@ -175,7 +179,7 @@ public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws } else { SessionHelper.endCommitFailed(globalSession); LOGGER.error("Finally, failed to commit global[{}] since branch[{}] commit failed", - globalSession.getTransactionId(), branchSession.getBranchId()); + globalSession.getXid(), branchSession.getBranchId()); return; } default: @@ -189,7 +193,7 @@ public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws } else { LOGGER.error( "Failed to commit global[{}] since branch[{}] commit failed, will retry later.", - globalSession.getTransactionId(), branchSession.getBranchId()); + globalSession.getXid(), branchSession.getBranchId()); return; } @@ -206,11 +210,11 @@ public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws } if (globalSession.hasBranch()) { - LOGGER.info("Global[{}] committing is NOT done.", globalSession.getTransactionId()); + LOGGER.info("Global[{}] committing is NOT done.", globalSession.getXid()); return; } SessionHelper.endCommitted(globalSession); - LOGGER.info("Global[{}] committing is successfully done.", globalSession.getTransactionId()); + LOGGER.info("Global[{}] committing is successfully done.", globalSession.getXid()); } private void asyncCommit(GlobalSession globalSession) throws TransactionException { @@ -238,10 +242,11 @@ private void queueToRetryRollback(GlobalSession globalSession) throws Transactio @Override public GlobalStatus rollback(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); if (globalSession == null) { return GlobalStatus.Finished; } + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); // just lock changeStatus boolean shouldRollBack = globalSession.lockAndExcute(() -> { globalSession.close(); // Highlight: Firstly, close the session, then no more branch can be registered. @@ -279,7 +284,7 @@ public void doGlobalRollback(GlobalSession globalSession, boolean retrying) thro continue; case PhaseTwo_RollbackFailed_Unretryable: SessionHelper.endRollbackFailed(globalSession); - LOGGER.error("Failed to rollback global[" + globalSession.getTransactionId() + "] since branch[" + LOGGER.error("Failed to rollback global[" + globalSession.getXid() + "] since branch[" + branchSession.getBranchId() + "] rollback failed"); return; default: @@ -304,7 +309,7 @@ public void doGlobalRollback(GlobalSession globalSession, boolean retrying) thro @Override public GlobalStatus getStatus(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); return globalSession.getStatus(); } } diff --git a/server/src/main/java/io/seata/server/lock/AbstractLockManager.java b/server/src/main/java/io/seata/server/lock/AbstractLockManager.java new file mode 100644 index 00000000000..a8db3a54d92 --- /dev/null +++ b/server/src/main/java/io/seata/server/lock/AbstractLockManager.java @@ -0,0 +1,117 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock; + +import io.seata.common.XID; +import io.seata.common.util.StringUtils; +import io.seata.core.lock.RowLock; +import io.seata.server.session.BranchSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type Abstract lock manager. + * + * @author zhangsen + * @data 2019 /4/25 + */ +public abstract class AbstractLockManager implements LockManager { + + /** + * The constant LOGGER. + */ + protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractLockManager.class); + + /** + * Collect row locks list.` + * + * @param branchSession the branch session + * @return the list + */ + protected List collectRowLocks(BranchSession branchSession){ + List locks = new ArrayList<>(); + if(branchSession == null || StringUtils.isBlank(branchSession.getLockKey())){ + return locks; + } + String xid = branchSession.getXid(); + String resourceId = branchSession.getResourceId(); + long transactionId = branchSession.getTransactionId(); + + String lockKey = branchSession.getLockKey(); + + return collectRowLocks(lockKey, resourceId, xid, transactionId, branchSession.getBranchId()); + } + + /** + * Collect row locks list. + * + * @param lockKey the lock key + * @param resourceId the resource id + * @param xid the xid + * @return the list + */ + protected List collectRowLocks(String lockKey, String resourceId, String xid) { + return collectRowLocks(lockKey, resourceId, xid, XID.getTransactionId(xid), null); + } + + /** + * Collect row locks list. + * + * @param lockKey the lock key + * @param resourceId the resource id + * @param xid the xid + * @param transactionId the transaction id + * @param branchID the branch id + * @return the list + */ + protected List collectRowLocks(String lockKey, String resourceId, String xid, Long transactionId, Long branchID){ + List locks = new ArrayList(); + + String[] tableGroupedLockKeys = lockKey.split(";"); + for (String tableGroupedLockKey : tableGroupedLockKeys) { + int idx = tableGroupedLockKey.indexOf(":"); + if (idx < 0) { + return locks; + } + String tableName = tableGroupedLockKey.substring(0, idx); + String mergedPKs = tableGroupedLockKey.substring(idx + 1); + if(StringUtils.isBlank(mergedPKs)){ + return locks; + } + String[] pks = mergedPKs.split(","); + if(pks == null || pks.length == 0){ + return locks; + } + for(String pk : pks){ + if(StringUtils.isNotBlank(pk)){ + RowLock rowLock = new RowLock(); + rowLock.setXid(xid); + rowLock.setTransactionId(transactionId); + rowLock.setBranchId(branchID); + rowLock.setTableName(tableName); + rowLock.setPk(pk); + rowLock.setResourceId(resourceId); + locks.add(rowLock); + } + } + } + return locks; + } + +} diff --git a/server/src/main/java/io/seata/server/lock/DefaultLockManager.java b/server/src/main/java/io/seata/server/lock/DefaultLockManager.java new file mode 100644 index 00000000000..dd66e979987 --- /dev/null +++ b/server/src/main/java/io/seata/server/lock/DefaultLockManager.java @@ -0,0 +1,103 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock; + +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringUtils; +import io.seata.core.exception.TransactionException; +import io.seata.core.lock.Locker; +import io.seata.core.lock.RowLock; +import io.seata.server.session.BranchSession; + +import java.util.List; + +/** + * The type Default lock manager. + * + * @author zhangsen + * @data 2019 -05-15 + */ +public class DefaultLockManager extends AbstractLockManager { + + private static Locker locker = null; + + @Override + public boolean acquireLock(BranchSession branchSession) throws TransactionException { + String lockKey = branchSession.getLockKey(); + if (StringUtils.isNullOrEmpty(lockKey)) { + //no lock + return true; + } + //get locks of branch + List locks = collectRowLocks(branchSession); + if(CollectionUtils.isEmpty(locks)){ + //no lock + return true; + } + return getLocker(branchSession).acquireLock(locks); + } + + @Override + public boolean releaseLock(BranchSession branchSession) throws TransactionException { + List locks = collectRowLocks(branchSession); + if(CollectionUtils.isEmpty(locks)){ + //no lock + return true; + } + try{ + return getLocker(branchSession).releaseLock(locks); + }catch(Exception t){ + LOGGER.error("unLock error, branchSession:" + branchSession, t); + return false; + } + } + + @Override + public boolean isLockable(String xid, String resourceId, String lockKey) throws TransactionException { + List locks = collectRowLocks(lockKey, resourceId, xid); + try{ + return getLocker().isLockable(locks); + }catch(Exception t){ + LOGGER.error("isLockable error, xid:" + xid + ", resourceId:"+resourceId + ", lockKey:"+lockKey, t); + return false; + } + } + + @Override + public void cleanAllLocks() throws TransactionException { + getLocker().cleanAllLocks(); + } + + /** + * Gets locker. + * + * @return the locker + */ + protected Locker getLocker() { + return getLocker(null); + } + + /** + * Gets locker. + * + * @param branchSession the branch session + * @return the locker + */ + protected Locker getLocker(BranchSession branchSession) { + return LockerFactory.get(branchSession); + } + +} diff --git a/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java b/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java deleted file mode 100644 index 14a68549987..00000000000 --- a/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import io.netty.util.internal.ConcurrentSet; -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.util.StringUtils; -import io.seata.core.exception.TransactionException; -import io.seata.server.session.BranchSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The type Default lock manager. - * - * @author sharajava - */ -public class DefaultLockManagerImpl implements LockManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLockManagerImpl.class); - - private static final int BUCKET_PER_TABLE = 128; - - private static final - ConcurrentHashMap>>> - LOCK_MAP = new ConcurrentHashMap>>>(); - - @Override - public boolean acquireLock(BranchSession branchSession) throws TransactionException { - String resourceId = branchSession.getResourceId(); - long transactionId = branchSession.getTransactionId(); - ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); - if (dbLockMap == null) { - LOCK_MAP.putIfAbsent(resourceId, - new ConcurrentHashMap>>()); - dbLockMap = LOCK_MAP.get(resourceId); - } - ConcurrentHashMap, Set> bucketHolder = branchSession.getLockHolder(); - - String lockKey = branchSession.getLockKey(); - if (StringUtils.isNullOrEmpty(lockKey)) { - return true; - } - - String[] tableGroupedLockKeys = lockKey.split(";"); - for (String tableGroupedLockKey : tableGroupedLockKeys) { - int idx = tableGroupedLockKey.indexOf(":"); - if (idx < 0) { - branchSession.unlock(); - throw new ShouldNeverHappenException("Wrong format of LOCK KEYS: " + branchSession.getLockKey()); - } - String tableName = tableGroupedLockKey.substring(0, idx); - String mergedPKs = tableGroupedLockKey.substring(idx + 1); - ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); - if (tableLockMap == null) { - dbLockMap.putIfAbsent(tableName, new ConcurrentHashMap>()); - tableLockMap = dbLockMap.get(tableName); - } - String[] pks = mergedPKs.split(","); - for (String pk : pks) { - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - Map bucketLockMap = tableLockMap.get(bucketId); - if (bucketLockMap == null) { - tableLockMap.putIfAbsent(bucketId, new HashMap()); - bucketLockMap = tableLockMap.get(bucketId); - } - synchronized (bucketLockMap) { - Long lockingTransactionId = bucketLockMap.get(pk); - if (lockingTransactionId == null) { - // No existing lock - bucketLockMap.put(pk, transactionId); - Set keysInHolder = bucketHolder.get(bucketLockMap); - if (keysInHolder == null) { - bucketHolder.putIfAbsent(bucketLockMap, new ConcurrentSet()); - keysInHolder = bucketHolder.get(bucketLockMap); - } - keysInHolder.add(pk); - - } else if (lockingTransactionId.longValue() == transactionId) { - // Locked by me - continue; - } else { - LOGGER.info( - "Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); - branchSession.unlock(); // Release all acquired locks. - return false; - } - } - } - } - return true; - } - - @Override - public boolean isLockable(long transactionId, String resourceId, String lockKey) throws TransactionException { - ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); - if (dbLockMap == null) { - return true; - } - String[] tableGroupedLockKeys = lockKey.split(";"); - for (String tableGroupedLockKey : tableGroupedLockKeys) { - int idx = tableGroupedLockKey.indexOf(":"); - if (idx < 0) { - throw new ShouldNeverHappenException("Wrong format of LOCK KEYS: " + lockKey); - } - String tableName = tableGroupedLockKey.substring(0, idx); - String mergedPKs = tableGroupedLockKey.substring(idx + 1); - ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); - if (tableLockMap == null) { - continue; - } - String[] pks = mergedPKs.split(","); - for (String pk : pks) { - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - Map bucketLockMap = tableLockMap.get(bucketId); - if (bucketLockMap == null) { - continue; - } - Long lockingTransactionId = bucketLockMap.get(pk); - if (lockingTransactionId == null || lockingTransactionId.longValue() == transactionId) { - // Locked by me - continue; - } else { - LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); - return false; - } - } - } - return true; - } - - @Override - public void cleanAllLocks() throws TransactionException { - LOCK_MAP.clear(); - } - - @Override - public boolean releaseLock(BranchSession branchSession) throws TransactionException { - ConcurrentHashMap, Set> lockHolder = branchSession.getLockHolder(); - if (lockHolder.size() == 0) { - return true; - } - Iterator, Set>> it = lockHolder.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry, Set> entry = it.next(); - Map bucket = entry.getKey(); - Set keys = entry.getValue(); - synchronized (bucket) { - for (String key : keys) { - Long v = bucket.get(key); - if (v == null) { - continue; - } - if (v.longValue() == branchSession.getTransactionId()) { - bucket.remove(key); - } - } - } - } - lockHolder.clear(); - return true; - } -} diff --git a/server/src/main/java/io/seata/server/lock/LockManager.java b/server/src/main/java/io/seata/server/lock/LockManager.java index 54bcef3c0b4..64e7bd7317e 100644 --- a/server/src/main/java/io/seata/server/lock/LockManager.java +++ b/server/src/main/java/io/seata/server/lock/LockManager.java @@ -35,29 +35,30 @@ public interface LockManager { boolean acquireLock(BranchSession branchSession) throws TransactionException; /** - * Is lockable boolean. + * Un lock boolean. * - * @param transactionId the transaction id - * @param resourceId the resource id - * @param lockKey the lock key + * @param branchSession the branch session * @return the boolean * @throws TransactionException the transaction exception */ - boolean isLockable(long transactionId, String resourceId, String lockKey) throws TransactionException; + boolean releaseLock(BranchSession branchSession) throws TransactionException; /** - * Clean all locks. + * Is lockable boolean. * + * @param xid the xid + * @param resourceId the resource id + * @param lockKey the lock key + * @return the boolean * @throws TransactionException the transaction exception */ - void cleanAllLocks() throws TransactionException; + boolean isLockable(String xid, String resourceId, String lockKey) throws TransactionException; /** - * Release lock boolean. + * Clean all locks. * - * @param branchSession the branch session - * @return the boolean * @throws TransactionException the transaction exception */ - boolean releaseLock(BranchSession branchSession) throws TransactionException; + void cleanAllLocks() throws TransactionException; + } diff --git a/server/src/main/java/io/seata/server/lock/LockerFactory.java b/server/src/main/java/io/seata/server/lock/LockerFactory.java new file mode 100644 index 00000000000..6a402f0a447 --- /dev/null +++ b/server/src/main/java/io/seata/server/lock/LockerFactory.java @@ -0,0 +1,99 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.lock.LockMode; +import io.seata.core.lock.Locker; +import io.seata.core.store.db.DataSourceGenerator; +import io.seata.server.session.BranchSession; + +import javax.sql.DataSource; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * The type Lock manager factory. + * + * @author sharajava + */ +public class LockerFactory { + + /** + * The constant CONFIG. + */ + protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + + /** + * The constant locker. + */ + protected static Locker locker = null; + + /** + * The constant lockerMap. + */ + protected static Map lockerMap = new ConcurrentHashMap<>(); + + /** + * The constant lockManager. + */ + protected static LockManager lockManager = new DefaultLockManager(); + + /** + * Get lock manager. + * + * @return the lock manager + */ + public static synchronized final LockManager getLockManager() { + return lockManager; + } + + /** + * Get lock manager. + * + * @param branchSession the branch session + * @return the lock manager + */ + public static synchronized final Locker get(BranchSession branchSession) { + String lockMode = CONFIG.getConfig(ConfigurationKeys.LOCK_MODE); + if(LockMode.DB.name().equalsIgnoreCase(lockMode)){ + if(lockerMap.get(lockMode) != null){ + return lockerMap.get(lockMode); + } + //init dataSource + String datasourceType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, datasourceType); + DataSource logStoreDataSource = dataSourceGenerator.generateDataSource(); + locker = EnhancedServiceLoader.load(Locker.class, lockMode, new Class[]{DataSource.class}, new Object[]{logStoreDataSource}); + lockerMap.put(lockMode, locker); + }else if(LockMode.MEMORY.name().equalsIgnoreCase(lockMode)){ + if(branchSession == null){ + throw new IllegalArgumentException("branchSession can be null for memory lockMode."); + } + locker = EnhancedServiceLoader.load(Locker.class, lockMode, + new Class[]{BranchSession.class}, new Object[]{branchSession} ); + }else { + //other locker + locker = EnhancedServiceLoader.load(Locker.class, lockMode); + } + return locker; + } + + +} diff --git a/server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java b/server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java new file mode 100644 index 00000000000..5721727fdc8 --- /dev/null +++ b/server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java @@ -0,0 +1,101 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock.db; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; +import io.seata.core.lock.AbstractLocker; +import io.seata.core.lock.LockMode; +import io.seata.core.lock.RowLock; +import io.seata.core.store.LockStore; + +import javax.sql.DataSource; +import java.util.List; + +/** + * The type Data base locker. + * + * @author zhangsen + * @data 2019 -05-15 + */ +@LoadLevel(name = "db") +public class DataBaseLocker extends AbstractLocker { + + private LockStore lockStore; + + /** + * Instantiates a new Data base locker. + */ + public DataBaseLocker(){ + } + + /** + * Instantiates a new Data base locker. + * + * @param logStoreDataSource the log store data source + */ + public DataBaseLocker(DataSource logStoreDataSource){ + lockStore = EnhancedServiceLoader.load(LockStore.class, LockMode.DB.name(), new Class[]{DataSource.class}, new Object[]{logStoreDataSource}); + } + + @Override + public boolean acquireLock(List locks) { + if(CollectionUtils.isEmpty(locks)){ + //no lock + return true; + } + try{ + return lockStore.acquireLock(convertToLockDO(locks)); + }catch(Exception t){ + LOGGER.error("AcquireLock error, locks:" + CollectionUtils.toString(locks), t); + return false; + } + } + + @Override + public boolean releaseLock(List locks) { + if(CollectionUtils.isEmpty(locks)){ + //no lock + return true; + } + try{ + return lockStore.unLock(convertToLockDO(locks)); + }catch(Exception t){ + LOGGER.error("unLock error, locks:" + CollectionUtils.toString(locks), t); + return false; + } + } + + @Override + public boolean isLockable(List locks) { + try{ + return lockStore.isLockable(convertToLockDO(locks)); + }catch(Exception t){ + LOGGER.error("isLockable error, locks:" + CollectionUtils.toString(locks), t); + return false; + } + } + + /** + * Sets lock store. + * + * @param lockStore the lock store + */ + public void setLockStore(LockStore lockStore) { + this.lockStore = lockStore; + } +} diff --git a/server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java b/server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java new file mode 100644 index 00000000000..f4dbb9423e6 --- /dev/null +++ b/server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java @@ -0,0 +1,193 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock.memory; + +import io.netty.util.internal.ConcurrentSet; +import io.seata.common.exception.FrameworkException; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; +import io.seata.core.exception.TransactionException; +import io.seata.core.lock.AbstractLocker; +import io.seata.core.lock.RowLock; +import io.seata.server.session.BranchSession; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * The type Memory locker. + * + * @author zhangsen + * @data 2019 -05-15 + */ +@LoadLevel(name="memory") +public class MemoryLocker extends AbstractLocker { + + private static final int BUCKET_PER_TABLE = 128; + + private static final ConcurrentHashMap>>> + LOCK_MAP = new ConcurrentHashMap>>>(); + + /** + * The Branch session. + */ + protected BranchSession branchSession = null; + + /** + * Instantiates a new Memory locker. + * + * @param branchSession the branch session + */ + public MemoryLocker(BranchSession branchSession){ + this.branchSession = branchSession; + } + + @Override + public boolean acquireLock(List rowLocks) { + if(CollectionUtils.isEmpty(rowLocks)){ + //no lock + return true; + } + String resourceId = branchSession.getResourceId(); + long transactionId = branchSession.getTransactionId(); + + ConcurrentHashMap, Set> bucketHolder = branchSession.getLockHolder(); + ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); + if (dbLockMap == null) { + LOCK_MAP.putIfAbsent(resourceId, new ConcurrentHashMap>>()); + dbLockMap = LOCK_MAP.get(resourceId); + } + + for(RowLock lock : rowLocks){ + String tableName = lock.getTableName(); + String pk = lock.getPk(); + ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); + if (tableLockMap == null) { + dbLockMap.putIfAbsent(tableName, new ConcurrentHashMap>()); + tableLockMap = dbLockMap.get(tableName); + } + int bucketId = pk.hashCode() % BUCKET_PER_TABLE; + Map bucketLockMap = tableLockMap.get(bucketId); + if (bucketLockMap == null) { + tableLockMap.putIfAbsent(bucketId, new ConcurrentHashMap()); + bucketLockMap = tableLockMap.get(bucketId); + } + synchronized (bucketLockMap) { + Long lockingTransactionId = bucketLockMap.get(pk); + if (lockingTransactionId == null) { + //No existing lock + bucketLockMap.put(pk, transactionId); + Set keysInHolder = bucketHolder.get(bucketLockMap); + if (keysInHolder == null) { + bucketHolder.putIfAbsent(bucketLockMap, new ConcurrentSet()); + keysInHolder = bucketHolder.get(bucketLockMap); + } + keysInHolder.add(pk); + + } else if (lockingTransactionId.longValue() == transactionId) { + // Locked by me + continue; + } else { + LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); + try { + // Release all acquired locks. + branchSession.unlock(); + } catch (TransactionException e) { + throw new FrameworkException(e); + } + return false; + } + } + } + return true; + } + + @Override + public boolean releaseLock(List rowLock) { + ConcurrentHashMap, Set> lockHolder = branchSession.getLockHolder(); + if (lockHolder == null || lockHolder.size() == 0) { + return true; + } + Iterator, Set>> it = lockHolder.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry, Set> entry = it.next(); + Map bucket = entry.getKey(); + Set keys = entry.getValue(); + synchronized (bucket) { + for (String key : keys) { + Long v = bucket.get(key); + if (v == null) { + continue; + } + if (v.longValue() == branchSession.getTransactionId()) { + bucket.remove(key); + } + } + } + } + lockHolder.clear(); + return true; + } + + @Override + public boolean isLockable(List rowLocks) { + if(CollectionUtils.isEmpty(rowLocks)){ + //no lock + return true; + } + Long transactionId = rowLocks.get(0).getTransactionId(); + String resourceId = rowLocks.get(0).getResourceId(); + ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); + if (dbLockMap == null) { + return true; + } + for(RowLock rowLock : rowLocks){ + String xid = rowLock.getXid(); + String tableName = rowLock.getTableName(); + String pk = rowLock.getPk(); + + ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); + if (tableLockMap == null) { + continue; + } + int bucketId = pk.hashCode() % BUCKET_PER_TABLE; + Map bucketLockMap = tableLockMap.get(bucketId); + if (bucketLockMap == null) { + continue; + } + Long lockingTransactionId = bucketLockMap.get(pk); + if (lockingTransactionId == null || lockingTransactionId.longValue() == transactionId) { + // Locked by me + continue; + } else { + LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); + return false; + } + } + return true; + } + + @Override + public void cleanAllLocks() { + LOCK_MAP.clear(); + } +} diff --git a/server/src/main/java/io/seata/server/session/AbstractSessionManager.java b/server/src/main/java/io/seata/server/session/AbstractSessionManager.java index d58f8b71d5a..8cce5790b8f 100644 --- a/server/src/main/java/io/seata/server/session/AbstractSessionManager.java +++ b/server/src/main/java/io/seata/server/session/AbstractSessionManager.java @@ -25,16 +25,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - /** * The type Abstract session manager. - * - * @author sharajava */ public abstract class AbstractSessionManager implements SessionManager, SessionLifecycleListener { @@ -43,11 +35,6 @@ public abstract class AbstractSessionManager implements SessionManager, SessionL */ protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractSessionManager.class); - /** - * The Session map. - */ - protected Map sessionMap = new ConcurrentHashMap<>(); - /** * The Transaction store manager. */ @@ -58,6 +45,12 @@ public abstract class AbstractSessionManager implements SessionManager, SessionL */ protected String name; + /** + * Instantiates a new Abstract session manager. + */ + public AbstractSessionManager() { + } + /** * Instantiates a new Abstract session manager. * @@ -73,15 +66,6 @@ public void addGlobalSession(GlobalSession session) throws TransactionException LOGGER.debug("MANAGER[" + name + "] SESSION[" + session + "] " + LogOperation.GLOBAL_ADD); } writeSession(LogOperation.GLOBAL_ADD, session); - sessionMap.put(session.getTransactionId(), session); - - } - - - - @Override - public GlobalSession findGlobalSession(Long transactionId) { - return sessionMap.get(transactionId); } @Override @@ -98,8 +82,6 @@ public void removeGlobalSession(GlobalSession session) throws TransactionExcepti LOGGER.debug("MANAGER[" + name + "] SESSION[" + session + "] " + LogOperation.GLOBAL_REMOVE); } writeSession(LogOperation.GLOBAL_REMOVE, session); - sessionMap.remove(session.getTransactionId()); - } @Override @@ -126,23 +108,6 @@ public void removeBranchSession(GlobalSession globalSession, BranchSession branc LOGGER.debug("MANAGER[" + name + "] SESSION[" + branchSession + "] " + LogOperation.GLOBAL_ADD); } writeSession(LogOperation.BRANCH_REMOVE, branchSession); - - } - - @Override - public Collection allSessions() { - return sessionMap.values(); - } - - @Override - public List findGlobalSessions(SessionCondition condition) { - List found = new ArrayList<>(); - for (GlobalSession globalSession : sessionMap.values()) { - if (System.currentTimeMillis() - globalSession.getBeginTime() > condition.getOverTimeAliveMills()) { - found.add(globalSession); - } - } - return found; } @Override @@ -174,18 +139,29 @@ public void onRemoveBranch(GlobalSession globalSession, BranchSession branchSess @Override public void onClose(GlobalSession globalSession) throws TransactionException { globalSession.setActive(false); - } @Override public void onEnd(GlobalSession globalSession) throws TransactionException { removeGlobalSession(globalSession); - } - private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException{ + private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException { if (!transactionStoreManager.writeSession(logOperation, sessionStorable)) { throw new TransactionException(TransactionExceptionCode.FailedWriteSession); } } + + @Override + public void destroy() { + } + + /** + * Sets transaction store manager. + * + * @param transactionStoreManager the transaction store manager + */ + public void setTransactionStoreManager(TransactionStoreManager transactionStoreManager) { + this.transactionStoreManager = transactionStoreManager; + } } diff --git a/server/src/main/java/io/seata/server/session/BranchSession.java b/server/src/main/java/io/seata/server/session/BranchSession.java index 31e51961235..7354a88ab07 100644 --- a/server/src/main/java/io/seata/server/session/BranchSession.java +++ b/server/src/main/java/io/seata/server/session/BranchSession.java @@ -15,22 +15,22 @@ */ package io.seata.server.session; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - import io.seata.common.util.CompressUtil; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; -import io.seata.server.lock.LockManagerFactory; +import io.seata.server.lock.LockerFactory; import io.seata.server.store.SessionStorable; import io.seata.server.store.StoreConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + /** * The type Branch session. * @@ -45,6 +45,8 @@ public class BranchSession implements Lockable, Comparable, Sessi private static ThreadLocal byteBufferThreadLocal = ThreadLocal.withInitial(() -> ByteBuffer.allocate( MAX_BRANCH_SESSION_SIZE)); + private String xid; + private long transactionId; private long branchId; @@ -64,7 +66,7 @@ public class BranchSession implements Lockable, Comparable, Sessi private String applicationData; private ConcurrentHashMap, Set> lockHolder - = new ConcurrentHashMap, Set>(); + = new ConcurrentHashMap<>(); /** * Gets application data. @@ -188,7 +190,7 @@ public BranchStatus getStatus() { * * @param status the status */ - void setStatus(BranchStatus status) { + public void setStatus(BranchStatus status) { this.status = status; } @@ -228,6 +230,24 @@ public void setBranchId(long branchId) { this.branchId = branchId; } + /** + * Gets xid. + * + * @return the xid + */ + public String getXid() { + return xid; + } + + /** + * Sets xid. + * + * @param xid the xid + */ + public void setXid(String xid) { + this.xid = xid; + } + @Override public String toString() { return "BR:" + branchId + "/" + transactionId; @@ -249,12 +269,12 @@ public ConcurrentHashMap, Set> getLockHolder() { @Override public boolean lock() throws TransactionException { - return LockManagerFactory.get().acquireLock(this); + return LockerFactory.getLockManager().acquireLock(this); } @Override public boolean unlock() throws TransactionException { - return LockManagerFactory.get().releaseLock(this); + return LockerFactory.getLockManager().releaseLock(this); } @Override @@ -268,7 +288,9 @@ public byte[] encode() { byte[] applicationDataBytes = applicationData != null ? applicationData.getBytes() : null; - int size = calBranchSessionSize(resourceIdBytes, lockKeyBytes, clientIdBytes, applicationDataBytes); + byte[] xidBytes = xid != null ? xid.getBytes() : null; + + int size = calBranchSessionSize(resourceIdBytes, lockKeyBytes, clientIdBytes, applicationDataBytes, xidBytes); if (size > MAX_BRANCH_SESSION_SIZE) { if (lockKeyBytes == null) { @@ -327,6 +349,13 @@ public byte[] encode() { byteBuffer.putInt(0); } + if(xidBytes != null){ + byteBuffer.putInt(xidBytes.length); + byteBuffer.put(xidBytes); + }else { + byteBuffer.putInt(0); + } + byteBuffer.put((byte)status.getCode()); byteBuffer.flip(); byte[] result = new byte[byteBuffer.limit()]; @@ -335,18 +364,19 @@ public byte[] encode() { } private int calBranchSessionSize(byte[] resourceIdBytes, byte[] lockKeyBytes, byte[] clientIdBytes, - byte[] applicationDataBytes) { + byte[] applicationDataBytes, byte[] xidBytes) { final int size = 8 // trascationId - + 8 // branchId - + 4 // resourceIdBytes.length - + 4 // lockKeyBytes.length - + 2 // clientIdBytes.length - + 4 // applicationDataBytes.length - + 1 // statusCode - + (resourceIdBytes == null ? 0 : resourceIdBytes.length) - + (lockKeyBytes == null ? 0 : lockKeyBytes.length) - + (clientIdBytes == null ? 0 : clientIdBytes.length) - + (applicationDataBytes == null ? 0 : applicationDataBytes.length); + + 8 // branchId + + 4 // resourceIdBytes.length + + 4 // lockKeyBytes.length + + 2 // clientIdBytes.length + + 4 // applicationDataBytes.length + + 1 // statusCode + + (resourceIdBytes == null ? 0 : resourceIdBytes.length) + + (lockKeyBytes == null ? 0 : lockKeyBytes.length) + + (clientIdBytes == null ? 0 : clientIdBytes.length) + + (applicationDataBytes == null ? 0 : applicationDataBytes.length) + + (xidBytes == null ? 0 : xidBytes.length); return size; } @@ -369,7 +399,7 @@ public void decode(byte[] a) { try { this.lockKey = new String(CompressUtil.uncompress(byLockKey)); } catch (IOException e) { - throw new RuntimeException("uncompress lockKey error", e); + throw new RuntimeException("decompress lockKey error", e); } } else { this.lockKey = new String(byLockKey); @@ -388,6 +418,12 @@ public void decode(byte[] a) { byteBuffer.get(byApplicationData); this.applicationData = new String(byApplicationData); } + int xidLen = byteBuffer.getInt(); + if (xidLen > 0) { + byte[] xidBytes = new byte[xidLen]; + byteBuffer.get(xidBytes); + this.xid = new String(xidBytes); + } this.status = BranchStatus.get(byteBuffer.get()); } diff --git a/server/src/main/java/io/seata/server/session/DefaultSessionManager.java b/server/src/main/java/io/seata/server/session/DefaultSessionManager.java index ff24f7f6bba..a9fcf0cae66 100644 --- a/server/src/main/java/io/seata/server/session/DefaultSessionManager.java +++ b/server/src/main/java/io/seata/server/session/DefaultSessionManager.java @@ -15,19 +15,30 @@ */ package io.seata.server.session; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import io.seata.common.loader.LoadLevel; +import io.seata.core.exception.TransactionException; +import io.seata.server.store.AbstractTransactionStoreManager; import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.TransactionWriteStore; /** - * The type Default session manager. + * The type Default session manager, store session data in memory. * * @author sharajava */ +@LoadLevel(name = "default") public class DefaultSessionManager extends AbstractSessionManager { + /** + * The Session map. + */ + protected Map sessionMap = new ConcurrentHashMap(); + /** * Instantiates a new Default session manager. * @@ -35,27 +46,45 @@ public class DefaultSessionManager extends AbstractSessionManager { */ public DefaultSessionManager(String name) { super(name); - transactionStoreManager = new TransactionStoreManager() { + transactionStoreManager = new AbstractTransactionStoreManager() { @Override public boolean writeSession(LogOperation logOperation, SessionStorable session) { return true; } + }; + } - @Override - public void shutdown() { + @Override + public void addGlobalSession(GlobalSession session) throws TransactionException { + super.addGlobalSession(session); + sessionMap.put(session.getXid(), session); + } - } + @Override + public GlobalSession findGlobalSession(String xid) { + return sessionMap.get(xid); + } - @Override - public List readWriteStoreFromFile(int readSize, boolean isHistory) { - return null; - } + @Override + public void removeGlobalSession(GlobalSession session) throws TransactionException { + super.removeGlobalSession(session); + sessionMap.remove(session.getXid()); + } - @Override - public boolean hasRemaining(boolean isHistory) { - return false; + @Override + public Collection allSessions() { + return sessionMap.values(); + } + + @Override + public List findGlobalSessions(SessionCondition condition) { + List found = new ArrayList<>(); + for (GlobalSession globalSession : sessionMap.values()) { + if (System.currentTimeMillis() - globalSession.getBeginTime() > condition.getOverTimeAliveMills()) { + found.add(globalSession); } - }; + } + return found; } @Override diff --git a/server/src/main/java/io/seata/server/session/GlobalSession.java b/server/src/main/java/io/seata/server/session/GlobalSession.java index 1c9f31d5bda..c7648178223 100644 --- a/server/src/main/java/io/seata/server/session/GlobalSession.java +++ b/server/src/main/java/io/seata/server/session/GlobalSession.java @@ -15,6 +15,7 @@ */ package io.seata.server.session; +import io.seata.common.XID; import io.seata.core.exception.TransactionException; import io.seata.core.exception.TransactionExceptionCode; import io.seata.core.model.BranchStatus; @@ -47,6 +48,8 @@ public class GlobalSession implements SessionLifecycle, SessionStorable { private static ThreadLocal byteBufferThreadLocal = ThreadLocal.withInitial(() -> ByteBuffer.allocate( MAX_GLOBAL_SESSION_SIZE)); + private String xid; + private long transactionId; private volatile GlobalStatus status; @@ -61,7 +64,9 @@ public class GlobalSession implements SessionLifecycle, SessionStorable { private long beginTime; - private boolean active; + private String applicationData; + + private boolean active = true; private ArrayList branchSessions = new ArrayList<>(); @@ -165,7 +170,7 @@ public void end() throws TransactionException { } - private void clean() throws TransactionException { + public void clean() throws TransactionException { for (BranchSession branchSession : branchSessions) { branchSession.unlock(); } @@ -282,6 +287,7 @@ public GlobalSession(String applicationId, String transactionServiceGroup, Strin this.transactionServiceGroup = transactionServiceGroup; this.transactionName = transactionName; this.timeout = timeout; + this.xid = XID.generateXID(transactionId); } /** @@ -293,6 +299,15 @@ public long getTransactionId() { return transactionId; } + /** + * Sets transaction id. + * + * @param transactionId the transaction id + */ + public void setTransactionId(long transactionId) { + this.transactionId = transactionId; + } + /** * Gets status. * @@ -307,10 +322,28 @@ public GlobalStatus getStatus() { * * @param status the status */ - void setStatus(GlobalStatus status) { + public void setStatus(GlobalStatus status) { this.status = status; } + /** + * Gets xid. + * + * @return the xid + */ + public String getXid() { + return xid; + } + + /** + * Sets xid. + * + * @param xid the xid + */ + public void setXid(String xid) { + this.xid = xid; + } + /** * Gets application id. * @@ -356,6 +389,32 @@ public long getBeginTime() { return beginTime; } + /** + * Sets begin time. + * + * @param beginTime the begin time + */ + public void setBeginTime(long beginTime) { + this.beginTime = beginTime; + } + + /** + * Gets application data. + * + * @return the application data + */ + public String getApplicationData() { + return applicationData; + } + + /** + * Sets application data. + * + * @param applicationData the application data + */ + public void setApplicationData(String applicationData) { + this.applicationData = applicationData; + } /** * Create global session global session. @@ -390,7 +449,11 @@ public byte[] encode() { byte[] byTxNameBytes = transactionName != null ? transactionName.getBytes() : null; - int size = calGlobalSessionSize(byApplicationIdBytes, byServiceGroupBytes, byTxNameBytes); + byte[] xidBytes = xid != null ? xid.getBytes():null; + + byte[] applicationDataBytes = applicationData != null ? applicationData.getBytes():null; + + int size = calGlobalSessionSize(byApplicationIdBytes, byServiceGroupBytes, byTxNameBytes, xidBytes, applicationDataBytes); if (size > MAX_GLOBAL_SESSION_SIZE) { throw new RuntimeException("global session size exceeded, size : " + size + " maxBranchSessionSize : " + @@ -420,6 +483,19 @@ public byte[] encode() { } else { byteBuffer.putShort((short)0); } + if(xidBytes != null){ + byteBuffer.putInt(xidBytes.length); + byteBuffer.put(xidBytes); + }else { + byteBuffer.putInt(0); + } + if(applicationDataBytes != null){ + byteBuffer.putInt(applicationDataBytes.length); + byteBuffer.put(applicationDataBytes); + }else { + byteBuffer.putInt(0); + } + byteBuffer.putLong(beginTime); byteBuffer.put((byte)status.getCode()); byteBuffer.flip(); @@ -428,17 +504,20 @@ public byte[] encode() { return result; } - private int calGlobalSessionSize(byte[] byApplicationIdBytes, byte[] byServiceGroupBytes, byte[] byTxNameBytes) { + private int calGlobalSessionSize(byte[] byApplicationIdBytes, byte[] byServiceGroupBytes, byte[] byTxNameBytes, + byte[] xidBytes, byte[] applicationDataBytes) { final int size = 8 // trascationId - + 4 // timeout - + 2 // byApplicationIdBytes.length - + 2 // byServiceGroupBytes.length - + 2 // byTxNameBytes.length - + 8 // beginTime - + 1 // statusCode - + (byApplicationIdBytes == null ? 0 : byApplicationIdBytes.length) - + (byServiceGroupBytes == null ? 0 : byServiceGroupBytes.length) - + (byTxNameBytes == null ? 0 : byTxNameBytes.length); + + 4 // timeout + + 2 // byApplicationIdBytes.length + + 2 // byServiceGroupBytes.length + + 2 // byTxNameBytes.length + + 8 // beginTime + + 1 // statusCode + + (byApplicationIdBytes == null ? 0 : byApplicationIdBytes.length) + + (byServiceGroupBytes == null ? 0 : byServiceGroupBytes.length) + + (byTxNameBytes == null ? 0 : byTxNameBytes.length) + + (xidBytes ==null ? 0 : xidBytes.length) + + (applicationDataBytes == null ? 0 : applicationDataBytes.length); return size; } @@ -465,6 +544,19 @@ public void decode(byte[] a) { byteBuffer.get(byTxName); this.transactionName = new String(byTxName); } + int xidLen = byteBuffer.getInt(); + if(xidLen > 0 ){ + byte[] xidBytes = new byte[xidLen]; + byteBuffer.get(xidBytes); + this.xid = new String(xidBytes); + } + int applicationDataLen = byteBuffer.getInt(); + if(applicationDataLen > 0){ + byte[] applicationDataLenBytes = new byte[applicationDataLen]; + byteBuffer.get(applicationDataLenBytes); + this.applicationData = new String(applicationDataLenBytes); + } + this.beginTime = byteBuffer.getLong(); this.status = GlobalStatus.get(byteBuffer.get()); } diff --git a/server/src/main/java/io/seata/server/session/SessionCondition.java b/server/src/main/java/io/seata/server/session/SessionCondition.java index 4063d7aa378..1b192bb0c85 100644 --- a/server/src/main/java/io/seata/server/session/SessionCondition.java +++ b/server/src/main/java/io/seata/server/session/SessionCondition.java @@ -15,6 +15,8 @@ */ package io.seata.server.session; +import io.seata.core.model.GlobalStatus; + /** * The type Session condition. * @@ -22,9 +24,46 @@ * @date 2018 /12/13 */ public class SessionCondition { - + private Long transactionId; + private String xid; + private GlobalStatus status; + private GlobalStatus[] statuses; private long overTimeAliveMills; + /** + * Instantiates a new Session condition. + */ + public SessionCondition() { + } + + /** + * Instantiates a new Session condition. + * + * @param xid the xid + */ + public SessionCondition(String xid) { + this.xid = xid; + } + + /** + * Instantiates a new Session condition. + * + * @param status the status + */ + public SessionCondition(GlobalStatus status) { + this.status = status; + statuses = new GlobalStatus[]{status}; + } + + /** + * Instantiates a new Session condition. + * + * @param statuses the statuses + */ + public SessionCondition(GlobalStatus[] statuses) { + this.statuses = statuses; + } + /** * Instantiates a new Session condition. * @@ -34,6 +73,23 @@ public SessionCondition( long overTimeAliveMills) { this.overTimeAliveMills = overTimeAliveMills; } + /** + * Gets status. + * + * @return the status + */ + public GlobalStatus getStatus() { + return status; + } + + /** + * Sets status. + * + * @param status the status + */ + public void setStatus(GlobalStatus status) { + this.status = status; + } /** * Gets over time alive mills. @@ -52,4 +108,28 @@ public long getOverTimeAliveMills() { public void setOverTimeAliveMills(long overTimeAliveMills) { this.overTimeAliveMills = overTimeAliveMills; } + + public Long getTransactionId() { + return transactionId; + } + + public void setTransactionId(Long transactionId) { + this.transactionId = transactionId; + } + + public String getXid() { + return xid; + } + + public void setXid(String xid) { + this.xid = xid; + } + + public GlobalStatus[] getStatuses() { + return statuses; + } + + public void setStatuses(GlobalStatus[] statuses) { + this.statuses = statuses; + } } diff --git a/server/src/main/java/io/seata/server/session/SessionHelper.java b/server/src/main/java/io/seata/server/session/SessionHelper.java index b3295d24e8f..fec302b1535 100644 --- a/server/src/main/java/io/seata/server/session/SessionHelper.java +++ b/server/src/main/java/io/seata/server/session/SessionHelper.java @@ -47,6 +47,7 @@ public static BranchSession newBranchByGlobal(GlobalSession globalSession, Branc String applicationData, String lockKeys, String clientId) { BranchSession branchSession = new BranchSession(); + branchSession.setXid(globalSession.getXid()); branchSession.setTransactionId(globalSession.getTransactionId()); branchSession.setBranchId(UUIDGenerator.generateUUID()); branchSession.setBranchType(branchType); diff --git a/server/src/main/java/io/seata/server/session/SessionHolder.java b/server/src/main/java/io/seata/server/session/SessionHolder.java index 30f4b4d00b3..316b6e11d99 100644 --- a/server/src/main/java/io/seata/server/session/SessionHolder.java +++ b/server/src/main/java/io/seata/server/session/SessionHolder.java @@ -21,6 +21,7 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.exception.StoreException; +import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; @@ -46,6 +47,11 @@ public class SessionHolder { */ protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + /** + * The constant DEFAULT. + */ + public static final String DEFAULT = "default"; + /** * The constant ROOT_SESSION_MANAGER_NAME. */ @@ -82,23 +88,33 @@ public static void init(String mode) throws IOException { //the store mode StoreMode storeMode = StoreMode.valueof(mode); if (StoreMode.DB.equals(storeMode)) { - //TODO database store - + //database store + ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name()); + ASYNC_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name(), new Object[]{ASYNC_COMMITTING_SESSION_MANAGER_NAME});; + RETRY_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name(), new Object[]{RETRY_COMMITTING_SESSION_MANAGER_NAME});; + RETRY_ROLLBACKING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name(), new Object[]{RETRY_ROLLBACKING_SESSION_MANAGER_NAME});; } else if (StoreMode.FILE.equals(storeMode)) { //file store String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR); if (sessionStorePath == null) { throw new StoreException("the {store.file.dir} is empty."); } - ROOT_SESSION_MANAGER = new FileBasedSessionManager(ROOT_SESSION_MANAGER_NAME, sessionStorePath); - ASYNC_COMMITTING_SESSION_MANAGER = new DefaultSessionManager(ASYNC_COMMITTING_SESSION_MANAGER_NAME); - RETRY_COMMITTING_SESSION_MANAGER = new DefaultSessionManager(RETRY_COMMITTING_SESSION_MANAGER_NAME); - RETRY_ROLLBACKING_SESSION_MANAGER = new DefaultSessionManager(RETRY_ROLLBACKING_SESSION_MANAGER_NAME); + ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.FILE.name(), new Object[]{ROOT_SESSION_MANAGER_NAME, sessionStorePath}); + ASYNC_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, DEFAULT, new Object[]{ASYNC_COMMITTING_SESSION_MANAGER_NAME});; + RETRY_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, DEFAULT, new Object[]{RETRY_COMMITTING_SESSION_MANAGER_NAME});; + RETRY_ROLLBACKING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, DEFAULT, new Object[]{RETRY_ROLLBACKING_SESSION_MANAGER_NAME});; } else { //unknown store throw new IllegalArgumentException("unknown store mode:" + mode); } + //relaod + reload(); + } + /** + * Reload. + */ + protected static void reload(){ if (ROOT_SESSION_MANAGER instanceof Reloadable) { ((Reloadable) ROOT_SESSION_MANAGER).reload(); @@ -173,7 +189,6 @@ public static void init(String mode) throws IOException { }); } } - } /** @@ -227,11 +242,11 @@ public static final SessionManager getRetryRollbackingSessionManager() { /** * Find global session. * - * @param transactionId the transaction id + * @param xid the xid * @return the global session */ - public static GlobalSession findGlobalSession(Long transactionId) { - return getRootSessionManager().findGlobalSession(transactionId); + public static GlobalSession findGlobalSession(String xid) { + return getRootSessionManager().findGlobalSession(xid); } public static void destory() { diff --git a/server/src/main/java/io/seata/server/session/SessionManager.java b/server/src/main/java/io/seata/server/session/SessionManager.java index 2883d440482..e7e94017191 100644 --- a/server/src/main/java/io/seata/server/session/SessionManager.java +++ b/server/src/main/java/io/seata/server/session/SessionManager.java @@ -41,11 +41,10 @@ public interface SessionManager extends SessionLifecycleListener, Disposable { /** * Find global session global session. * - * @param transactionId the transaction id + * @param xid the xid * @return the global session - * @throws TransactionException the transaction exception */ - GlobalSession findGlobalSession(Long transactionId); + GlobalSession findGlobalSession(String xid) ; /** * Update global session status. diff --git a/server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java b/server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java new file mode 100644 index 00000000000..333b78e3ba1 --- /dev/null +++ b/server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java @@ -0,0 +1,186 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.session.db; + +import io.seata.common.exception.StoreException; +import io.seata.common.executor.Initialize; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.StringUtils; +import io.seata.core.exception.TransactionException; +import io.seata.core.model.BranchStatus; +import io.seata.core.model.GlobalStatus; +import io.seata.core.store.StoreMode; +import io.seata.server.session.AbstractSessionManager; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionCondition; +import io.seata.server.session.SessionHolder; +import io.seata.server.session.SessionLifecycleListener; +import io.seata.server.session.SessionManager; +import io.seata.server.store.TransactionStoreManager; +import io.seata.server.store.TransactionStoreManager.LogOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.List; + +/** + * The Data base session manager. + * + * @author zhangsen + * @data 2019 /4/4 + */ +@LoadLevel(name = "db") +public class DataBaseSessionManager extends AbstractSessionManager implements SessionManager, SessionLifecycleListener, Initialize { + + /** + * The constant LOGGER. + */ + protected static final Logger LOGGER = LoggerFactory.getLogger(DataBaseSessionManager.class); + + /** + * The Task name. + */ + protected String taskName; + + /** + * Instantiates a new Data base session manager. + */ + public DataBaseSessionManager() { + super(); + } + + /** + * Instantiates a new Data base session manager. + * + * @param name the name + */ + public DataBaseSessionManager(String name) { + super(); + this.taskName = name; + } + + @Override + public void init() { + transactionStoreManager = EnhancedServiceLoader.load(TransactionStoreManager.class, StoreMode.DB.name()); + } + + @Override + public void addGlobalSession(GlobalSession session) throws TransactionException { + if (StringUtils.isBlank(taskName)) { + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_ADD, session); + if (!ret) { + throw new StoreException("addGlobalSession failed."); + } + }else { + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); + if (!ret) { + throw new StoreException("addGlobalSession failed."); + } + } + } + + @Override + public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { + if (StringUtils.isNotBlank(taskName)) { + return; + } + session.setStatus(status); + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); + if (!ret) { + throw new StoreException("updateGlobalSessionStatus failed."); + } + } + + @Override + public void removeGlobalSession(GlobalSession session) throws TransactionException { + if (StringUtils.isNotBlank(taskName)) { + return; + } + boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_REMOVE, session); + if (!ret) { + throw new StoreException("removeGlobalSession failed."); + } + } + + @Override + public void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { + if (StringUtils.isNotBlank(taskName)) { + return; + } + boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_ADD, session); + if (!ret) { + throw new StoreException("addBranchSession failed."); + } + } + + @Override + public void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException { + if (StringUtils.isNotBlank(taskName)) { + return; + } + boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_UPDATE, session); + if (!ret) { + throw new StoreException("updateBranchSessionStatus failed."); + } + } + + @Override + public void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { + if (StringUtils.isNotBlank(taskName)) { + return; + } + boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_REMOVE, session); + if (!ret) { + throw new StoreException("removeBranchSession failed."); + } + } + + @Override + public GlobalSession findGlobalSession(String xid) { + return transactionStoreManager.readSession(xid); + } + + @Override + public Collection allSessions() { + //get by taskName + if (SessionHolder.ASYNC_COMMITTING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { + return findGlobalSessions(new SessionCondition(GlobalStatus.AsyncCommitting)); + } else if (SessionHolder.RETRY_COMMITTING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { + return findGlobalSessions(new SessionCondition(new GlobalStatus[]{GlobalStatus.CommitRetrying})); + } else if (SessionHolder.RETRY_ROLLBACKING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { + return findGlobalSessions(new SessionCondition(new GlobalStatus[]{GlobalStatus.RollbackRetrying, + GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying})); + } else { + //all data + return findGlobalSessions(new SessionCondition(new GlobalStatus[]{ + GlobalStatus.UnKnown, GlobalStatus.Begin, + GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Rollbacking, GlobalStatus.RollbackRetrying, + GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying, GlobalStatus.AsyncCommitting})); + } + } + + @Override + public List findGlobalSessions(SessionCondition condition) { + //nothing need to do + return transactionStoreManager.readSession(condition); + } + + + +} \ No newline at end of file diff --git a/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java b/server/src/main/java/io/seata/server/session/file/FileBasedSessionManager.java similarity index 71% rename from server/src/main/java/io/seata/server/session/FileBasedSessionManager.java rename to server/src/main/java/io/seata/server/session/file/FileBasedSessionManager.java index 1684cccdfac..02ade24cefb 100644 --- a/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java +++ b/server/src/main/java/io/seata/server/session/file/FileBasedSessionManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.session; +package io.seata.server.session.file; import java.io.File; import java.io.IOException; @@ -23,21 +23,31 @@ import java.util.Map; import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.LoadLevel; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.model.GlobalStatus; +import io.seata.core.store.StoreMode; +import io.seata.server.session.BranchSession; +import io.seata.server.session.DefaultSessionManager; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.Reloadable; +import io.seata.server.session.SessionManager; +import io.seata.server.store.ReloadableStore; import io.seata.server.UUIDGenerator; -import io.seata.server.store.FileTransactionStoreManager; import io.seata.server.store.SessionStorable; import io.seata.server.store.TransactionStoreManager; import io.seata.server.store.TransactionWriteStore; + /** * The type File based session manager. * * @author jimin.jm @alibaba-inc.com */ -public class FileBasedSessionManager extends AbstractSessionManager implements Reloadable { +@LoadLevel(name = "file") +public class FileBasedSessionManager extends DefaultSessionManager implements Reloadable { private static final int READ_SIZE = ConfigurationFactory.getInstance().getInt( ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE, 100); @@ -51,7 +61,9 @@ public class FileBasedSessionManager extends AbstractSessionManager implements R */ public FileBasedSessionManager(String name, String sessionStoreFilePath) throws IOException { super(name); - transactionStoreManager = new FileTransactionStoreManager(sessionStoreFilePath + File.separator + name, this); + transactionStoreManager = EnhancedServiceLoader.load(TransactionStoreManager.class, StoreMode.FILE.name(), + new Class[]{String.class, SessionManager.class}, + new Object[]{sessionStoreFilePath + File.separator + name, this}); } @Override @@ -68,13 +80,13 @@ private void restoreSessions() { if (!unhandledBranchBuffer.isEmpty()) { unhandledBranchBuffer.values().forEach(branchSession -> { - long tid = branchSession.getTransactionId(); + String xid = branchSession.getXid(); long bid = branchSession.getBranchId(); - GlobalSession found = sessionMap.get(tid); + GlobalSession found = sessionMap.get(xid); if (found == null) { // Ignore if (LOGGER.isInfoEnabled()) { - LOGGER.info("GlobalSession Does Not Exists For BranchSession [" + bid + "/" + tid + "]"); + LOGGER.info("GlobalSession Does Not Exists For BranchSession [" + bid + "/" + xid + "]"); } } else { BranchSession existingBranch = found.getBranch(branchSession.getBranchId()); @@ -91,7 +103,7 @@ private void restoreSessions() { private void washSessions() { if (sessionMap.size() > 0) { - Iterator> iterator = sessionMap.entrySet().iterator(); + Iterator> iterator = sessionMap.entrySet().iterator(); while (iterator.hasNext()) { GlobalSession globalSession = iterator.next().getValue(); @@ -116,8 +128,11 @@ private void washSessions() { } private void restoreSessions(boolean isHistory, Map unhandledBranchBuffer) { - while (transactionStoreManager.hasRemaining(isHistory)) { - List stores = transactionStoreManager.readWriteStoreFromFile(READ_SIZE, isHistory); + if(!(transactionStoreManager instanceof ReloadableStore)){ + return; + } + while (((ReloadableStore)transactionStoreManager).hasRemaining(isHistory)) { + List stores = ((ReloadableStore)transactionStoreManager).readWriteStore(READ_SIZE, isHistory); restore(stores, unhandledBranchBuffer); } } @@ -131,31 +146,40 @@ private void restore(List stores, Map stores, Map readSession(SessionCondition sessionCondition) { + return null; + } + + @Override + public void shutdown() { + } +} diff --git a/server/src/main/java/io/seata/server/lock/LockManagerFactory.java b/server/src/main/java/io/seata/server/store/ReloadableStore.java similarity index 54% rename from server/src/main/java/io/seata/server/lock/LockManagerFactory.java rename to server/src/main/java/io/seata/server/store/ReloadableStore.java index 3468cc89449..d7b705c65a8 100644 --- a/server/src/main/java/io/seata/server/lock/LockManagerFactory.java +++ b/server/src/main/java/io/seata/server/store/ReloadableStore.java @@ -13,34 +13,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.lock; +package io.seata.server.store; + +import java.util.List; /** - * The type Lock manager factory. + * The interface Reloadable store. * - * @author sharajava + * @author zhangsen + * @data 2019 /4/24 */ -public class LockManagerFactory { - - private static class SingletonHolder { - private static LockManager INSTANCE = new DefaultLockManagerImpl(); - } +public interface ReloadableStore { /** - * Get lock manager. + * Read write store. * - * @return the lock manager + * @param readSize the read size + * @param isHistory the is history + * @return the list */ - public static final LockManager get() { - return SingletonHolder.INSTANCE; - } + List readWriteStore(int readSize, boolean isHistory); /** - * Just for test mocking + * Has remaining boolean. * - * @param lockManager the lock manager + * @param isHistory the is history + * @return the boolean */ - public static void set(LockManager lockManager) { - SingletonHolder.INSTANCE = lockManager; - } + boolean hasRemaining(boolean isHistory); + + } diff --git a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java index da7d44a4ad9..26dc122009c 100644 --- a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java @@ -15,6 +15,9 @@ */ package io.seata.server.store; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionCondition; + import java.util.List; /** @@ -33,27 +36,28 @@ public interface TransactionStoreManager { */ boolean writeSession(LogOperation logOperation, SessionStorable session); + /** - * Shutdown. + * Read global session global session. + * + * @param xid the xid + * @return the global session */ - void shutdown(); + GlobalSession readSession(String xid); /** - * Read write store from file list. + * Read session by status list. * - * @param readSize the read size - * @param isHistory the is history + * @param sessionCondition the session condition * @return the list */ - List readWriteStoreFromFile(int readSize, boolean isHistory); + List readSession(SessionCondition sessionCondition); /** - * Has remaining boolean. - * - * @param isHistory the is history - * @return the boolean + * Shutdown. */ - boolean hasRemaining(boolean isHistory); + void shutdown(); + /** * The enum Log operation. diff --git a/server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java b/server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java new file mode 100644 index 00000000000..1cce734f8ea --- /dev/null +++ b/server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java @@ -0,0 +1,299 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.store.db; + + +import io.seata.common.exception.StoreException; +import io.seata.common.executor.Initialize; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.model.BranchStatus; +import io.seata.core.model.BranchType; +import io.seata.core.model.GlobalStatus; +import io.seata.core.store.BranchTransactionDO; +import io.seata.core.store.GlobalTransactionDO; +import io.seata.core.store.LogStore; +import io.seata.core.store.StoreMode; +import io.seata.core.store.db.DataSourceGenerator; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionCondition; +import io.seata.server.store.AbstractTransactionStoreManager; +import io.seata.server.store.SessionStorable; +import io.seata.server.store.TransactionStoreManager; + +import javax.sql.DataSource; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * The type Database transaction store manager. + * + * @author zhangsen + * @data 2019 /4/2 + */ +@LoadLevel(name = "db") +public class DatabaseTransactionStoreManager extends AbstractTransactionStoreManager implements TransactionStoreManager, Initialize { + + /** + * The constant CONFIG. + */ + protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); + + /** + * The constant DEFAULT_LOG_QUERY_LIMIT. + */ + protected static final int DEFAULT_LOG_QUERY_LIMIT = 100; + + /** + * is inited + */ + protected AtomicBoolean inited = new AtomicBoolean(false); + + /** + * The Log store. + */ + protected LogStore logStore ; + + + /** + * The Log query limit. + */ + protected int logQueryLimit ; + + /** + * Instantiates a new Database transaction store manager. + */ + public DatabaseTransactionStoreManager(){ + } + + @Override + public synchronized void init(){ + if(inited.get()){ + return ; + } + logQueryLimit = CONFIG.getInt(ConfigurationKeys.STORE_DB_LOG_QUERY_LIMIT, DEFAULT_LOG_QUERY_LIMIT); + String datasourceType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + //init dataSource + DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, datasourceType); + DataSource logStoreDataSource = dataSourceGenerator.generateDataSource(); + logStore = EnhancedServiceLoader.load(LogStore.class, StoreMode.DB.name(), new Class[]{DataSource.class}, new Object[]{logStoreDataSource}); + inited.set(true); + } + + @Override + public boolean writeSession(LogOperation logOperation, SessionStorable session) { + if (LogOperation.GLOBAL_ADD.equals(logOperation)){ + logStore.insertGlobalTransactionDO(convertGlobalTransactionDO(session)); + }else if(LogOperation.GLOBAL_UPDATE.equals(logOperation)){ + logStore.updateGlobalTransactionDO(convertGlobalTransactionDO(session)); + }else if(LogOperation.GLOBAL_REMOVE.equals(logOperation)){ + logStore.deleteGlobalTransactionDO(convertGlobalTransactionDO(session)); + }else if(LogOperation.BRANCH_ADD.equals(logOperation)){ + logStore.insertBranchTransactionDO(convertBranchTransactionDO(session)); + }else if(LogOperation.BRANCH_UPDATE.equals(logOperation)){ + logStore.updateBranchTransactionDO(convertBranchTransactionDO(session)); + }else if(LogOperation.BRANCH_REMOVE.equals(logOperation)){ + logStore.deleteBranchTransactionDO(convertBranchTransactionDO(session)); + }else { + throw new StoreException("Unknown LogOperation:" + logOperation.name()); + } + return true; + } + + /** + * Read session global session. + * + * @param transactionId the transaction id + * @return the global session + */ + public GlobalSession readSession(Long transactionId) { + //global transaction + GlobalTransactionDO globalTransactionDO = logStore.queryGlobalTransactionDO(transactionId); + if(globalTransactionDO == null){ + return null; + } + //branch transactions + List branchTransactionDOs = logStore.queryBranchTransactionDO(globalTransactionDO.getXid()); + return getGlobalSession(globalTransactionDO, branchTransactionDOs); + } + + /** + * Read session global session. + * + * @param xid the xid + * @return the global session + */ + @Override + public GlobalSession readSession(String xid) { + //global transaction + GlobalTransactionDO globalTransactionDO = logStore.queryGlobalTransactionDO(xid); + if(globalTransactionDO == null){ + return null; + } + //branch transactions + List branchTransactionDOs = logStore.queryBranchTransactionDO(globalTransactionDO.getXid()); + return getGlobalSession(globalTransactionDO, branchTransactionDOs); + } + + /** + * Read session list. + * + * @param statuses the statuses + * @return the list + */ + public List readSession(GlobalStatus[] statuses) { + int[] states = new int[statuses.length]; + for(int i = 0; i < statuses.length; i++){ + states[i] = statuses[i].getCode(); + } + List globalSessions = new ArrayList(); + //global transaction + List globalTransactionDOs = logStore.queryGlobalTransactionDO(states, logQueryLimit); + if(CollectionUtils.isEmpty(globalTransactionDOs)){ + return null; + } + for(GlobalTransactionDO globalTransactionDO : globalTransactionDOs){ + List branchTransactionDOs = logStore.queryBranchTransactionDO(globalTransactionDO.getXid()); + globalSessions.add(getGlobalSession(globalTransactionDO, branchTransactionDOs)); + } + return globalSessions; + } + + @Override + public List readSession(SessionCondition sessionCondition) { + if(StringUtils.isNotBlank(sessionCondition.getXid())){ + GlobalSession globalSession = readSession(sessionCondition.getXid()); + if(globalSession != null){ + List globalSessions = new ArrayList(); + globalSessions.add(globalSession); + return globalSessions; + } + }else if(sessionCondition.getTransactionId() != null){ + GlobalSession globalSession = readSession(sessionCondition.getTransactionId()); + if(globalSession != null){ + List globalSessions = new ArrayList(); + globalSessions.add(globalSession); + return globalSessions; + } + }else if(CollectionUtils.isNotEmpty(sessionCondition.getStatuses())){ + return readSession(sessionCondition.getStatuses()); + } + return null; + } + + private GlobalSession getGlobalSession(GlobalTransactionDO globalTransactionDO, List branchTransactionDOs){ + GlobalSession globalSession = convertGlobalSession(globalTransactionDO); + //branch transactions + if(branchTransactionDOs != null && branchTransactionDOs.size() > 0){ + for(BranchTransactionDO branchTransactionDO : branchTransactionDOs){ + globalSession.add(convertBranchSession(branchTransactionDO)); + } + } + return globalSession; + } + + private GlobalSession convertGlobalSession(GlobalTransactionDO globalTransactionDO){ + GlobalSession session = new GlobalSession(globalTransactionDO.getApplicationId(), + globalTransactionDO.getTransactionServiceGroup(), + globalTransactionDO.getTransactionName(), + globalTransactionDO.getTimeout()); + session.setTransactionId(globalTransactionDO.getTransactionId()); + session.setXid(globalTransactionDO.getXid()); + session.setStatus(GlobalStatus.get(globalTransactionDO.getStatus())); + session.setApplicationData(globalTransactionDO.getApplicationData()); + session.setBeginTime(globalTransactionDO.getBeginTime()); + return session; + } + + private BranchSession convertBranchSession(BranchTransactionDO branchTransactionDO){ + BranchSession branchSession = new BranchSession(); + branchSession.setXid(branchTransactionDO.getXid()); + branchSession.setTransactionId(branchTransactionDO.getTransactionId()); + branchSession.setApplicationData(branchTransactionDO.getApplicationData()); + branchSession.setBranchId(branchTransactionDO.getBranchId()); + branchSession.setBranchType(BranchType.valueOf(branchTransactionDO.getBranchType())); + branchSession.setResourceId(branchTransactionDO.getResourceId()); + branchSession.setClientId(branchTransactionDO.getClientId()); + branchSession.setLockKey(branchTransactionDO.getLockKey()); + branchSession.setResourceGroupId(branchTransactionDO.getResourceGroupId()); + branchSession.setStatus(BranchStatus.get(branchTransactionDO.getStatus())); + return branchSession; + } + + private GlobalTransactionDO convertGlobalTransactionDO(SessionStorable session){ + if(session == null || !(session instanceof GlobalSession)){ + throw new IllegalArgumentException("the parameter of SessionStorable is not available, SessionStorable:" + StringUtils.toString(session)); + } + GlobalSession globalSession = (GlobalSession) session; + + GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); + globalTransactionDO.setXid(globalSession.getXid()); + globalTransactionDO.setStatus(globalSession.getStatus().getCode()); + globalTransactionDO.setApplicationId(globalSession.getApplicationId()); + globalTransactionDO.setBeginTime(globalSession.getBeginTime()); + globalTransactionDO.setTimeout(globalSession.getTimeout()); + globalTransactionDO.setTransactionId(globalSession.getTransactionId()); + globalTransactionDO.setTransactionName(globalSession.getTransactionName()); + globalTransactionDO.setTransactionServiceGroup(globalSession.getTransactionServiceGroup()); + globalTransactionDO.setApplicationData(globalSession.getApplicationData()); + return globalTransactionDO; + } + + private BranchTransactionDO convertBranchTransactionDO(SessionStorable session){ + if(session == null || !(session instanceof BranchSession)){ + throw new IllegalArgumentException("the parameter of SessionStorable is not available, SessionStorable:" + StringUtils.toString(session)); + } + BranchSession branchSession = (BranchSession) session; + + BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); + branchTransactionDO.setXid(branchSession.getXid()); + branchTransactionDO.setBranchId(branchSession.getBranchId()); + branchTransactionDO.setBranchType(branchSession.getBranchType().name()); + branchTransactionDO.setClientId(branchSession.getClientId()); + branchTransactionDO.setLockKey(branchSession.getLockKey()); + branchTransactionDO.setResourceGroupId(branchSession.getResourceGroupId()); + branchTransactionDO.setTransactionId(branchSession.getTransactionId()); + branchTransactionDO.setApplicationData(branchSession.getApplicationData()); + branchTransactionDO.setResourceId(branchSession.getResourceId()); + branchTransactionDO.setStatus(branchSession.getStatus().getCode()); + return branchTransactionDO; + } + + /** + * Sets log store. + * + * @param logStore the log store + */ + public void setLogStore(LogStore logStore) { + this.logStore = logStore; + } + + /** + * Sets log query limit. + * + * @param logQueryLimit the log query limit + */ + public void setLogQueryLimit(int logQueryLimit) { + this.logQueryLimit = logQueryLimit; + } +} \ No newline at end of file diff --git a/server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java b/server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java new file mode 100644 index 00000000000..2cc8e14929e --- /dev/null +++ b/server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java @@ -0,0 +1,54 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.store.db; + +import io.seata.common.loader.LoadLevel; +import io.seata.core.store.db.AbstractDataSourceGenerator; +import org.apache.commons.dbcp.BasicDataSource; + +import javax.sql.DataSource; + +/** + * The type Dbcp data source generator. + * + * @author zhangsen + * @data 2019 /4/24 + */ +@LoadLevel(name = "dbcp") +public class DbcpDataSourceGenerator extends AbstractDataSourceGenerator { + + @Override + public DataSource generateDataSource() { + BasicDataSource ds = new BasicDataSource(); + ds.setDriverClassName(getDriverName(getDBType())); + ds.setUrl(getUrl()); + ds.setUsername(getUser()); + ds.setPassword(getPassword()); + ds.setInitialSize(getMinConn()); + ds.setMaxActive(getMaxConn()); + ds.setMinIdle(getMinConn()); + ds.setMaxIdle(getMinConn()); + ds.setMaxWait(5000); + ds.setTimeBetweenEvictionRunsMillis(120000); + ds.setNumTestsPerEvictionRun(1); + ds.setTestWhileIdle(true); + ds.setValidationQuery(getValidationQuery(getDBType())); + ds.setConnectionProperties("useUnicode=yes;characterEncoding=utf8;socketTimeout=5000;connectTimeout=500"); + return ds; + } + + +} diff --git a/server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java b/server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java new file mode 100644 index 00000000000..04ddfe77b63 --- /dev/null +++ b/server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java @@ -0,0 +1,54 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.store.db; + +import com.alibaba.druid.pool.DruidDataSource; +import io.seata.common.loader.LoadLevel; +import io.seata.core.store.db.AbstractDataSourceGenerator; + +import javax.sql.DataSource; + +/** + * The type Druid data source generator. + * + * @author zhangsen + * @data 2019 /4/28 + */ +@LoadLevel(name = "druid") +public class DruidDataSourceGenerator extends AbstractDataSourceGenerator { + + @Override + public DataSource generateDataSource() { + DruidDataSource ds = new DruidDataSource(); + ds.setDriverClassName(getDriverName(getDBType())); + ds.setUrl(getUrl()); + ds.setUsername(getUser()); + ds.setPassword(getPassword()); + ds.setInitialSize(getMinConn()); + ds.setMaxActive(getMaxConn()); + ds.setMinIdle(getMinConn()); + ds.setMaxWait(5000); + ds.setTimeBetweenEvictionRunsMillis(120000); + ds.setMinEvictableIdleTimeMillis(300000); + ds.setTestWhileIdle(true); + ds.setTestOnBorrow(true); + ds.setPoolPreparedStatements(true); + ds.setMaxPoolPreparedStatementPerConnectionSize(20); + ds.setValidationQuery(getValidationQuery(getDBType())); + ds.setDefaultAutoCommit(true); + return ds; + } +} diff --git a/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java b/server/src/main/java/io/seata/server/store/file/FileTransactionStoreManager.java similarity index 92% rename from server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java rename to server/src/main/java/io/seata/server/store/file/FileTransactionStoreManager.java index 9b3a32229c5..5f8e42d8a31 100644 --- a/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/store/file/FileTransactionStoreManager.java @@ -13,16 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.store; - -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.CollectionUtils; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.session.SessionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package io.seata.server.store.file; import java.io.File; import java.io.IOException; @@ -33,17 +24,39 @@ import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; +import io.seata.common.exception.StoreException; +import io.seata.common.loader.LoadLevel; +import io.seata.common.thread.NamedThreadFactory; +import io.seata.common.util.CollectionUtils; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionCondition; +import io.seata.server.session.SessionManager; +import io.seata.server.store.AbstractTransactionStoreManager; +import io.seata.server.store.FlushDiskMode; +import io.seata.server.store.ReloadableStore; +import io.seata.server.store.SessionStorable; +import io.seata.server.store.StoreConfig; +import io.seata.server.store.TransactionStoreManager; +import io.seata.server.store.TransactionWriteStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * The type File transaction store manager. * * @author jimin.jm @alibaba-inc.com */ -public class FileTransactionStoreManager implements TransactionStoreManager { - +@LoadLevel(name = "file") +public class FileTransactionStoreManager extends AbstractTransactionStoreManager implements TransactionStoreManager, ReloadableStore { private static final Logger LOGGER = LoggerFactory.getLogger(FileTransactionStoreManager.class); private static final int MAX_THREAD_WRITE = 1; @@ -119,8 +132,7 @@ public class FileTransactionStoreManager implements TransactionStoreManager { */ public FileTransactionStoreManager(String fullFileName, SessionManager sessionManager) throws IOException { initFile(fullFileName); - fileWriteExecutor = - new ThreadPoolExecutor(MAX_THREAD_WRITE, MAX_THREAD_WRITE, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, + fileWriteExecutor = new ThreadPoolExecutor(MAX_THREAD_WRITE, MAX_THREAD_WRITE, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("fileTransactionStore", MAX_THREAD_WRITE, true)); writeDataFileRunnable = new WriteDataFileRunnable(); @@ -247,6 +259,16 @@ private boolean findTimeoutAndSave() throws IOException { return false; } + @Override + public GlobalSession readSession(String xid) { + throw new StoreException("unsupport for read from file, xid:" + xid); + } + + @Override + public List readSession(SessionCondition sessionCondition) { + throw new StoreException("unsupport for read from file"); + } + @Override public void shutdown() { if (null != fileWriteExecutor) { @@ -257,7 +279,7 @@ public void shutdown() { ++retry; try { Thread.sleep(SHUTDOWN_CHECK_INTERNAL); - } catch (InterruptedException exx) { + } catch (InterruptedException ignore) { } } if (retry >= MAX_SHUTDOWN_RETRY) { @@ -273,7 +295,7 @@ public void shutdown() { } @Override - public List readWriteStoreFromFile(int readSize, boolean isHistory) { + public List readWriteStore(int readSize, boolean isHistory) { File file = null; long currentOffset = 0; if (isHistory) { @@ -305,7 +327,7 @@ public boolean hasRemaining(boolean isHistory) { raf = new RandomAccessFile(file, "r"); return currentOffset < raf.length(); - } catch (IOException exx) { + } catch (IOException ignore) { } finally { closeFile(raf); } @@ -512,7 +534,7 @@ public void run() { StoreRequest storeRequest = storeRequests.poll(MAX_WAIT_TIME_MILLS, TimeUnit.MILLISECONDS); handleStoreRequest(storeRequest); } catch (Exception exx) { - LOGGER.error("write file error", exx.getMessage()); + LOGGER.error("write file error: {}", exx.getMessage(), exx); } } handleRestRequest(); diff --git a/server/src/main/resources/META-INF/services/io.seata.core.lock.Locker b/server/src/main/resources/META-INF/services/io.seata.core.lock.Locker new file mode 100644 index 00000000000..d8b311d6e93 --- /dev/null +++ b/server/src/main/resources/META-INF/services/io.seata.core.lock.Locker @@ -0,0 +1,2 @@ +io.seata.server.lock.memory.MemoryLocker +io.seata.server.lock.db.DataBaseLocker \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator b/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator new file mode 100644 index 00000000000..68b9548e561 --- /dev/null +++ b/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator @@ -0,0 +1,2 @@ +io.seata.server.store.db.DbcpDataSourceGenerator +io.seata.server.store.db.DruidDataSourceGenerator \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager b/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager new file mode 100644 index 00000000000..9d3f0808a60 --- /dev/null +++ b/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager @@ -0,0 +1,3 @@ +io.seata.server.session.file.FileBasedSessionManager +io.seata.server.session.db.DataBaseSessionManager +io.seata.server.session.DefaultSessionManager \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager b/server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager new file mode 100644 index 00000000000..948d6c079dd --- /dev/null +++ b/server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager @@ -0,0 +1,2 @@ +io.seata.server.store.db.DatabaseTransactionStoreManager +io.seata.server.store.file.FileTransactionStoreManager \ No newline at end of file diff --git a/server/src/main/resources/db_store.sql b/server/src/main/resources/db_store.sql new file mode 100644 index 00000000000..78b4fa01871 --- /dev/null +++ b/server/src/main/resources/db_store.sql @@ -0,0 +1,52 @@ +-- the table to store GlobalSession data +drop table `global_table`; +create table `global_table` ( + `xid` varchar(128) not null, + `transaction_id` bigint, + `status` tinyint not null, + `application_id` varchar(32), + `transaction_service_group` varchar(32), + `transaction_name` varchar(64), + `timeout` int, + `begin_time` bigint, + `application_data` varchar(2000), + `gmt_create` datetime, + `gmt_modified` datetime, + primary key (`xid`), + key `idx_gmt_modified_status` (`gmt_modified`, `status`), + key `idx_transaction_id` (`transaction_id`) +); + +-- the table to store BranchSession data +drop table `branch_table`; +create table `branch_table` ( + `branch_id` bigint not null, + `xid` varchar(128) not null, + `transaction_id` bigint , + `resource_group_id` varchar(32), + `resource_id` varchar(256) , + `lock_key` varchar(128) , + `branch_type` varchar(8) , + `status` tinyint, + `client_id` varchar(64), + `application_data` varchar(2000), + `gmt_create` datetime, + `gmt_modified` datetime, + primary key (`branch_id`), + key `idx_xid` (`xid`) +); + +-- the table to store lock data +drop table `lock_table`; +create table `lock_table` ( + `row_key` varchar(128) not null, + `xid` varchar(96), + `transaction_id` long , + `branch_id` long, + `resource_id` varchar(256) , + `table_name` varchar(32) , + `pk` varchar(32) , + `gmt_create` datetime , + `gmt_modified` datetime, + primary key(`row_key`) +); diff --git a/server/src/main/resources/file.conf b/server/src/main/resources/file.conf index dc908a344ef..59e21433299 100644 --- a/server/src/main/resources/file.conf +++ b/server/src/main/resources/file.conf @@ -29,6 +29,9 @@ service { enableDegrade = false #disable disable = false + #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent + max.commit.retry.timeout = "-1" + max.rollback.retry.timeout = "-1" } client { @@ -63,10 +66,44 @@ store { ## database store db { - driver_class = "" - url = "" - user = "" - password = "" - } + ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. + datasource = "dbcp" + ## mysql/oracle/h2/oceanbase etc. + db-type = "mysql" + url = "jdbc:mysql://127.0.0.1:3306/seata" + user = "mysql" + password = "mysql" + min-conn = 1 + max-conn = 3 + global.table = "global_table" + branch.table = "branch_table" + query-limit = 100 + } +} +lock { + ## the data row lock store mode: local_db、memory or db + mode = "memory" + + memory{ + ## store lock in memory of server + } + db{ + ## use db of server to store lock, the db is ${store.db.url} + lock-table= "lock_table" + } + + local_db { + ## store lock in local db + } +} +recovery{ + committing-retry-delay = 5 + asyn-committing-retry-delay = 5 + rollbacking-retry-delay = 5 + timeout-retry-delay = 5 } + +transaction { + undo.data.validation = true +} \ No newline at end of file diff --git a/server/src/main/resources/logback.xml b/server/src/main/resources/logback.xml index 62d9e1acd56..4f2b1d02edc 100644 --- a/server/src/main/resources/logback.xml +++ b/server/src/main/resources/logback.xml @@ -41,7 +41,7 @@ - + diff --git a/server/src/main/resources/nacos-config.txt b/server/src/main/resources/nacos-config.txt index 254a8db09d4..b80827982df 100644 --- a/server/src/main/resources/nacos-config.txt +++ b/server/src/main/resources/nacos-config.txt @@ -13,6 +13,8 @@ transport.thread-factory.worker-thread-size=8 service.vgroup_mapping.my_test_tx_group=default service.enableDegrade=false service.disable=false +service.max.commit.retry.timeout=-1 +service.max.rollback.retry.timeout=-1 client.async.commit.buffer.limit=10000 client.lock.retry.internal=10 client.lock.retry.times=30 @@ -23,7 +25,21 @@ store.file.max-global-session-size=512 store.file.file-write-buffer-cache-size=16384 store.file.flush-disk-mode=async store.file.session.reload.read_size=100 -store.db.driver_class=com.mysql.jdbc.Driver -store.db.url=jdbc:mysql://localhost:3306/seata_demo -store.db.user=user -store.db.password=password \ No newline at end of file +store.db.datasource=dbcp +store.db.db-type=mysql +store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true +store.db.user=mysql +store.db.password=mysql +store.db.min-conn=1 +store.db.max-conn=3 +store.db.global.table=global_table +store.db.branch.table=branch_table +store.db.query-limit=100 +lock.mode=memory +lock.db.lock-table=lock_table +recovery.committing-retry-delay = 5 +recovery.asyn-committing-retry-delay = 5 +recovery.rollbacking-retry-delay = 5 +recovery.timeout-retry-delay = 5 +transaction.undo.data.validation=true + diff --git a/server/src/main/resources/registry.conf b/server/src/main/resources/registry.conf index 1cddea72194..66b963d139a 100644 --- a/server/src/main/resources/registry.conf +++ b/server/src/main/resources/registry.conf @@ -45,7 +45,7 @@ registry { } config { - # file、nacos 、apollo、zk、consul + # file、nacos 、apollo、zk、consul、etcd3 type = "file" nacos { @@ -65,6 +65,9 @@ config { session.timeout = 6000 connect.timeout = 2000 } + etcd3 { + serverAddr = "http://localhost:2379" + } file { name = "file.conf" } diff --git a/server/src/test/java/WriteStoreMultithreadTest.java b/server/src/test/java/WriteStoreMultithreadTest.java index 94eb5c88770..360759f5b69 100644 --- a/server/src/test/java/WriteStoreMultithreadTest.java +++ b/server/src/test/java/WriteStoreMultithreadTest.java @@ -20,8 +20,8 @@ import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionCondition; import io.seata.server.session.SessionManager; -import io.seata.server.store.FileTransactionStoreManager; import io.seata.server.store.TransactionStoreManager; +import io.seata.server.store.file.FileTransactionStoreManager; import java.util.ArrayList; import java.util.Collection; @@ -55,10 +55,11 @@ public void addGlobalSession(GlobalSession session) throws TransactionException } @Override - public GlobalSession findGlobalSession(Long transactionId) { + public GlobalSession findGlobalSession(String xid) { return null; } + @Override public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { diff --git a/server/src/test/java/WriteStoreTest.java b/server/src/test/java/WriteStoreTest.java index 9f9964d1b86..d2056f75f63 100644 --- a/server/src/test/java/WriteStoreTest.java +++ b/server/src/test/java/WriteStoreTest.java @@ -27,11 +27,13 @@ import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionCondition; import io.seata.server.session.SessionManager; -import io.seata.server.store.FileTransactionStoreManager; +import io.seata.server.store.ReloadableStore; import io.seata.server.store.SessionStorable; import io.seata.server.store.TransactionStoreManager; import io.seata.server.store.TransactionStoreManager.LogOperation; import io.seata.server.store.TransactionWriteStore; +import io.seata.server.store.file.FileTransactionStoreManager; + /** * The type Write store test. @@ -71,7 +73,7 @@ public void addGlobalSession(GlobalSession session) throws TransactionException } @Override - public GlobalSession findGlobalSession(Long transactionId) { + public GlobalSession findGlobalSession(String xid) { return null; } @@ -220,8 +222,8 @@ private static void write(TransactionStoreManager transactionStoreManager) { private static Map readAll(TransactionStoreManager transactionStoreManager) { Map resultMap = new HashMap<>(65535 * 5 * 9); - while (transactionStoreManager.hasRemaining(true)) { - List transactionWriteStores = transactionStoreManager.readWriteStoreFromFile(2000, + while (((ReloadableStore)transactionStoreManager).hasRemaining(true)) { + List transactionWriteStores = ((ReloadableStore)transactionStoreManager).readWriteStore(2000, true); if (null != transactionWriteStores) { for (TransactionWriteStore transactionWriteStore : transactionWriteStores) { @@ -230,8 +232,8 @@ private static Map readAll(TransactionStoreManage } } } - while (transactionStoreManager.hasRemaining(false)) { - List transactionWriteStores = transactionStoreManager.readWriteStoreFromFile(2000, + while (((ReloadableStore)transactionStoreManager).hasRemaining(false)) { + List transactionWriteStores = ((ReloadableStore)transactionStoreManager).readWriteStore(2000, false); if (null != transactionWriteStores) { for (TransactionWriteStore transactionWriteStore : transactionWriteStores) { diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java index d68dcf16bb5..d5a03ece983 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java @@ -31,6 +31,8 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -76,7 +78,7 @@ public static void beforeClass() throws Exception { SessionHolder.init(null); serverMessageSender = new MockServerMessageSender(); defaultCoordinator = new DefaultCoordinator(serverMessageSender); - defaultCoordinator.init(); +// defaultCoordinator.init(); } @ParameterizedTest @@ -105,6 +107,23 @@ public void branchRollback(String xid, Long branchId) { Assertions.assertEquals(result, BranchStatus.PhaseTwo_Rollbacked); } + + @Test + public void test_handleRetryRollbacking() throws TransactionException, InterruptedException { + + String xid = core.begin(applicationId, txServiceGroup, txName, 10); + Long branchId = core.branchRegister(BranchType.AT, "abcd", clientId, xid, applicationData, lockKeys_2); + + Thread.sleep(100); + + defaultCoordinator.timeoutCheck(); + defaultCoordinator.handleRetryRollbacking(); + + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + Assertions.assertNull(globalSession); + + } + @AfterAll public static void afterClass() throws Exception { @@ -164,4 +183,4 @@ public Object sendSyncRequest(String resourceId, String clientId, Object message } } -} +} \ No newline at end of file diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java index 42b33e4ff5a..8569001e89a 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java @@ -23,6 +23,7 @@ import io.seata.core.model.ResourceManagerInbound; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionHelper; import io.seata.server.session.SessionHolder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -84,7 +85,7 @@ public void initSessionManager() throws Exception { public void branchRegisterTest(String xid) throws Exception { core.branchRegister(BranchType.AT, resourceId, clientId, xid, "abc", lockKeys_1); long transactionId = XID.getTransactionId(xid); - GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); Assertions.assertEquals(globalSession.getSortedBranches().size(), 1); //clear @@ -103,7 +104,7 @@ public void branchRegisterTest(String xid) throws Exception { public void branchReportTest(String xid, Long branchId) throws Exception { core.branchReport(BranchType.AT, xid, branchId, BranchStatus.PhaseOne_Done, applicationData); long transactionId = XID.getTransactionId(xid); - GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); BranchSession branchSession = globalSession.getBranch(branchId); Assertions.assertEquals(branchSession.getStatus(), BranchStatus.PhaseOne_Done); @@ -120,8 +121,12 @@ public void branchReportTest(String xid, Long branchId) throws Exception { public void beginTest() throws Exception { String xid = core.begin(applicationId, txServiceGroup, txName, timeout); long transactionId = XID.getTransactionId(xid); - GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); Assertions.assertNotNull(globalSession); + + //clear + globalSession.end(); + } /** @@ -146,8 +151,9 @@ public void commitTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalCommitCommitTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - BranchSession branchSession = new BranchSession(); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, + applicationData, "t1:1", clientId); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseOne_Done)); @@ -168,8 +174,9 @@ public void doGlobalCommitCommitTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalCommitUnretryableTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - BranchSession branchSession = new BranchSession(); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, + applicationData, "t1:1", clientId); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_CommitFailed_Unretryable, BranchStatus.PhaseOne_Done)); @@ -189,8 +196,9 @@ public void doGlobalCommitUnretryableTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalCommitExpTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - BranchSession branchSession = new BranchSession(); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, + applicationData, "t1:1", clientId); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseOne_Timeout, BranchStatus.PhaseOne_Done)); @@ -223,8 +231,9 @@ public void rollBackTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalRollBackRollbackedTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - BranchSession branchSession = new BranchSession(); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, + applicationData, "t1:1", clientId); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_Rollbacked)); @@ -245,8 +254,9 @@ public void doGlobalRollBackRollbackedTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalRollBackUnretryableTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - BranchSession branchSession = new BranchSession(); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, + applicationData, "t1:1", clientId); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_RollbackFailed_Unretryable)); @@ -266,14 +276,16 @@ public void doGlobalRollBackUnretryableTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalRollBackRetryableExpTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); - BranchSession branchSession = new BranchSession(); + GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, + applicationData, "t1:1", clientId); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_RollbackFailed_Retryable)); core.doGlobalRollback(globalSession, false); Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.RollbackRetrying); + //clear globalSession.end(); } diff --git a/server/src/test/java/io/seata/server/lock/LockManagerTest.java b/server/src/test/java/io/seata/server/lock/LockManagerTest.java index 31084b1358a..f420ebe7635 100644 --- a/server/src/test/java/io/seata/server/lock/LockManagerTest.java +++ b/server/src/test/java/io/seata/server/lock/LockManagerTest.java @@ -17,6 +17,7 @@ import io.seata.core.model.BranchType; import io.seata.server.UUIDGenerator; +import io.seata.server.lock.memory.MemoryLockManagerForTest; import io.seata.server.session.BranchSession; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; @@ -42,7 +43,7 @@ public class LockManagerTest { @ParameterizedTest @MethodSource("branchSessionProvider") public void acquireLock_success(BranchSession branchSession) throws Exception { - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); Assertions.assertTrue(lockManager.acquireLock(branchSession)); } @@ -56,7 +57,7 @@ public void acquireLock_success(BranchSession branchSession) throws Exception { @ParameterizedTest @MethodSource("branchSessionsProvider") public void acquireLock_failed(BranchSession branchSession1, BranchSession branchSession2) throws Exception { - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); Assertions.assertTrue(lockManager.acquireLock(branchSession1)); Assertions.assertFalse(lockManager.acquireLock(branchSession2)); } @@ -71,13 +72,13 @@ public void acquireLock_failed(BranchSession branchSession1, BranchSession branc @MethodSource("branchSessionProvider") public void isLockableTest(BranchSession branchSession) throws Exception { branchSession.setLockKey("t:4"); - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); Assertions.assertTrue(lockManager - .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey())); + .isLockable(branchSession.getXid(), branchSession.getResourceId(), branchSession.getLockKey())); lockManager.acquireLock(branchSession); branchSession.setTransactionId(UUIDGenerator.generateUUID()); Assertions.assertFalse(lockManager - .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey())); + .isLockable(branchSession.getXid(), branchSession.getResourceId(), branchSession.getLockKey())); } /** diff --git a/server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java b/server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java new file mode 100644 index 00000000000..f11485d6408 --- /dev/null +++ b/server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java @@ -0,0 +1,301 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock.db; + +import io.seata.core.exception.TransactionException; +import io.seata.core.lock.Locker; +import io.seata.core.store.db.LockStoreDataBaseDAO; +import io.seata.server.lock.DefaultLockManager; +import io.seata.server.lock.LockManager; +import io.seata.server.session.BranchSession; +import org.apache.commons.dbcp.BasicDataSource; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + + + +/** + * @author zhangsen + * @data 2019/4/28 + */ +public class DataBaseLockManagerImplTest { + + static LockManager lockManager = null; + + static BasicDataSource dataSource = null; + + static LockStoreDataBaseDAO dataBaseLockStoreDAO = null; + + @BeforeAll + public static void start(){ + dataSource = new BasicDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUrl("jdbc:h2:./db_store/db_lock"); + dataSource.setUsername("sa"); + dataSource.setPassword(""); + + dataBaseLockStoreDAO = new LockStoreDataBaseDAO(dataSource); + dataBaseLockStoreDAO.setDbType("h2"); + dataBaseLockStoreDAO.setLockTable("lock_table"); + + lockManager = new DBLockManagerForTest(dataBaseLockStoreDAO); + + prepareTable(dataSource); + } + + private static void prepareTable(BasicDataSource dataSource) { + Connection conn = null; + try { + conn = dataSource.getConnection(); + Statement s = conn.createStatement(); + try { + s.execute("drop table lock_table"); + } catch (Exception e) { + } + s.execute("CREATE TABLE lock_table ( xid varchar(96), transaction_id long , branch_id long, resource_id varchar(32) ,table_name varchar(32) ,pk varchar(32) , row_key varchar(128) primary key not null, gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6)) "); + System.out.println("create table lock_table success."); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + + @Test + public void acquireLock() throws TransactionException, SQLException { + BranchSession branchSession = new BranchSession(); + branchSession.setXid("abc-123:786756"); + branchSession.setTransactionId(123543465); + branchSession.setBranchId(5756678); + branchSession.setResourceId("abcss"); + branchSession.setLockKey("t1:13,14;t2:11,12"); + + Assertions.assertTrue(lockManager.acquireLock(branchSession)); + + String sql = "select * from lock_table where xid = 'abc-123:786756'" ; + String sql2 = "select count(*) from lock_table where xid = 'abc-123:786756' " + + "and row_key in ('abcss^^^t1^^^13', 'abcss^^^t1^^^14', 'abcss^^^t2^^^11', 'abcss^^^t2^^^12')" ; + String delSql = "delete from lock_table where xid = 'abc-123:786756'" ; + Connection conn = null; + try { + conn = dataSource.getConnection(); + + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + rs.close(); + + rs = conn.createStatement().executeQuery(sql2); + if(rs.next()){ + Assertions.assertTrue(true); + Assertions.assertEquals(4, rs.getInt(1)); + }else { + Assertions.assertTrue(false); + } + rs.close(); + + conn.createStatement().execute(delSql); + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Test + public void re_acquireLock() throws TransactionException, SQLException { + BranchSession branchSession = new BranchSession(); + branchSession.setXid("abc-123:65867978"); + branchSession.setTransactionId(123543465); + branchSession.setBranchId(5756678); + branchSession.setResourceId("abcss"); + branchSession.setLockKey("t1:53,54;t2:21,32"); + + Assertions.assertTrue(lockManager.acquireLock(branchSession)); + + BranchSession branchSession2 = new BranchSession(); + branchSession2.setXid("abc-123:65867978"); + branchSession2.setTransactionId(123543465); + branchSession2.setBranchId(575667854); + branchSession2.setResourceId("abcss"); + branchSession2.setLockKey("t1:13,14;t2:21,45"); + + Assertions.assertTrue(lockManager.acquireLock(branchSession2)); + + BranchSession branchSession3 = new BranchSession(); + branchSession3.setXid("abc-123:5678789"); + branchSession3.setTransactionId(334123); + branchSession3.setBranchId(5657); + branchSession3.setResourceId("abcss"); + branchSession3.setLockKey("t1:53,14;t2:21,45"); + + Assertions.assertTrue(!lockManager.acquireLock(branchSession3)); + + String delSql = "delete from lock_table where xid in( 'abc-123:65867978' , 'abc-123:65867978' , 'abc-123:5678789' )" ; + Connection conn = null; + try { + conn = dataSource.getConnection(); + + conn.createStatement().execute(delSql); + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + @Test + public void unLock() throws TransactionException, SQLException { + BranchSession branchSession = new BranchSession(); + branchSession.setXid("abc-123:56867"); + branchSession.setTransactionId(1236765); + branchSession.setBranchId(204565); + branchSession.setResourceId("abcss"); + branchSession.setLockKey("t1:3,4;t2:4,5"); + + Assertions.assertTrue(lockManager.acquireLock(branchSession)); + + String sql = "select * from lock_table where xid = 'abc-123:56867'" ; + String sql2 = "select count(*) from lock_table where xid = 'abc-123:56867' " + + "and row_key in ('abcss^^^t1^^^3', 'abcss^^^t1^^^4', 'abcss^^^t2^^^4', 'abcss^^^t2^^^5')" ; + Connection conn = null; + try { + conn = dataSource.getConnection(); + + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else { + Assertions.assertTrue(false); + } + rs.close(); + + rs = conn.createStatement().executeQuery(sql2); + if(rs.next()){ + Assertions.assertTrue(true); + Assertions.assertEquals(4, rs.getInt(1)); + }else { + Assertions.assertTrue(false); + } + rs.close(); + + //un lock + Assertions.assertTrue(lockManager.releaseLock(branchSession)); + + rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(false); + }else { + Assertions.assertTrue(true); + } + rs.close(); + + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + + + + } + + @Test + public void isLockable() throws TransactionException, SQLException { + BranchSession branchSession = new BranchSession(); + branchSession.setXid("abc-123:56877898"); + branchSession.setTransactionId(245686786); + branchSession.setBranchId(467568); + branchSession.setResourceId("abcss"); + branchSession.setLockKey("t1:8,7;t2:1,2"); + + Assertions.assertTrue(lockManager.acquireLock(branchSession)); + + BranchSession branchSession2 = new BranchSession(); + branchSession2.setXid("abc-123:56877898"); + branchSession2.setTransactionId(245686786); + branchSession2.setBranchId(1242354576); + branchSession2.setResourceId("abcss"); + branchSession2.setLockKey("t1:8"); + + Assertions.assertTrue(lockManager.isLockable(branchSession2.getXid(), branchSession2.getResourceId(), branchSession2.getLockKey())); + + BranchSession branchSession3 = new BranchSession(); + branchSession3.setXid("abc-123:4575614354"); + branchSession3.setTransactionId(65867867); + branchSession3.setBranchId(123123); + branchSession3.setResourceId("abcss"); + branchSession3.setLockKey("t2:1,12"); + + Assertions.assertTrue(!lockManager.isLockable(branchSession3.getXid(), branchSession3.getResourceId(), branchSession3.getLockKey())); + + String delSql = "delete from lock_table where xid in( 'abc-123:56877898' , 'abc-123:56877898' , 'abc-123:4575614354' )" ; + Connection conn = null; + try { + conn = dataSource.getConnection(); + + conn.createStatement().execute(delSql); + } finally { + if(conn != null){ + try { + conn.close(); + } catch (SQLException e) { + } + } + } + } + + public static class DBLockManagerForTest extends DefaultLockManager { + + protected LockStoreDataBaseDAO lockStore; + + public DBLockManagerForTest(LockStoreDataBaseDAO db){ + lockStore = db; + } + + @Override + protected Locker getLocker(BranchSession branchSession) { + DataBaseLocker locker = new DataBaseLocker(); + locker.setLockStore(lockStore); + return locker; + } + } +} \ No newline at end of file diff --git a/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java b/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java new file mode 100644 index 00000000000..1bdd7c0c0b7 --- /dev/null +++ b/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock.memory; + +import io.seata.core.lock.Locker; +import io.seata.server.lock.DefaultLockManager; +import io.seata.server.session.BranchSession; + +/** + * @author zhangsen + * @data 2019-05-16 + */ +public class MemoryLockManagerForTest extends DefaultLockManager { + + @Override + protected Locker getLocker(BranchSession branchSession) { + return new MemoryLocker(branchSession); + } +} diff --git a/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java b/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerImplTest.java similarity index 87% rename from server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java rename to server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerImplTest.java index fbe0c216b42..7bf4148174e 100644 --- a/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java +++ b/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerImplTest.java @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.lock; +package io.seata.server.lock.memory; +import io.seata.common.XID; import io.seata.core.model.BranchType; import io.seata.server.UUIDGenerator; +import io.seata.server.lock.LockManager; import io.seata.server.session.BranchSession; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -25,15 +27,16 @@ import java.util.stream.Stream; + /** * The type Default lock manager impl test. * * @author zhimo.xiao @gmail.com * @since 2019 /1/23 */ -public class DefaultLockManagerImplTest { +public class MemoryLockManagerImplTest { - private LockManager lockManager = new DefaultLockManagerImpl(); + private LockManager lockManager = new MemoryLockManagerForTest();; private static final long transactionId = UUIDGenerator.generateUUID(); @@ -50,6 +53,7 @@ public class DefaultLockManagerImplTest { @ParameterizedTest @MethodSource("branchSessionProvider") public void acquireLockTest(BranchSession branchSession) throws Exception { + boolean result = lockManager.acquireLock(branchSession); Assertions.assertTrue(result); branchSession.unlock(); @@ -62,7 +66,8 @@ public void acquireLockTest(BranchSession branchSession) throws Exception { */ @Test public void isLockableTest() throws Exception { - boolean resultOne = lockManager.isLockable(transactionId, resourceId, lockKey); + boolean resultOne = lockManager.isLockable(XID.generateXID(transactionId), resourceId, lockKey); + Assertions.assertTrue(resultOne); } @@ -73,6 +78,7 @@ public void isLockableTest() throws Exception { */ static Stream branchSessionProvider() { BranchSession branchSession = new BranchSession(); + branchSession.setXid(XID.generateXID(transactionId)); branchSession.setBranchId(1L); branchSession.setTransactionId(transactionId); branchSession.setClientId("c1"); diff --git a/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java b/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java index 33544245aa5..69b12a0c247 100644 --- a/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java +++ b/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java @@ -15,6 +15,7 @@ */ package io.seata.server.session; +import io.seata.common.XID; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; @@ -61,7 +62,7 @@ public void addGlobalSessionTest(GlobalSession globalSession) throws Exception { @MethodSource("globalSessionProvider") public void findGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); Assertions.assertNotNull(expected); Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId()); Assertions.assertEquals(expected.getApplicationId(), globalSession.getApplicationId()); @@ -84,7 +85,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex sessionManager.addGlobalSession(globalSession); globalSession.setStatus(GlobalStatus.Finished); sessionManager.updateGlobalSessionStatus(globalSession, GlobalStatus.Finished); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); Assertions.assertNotNull(expected); Assertions.assertEquals(GlobalStatus.Finished, expected.getStatus()); sessionManager.removeGlobalSession(globalSession); @@ -101,7 +102,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex public void removeGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); sessionManager.removeGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); Assertions.assertNull(expected); } @@ -301,6 +302,10 @@ public void onEndTest(GlobalSession globalSession) throws Exception { */ static Stream globalSessionProvider() { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + return Stream.of( Arguments.of(globalSession) ); diff --git a/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java b/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java index 803f1200c47..7c58a309b89 100644 --- a/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java +++ b/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java @@ -15,6 +15,11 @@ */ package io.seata.server.session; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import io.seata.common.XID; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; @@ -24,11 +29,10 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import io.seata.server.session.file.FileBasedSessionManager; import java.util.stream.Stream; + /** * The type File based session manager test. * @@ -72,7 +76,7 @@ public void addGlobalSessionTest(GlobalSession globalSession) throws Exception { @MethodSource("globalSessionProvider") public void findGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); Assertions.assertNotNull(expected); Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId()); Assertions.assertEquals(expected.getApplicationId(), globalSession.getApplicationId()); @@ -95,7 +99,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex sessionManager.addGlobalSession(globalSession); globalSession.setStatus(GlobalStatus.Finished); sessionManager.updateGlobalSessionStatus(globalSession, GlobalStatus.Finished); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); Assertions.assertNotNull(expected); Assertions.assertEquals(GlobalStatus.Finished, expected.getStatus()); sessionManager.removeGlobalSession(globalSession); @@ -112,7 +116,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex public void removeGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); sessionManager.removeGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); Assertions.assertNull(expected); } @@ -312,6 +316,10 @@ public void onEndTest(GlobalSession globalSession) throws Exception { */ static Stream globalSessionProvider() { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + return Stream.of( Arguments.of(globalSession) ); @@ -337,6 +345,7 @@ static Stream globalSessionsProvider() { */ static Stream branchSessionProvider() { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + globalSession.setXid(XID.generateXID(globalSession.getTransactionId())); BranchSession branchSession = new BranchSession(); branchSession.setTransactionId(globalSession.getTransactionId()); branchSession.setBranchId(1L); diff --git a/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java b/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java new file mode 100644 index 00000000000..14b04c30b20 --- /dev/null +++ b/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java @@ -0,0 +1,565 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.session.db; + +import io.seata.common.XID; +import io.seata.core.exception.TransactionException; +import io.seata.core.model.BranchStatus; +import io.seata.core.model.BranchType; +import io.seata.core.model.GlobalStatus; +import io.seata.core.store.db.LogStoreDataBaseDAO; +import io.seata.server.UUIDGenerator; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionCondition; +import io.seata.server.session.SessionManager; +import io.seata.server.store.db.DatabaseTransactionStoreManager; +import org.apache.commons.dbcp.BasicDataSource; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; + +/** + * The type Data base session manager test. + * + * @author zhangsen + * @data 2019 /4/28 + */ +public class DataBaseSessionManagerTest { + + static SessionManager sessionManager = null; + + static LogStoreDataBaseDAO logStoreDataBaseDAO = null; + + static BasicDataSource dataSource = null; + + @BeforeAll + public static void start() throws Exception { + DataBaseSessionManager tempSessionManager = new DataBaseSessionManager(); + DatabaseTransactionStoreManager transactionStoreManager = new DatabaseTransactionStoreManager(); + + dataSource = new BasicDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUrl("jdbc:h2:./db_store/db_session"); + dataSource.setUsername("sa"); + dataSource.setPassword(""); + + logStoreDataBaseDAO = new LogStoreDataBaseDAO(dataSource); + logStoreDataBaseDAO.setDbType("h2"); + logStoreDataBaseDAO.setGlobalTable("global_table"); + logStoreDataBaseDAO.setBrachTable("branch_table"); + + transactionStoreManager.setLogQueryLimit(100); + transactionStoreManager.setLogStore(logStoreDataBaseDAO); + + tempSessionManager.setTransactionStoreManager(transactionStoreManager); + sessionManager = tempSessionManager; + + prepareTable(dataSource); + } + + private static void prepareTable(BasicDataSource dataSource) { + Connection conn = null; + try { + conn = dataSource.getConnection(); + Statement s = conn.createStatement(); + try { + s.execute("drop table global_table"); + } catch (Exception e) { + } + s.execute("CREATE TABLE global_table ( xid varchar(96), transaction_id long , STATUS int, application_id varchar(32), transaction_service_group varchar(32) ,transaction_name varchar(32) ,timeout int, begin_time long, application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); + System.out.println("create table global_table success."); + + try { + s.execute("drop table branch_table"); + } catch (Exception e) { + } + s.execute("CREATE TABLE branch_table ( xid varchar(96), transaction_id long , branch_id long, resource_group_id varchar(32), resource_id varchar(32) ,lock_key varchar(64) ,branch_type varchar(32) , status int , client_id varchar(128), application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); + System.out.println("create table branch_table success."); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + + + @Test + public void test_addGlobalSession() throws TransactionException, SQLException { + GlobalSession session = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(session.getTransactionId()); + session.setXid(xid); + session.setTransactionId(146757978); + session.setBeginTime(System.currentTimeMillis()); + session.setApplicationData("abc=878s"); + session.setStatus(GlobalStatus.Begin); + + sessionManager.addGlobalSession(session); + + String sql = "select * from global_table where xid= '"+xid+"'"; + String delSql = "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else{ + Assertions.assertTrue(false); + } + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + + @Test + public void test_updateGlobalSessionStatus() throws TransactionException, SQLException { + GlobalSession session = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(session.getTransactionId()); + session.setXid(xid); + session.setTransactionId(146757978); + session.setBeginTime(System.currentTimeMillis()); + session.setApplicationData("abc=878s"); + session.setStatus(GlobalStatus.Begin); + + sessionManager.addGlobalSession(session); + + session.setStatus(GlobalStatus.Committing); + sessionManager.updateGlobalSessionStatus(session, GlobalStatus.Committing); + + String sql = "select * from global_table where xid= '"+xid+"'"; + String delSql = "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + Assertions.assertEquals(rs.getInt("status"), GlobalStatus.Committing.getCode()); + }else{ + Assertions.assertTrue(false); + } + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void test_removeGlobalSession() throws Exception { + GlobalSession session = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(session.getTransactionId()); + session.setXid(xid); + session.setTransactionId(146757978); + session.setBeginTime(System.currentTimeMillis()); + session.setApplicationData("abc=878s"); + session.setStatus(GlobalStatus.Begin); + + sessionManager.addGlobalSession(session); + + String sql = "select * from global_table where xid= '"+xid+"'"; + String delSql = "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else{ + Assertions.assertTrue(false); + } + rs.close(); + + //delete + sessionManager.removeGlobalSession(session); + + rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(false); + }else{ + Assertions.assertTrue(true); + } + rs.close(); + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void test_findGlobalSession() throws Exception { + GlobalSession session = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(session.getTransactionId()); + session.setXid(xid); + session.setTransactionId(146757978); + session.setBeginTime(System.currentTimeMillis()); + session.setApplicationData("abc=878s"); + session.setStatus(GlobalStatus.Begin); + + sessionManager.addGlobalSession(session); + + GlobalSession globalSession_db = sessionManager.findGlobalSession(session.getXid()); + Assertions.assertNotNull(globalSession_db); + + Assertions.assertEquals(globalSession_db.getTransactionId(), session.getTransactionId()); + Assertions.assertEquals(globalSession_db.getXid(), session.getXid()); + Assertions.assertEquals(globalSession_db.getApplicationData(), session.getApplicationData()); + Assertions.assertEquals(globalSession_db.getApplicationId(), session.getApplicationId()); + Assertions.assertEquals(globalSession_db.getTransactionName(), session.getTransactionName()); + Assertions.assertEquals(globalSession_db.getTransactionServiceGroup(), session.getTransactionServiceGroup()); + Assertions.assertEquals(globalSession_db.getBeginTime(), session.getBeginTime()); + Assertions.assertEquals(globalSession_db.getTimeout(), session.getTimeout()); + Assertions.assertEquals(globalSession_db.getStatus(), session.getStatus()); + + String delSql = "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + + @Test + public void test_addBranchSession() throws Exception { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.Begin); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setApplicationData("{\"data\":\"test\"}"); + + sessionManager.addBranchSession(globalSession, branchSession); + + String sql = "select * from branch_table where xid= '"+xid+"'"; + String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + }else{ + Assertions.assertTrue(false); + } + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + + @Test + public void test_updateBranchSessionStatus() throws Exception { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.Begin); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setApplicationData("{\"data\":\"test\"}"); + branchSession.setStatus(BranchStatus.PhaseOne_Done); + + sessionManager.addBranchSession(globalSession, branchSession); + + branchSession.setStatus(BranchStatus.PhaseOne_Timeout); + sessionManager.updateBranchSessionStatus(branchSession, BranchStatus.PhaseOne_Timeout); + + String sql = "select * from branch_table where xid= '"+xid+"'"; + String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(true); + Assertions.assertEquals(rs.getInt("status"), BranchStatus.PhaseOne_Timeout.getCode()); + }else{ + Assertions.assertTrue(false); + } + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void test_removeBranchSession() throws Exception { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.Begin); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setApplicationData("{\"data\":\"test\"}"); + branchSession.setStatus(BranchStatus.PhaseOne_Done); + + sessionManager.addBranchSession(globalSession, branchSession); + + sessionManager.removeBranchSession(globalSession, branchSession); + + String sql = "select * from branch_table where xid= '"+xid+"'"; + String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + ResultSet rs = conn.createStatement().executeQuery(sql); + if(rs.next()){ + Assertions.assertTrue(false); + }else{ + Assertions.assertTrue(true); + } + + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + + @Test + public void test_allSessions() throws Exception { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.Begin); + + sessionManager.addGlobalSession(globalSession); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setClientId("abc-123"); + branchSession.setApplicationData("{\"data\":\"test\"}"); + branchSession.setStatus(BranchStatus.PhaseOne_Done); + + sessionManager.addBranchSession(globalSession, branchSession); + + + BranchSession branchSession2 = new BranchSession(); + branchSession2.setBranchId(UUIDGenerator.generateUUID()); + branchSession2.setXid(xid); + branchSession2.setTransactionId(globalSession.getTransactionId()); + branchSession2.setBranchId(2L); + branchSession2.setResourceGroupId("my_test_tx_group"); + branchSession2.setResourceId("tb_1"); + branchSession2.setLockKey("t_1"); + branchSession2.setBranchType(BranchType.TCC); + branchSession2.setClientId("abc-123"); + branchSession2.setApplicationData("{\"data\":\"test\"}"); + branchSession2.setStatus(BranchStatus.PhaseOne_Done); + + sessionManager.addBranchSession(globalSession, branchSession2); + + Collection rets = sessionManager.allSessions(); + Assertions.assertNotNull(rets); + Assertions.assertEquals(1, rets.size()); + + GlobalSession globalSession_db = (io.seata.server.session.GlobalSession) new ArrayList(rets).get(0); + + Assertions.assertNotNull(globalSession_db.getReverseSortedBranches()); + Assertions.assertEquals(2, globalSession_db.getReverseSortedBranches().size()); + + Assertions.assertNotNull(globalSession_db.getBranch(1L)); + Assertions.assertNotNull(globalSession_db.getBranch(2L)); + + String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + conn.createStatement().execute(delSql); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + @Test + public void test_findGlobalSessions() throws TransactionException, SQLException { + String xid = null; + { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.Begin); + + sessionManager.addGlobalSession(globalSession); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setClientId("abc-123"); + branchSession.setApplicationData("{\"data\":\"test\"}"); + branchSession.setStatus(BranchStatus.PhaseOne_Done); + sessionManager.addBranchSession(globalSession, branchSession); + } + String xid2 = null; + { + GlobalSession globalSession = GlobalSession.createGlobalSession("test", + "test", "test123", 100); + xid2 = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.setTransactionId(146757978); + globalSession.setBeginTime(System.currentTimeMillis()); + globalSession.setApplicationData("abc=878s"); + globalSession.setStatus(GlobalStatus.CommitRetrying); + + sessionManager.addGlobalSession(globalSession); + + BranchSession branchSession = new BranchSession(); + branchSession.setBranchId(UUIDGenerator.generateUUID()); + branchSession.setXid(xid2); + branchSession.setTransactionId(globalSession.getTransactionId()); + branchSession.setBranchId(1L); + branchSession.setResourceGroupId("my_test_tx_group"); + branchSession.setResourceId("tb_1"); + branchSession.setLockKey("t_1"); + branchSession.setBranchType(BranchType.AT); + branchSession.setClientId("abc-123"); + branchSession.setApplicationData("{\"data\":\"test\"}"); + branchSession.setStatus(BranchStatus.PhaseOne_Done); + sessionManager.addBranchSession(globalSession, branchSession); + } + + + Collection rets = sessionManager.findGlobalSessions(new SessionCondition( GlobalStatus.Begin)); + Assertions.assertNotNull(rets); + Assertions.assertEquals(1, rets.size()); + + GlobalSession globalSession_db = (io.seata.server.session.GlobalSession) new ArrayList(rets).get(0); + + Assertions.assertNotNull(globalSession_db.getReverseSortedBranches()); + Assertions.assertEquals(1, globalSession_db.getReverseSortedBranches().size()); + + Assertions.assertNotNull(globalSession_db.getBranch(1L)); + + String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; + String delSql2 = "delete from branch_table where xid= '"+xid2+"'" + ";" + "delete from global_table where xid= '"+xid2+"'"; + Connection conn = null; + try{ + conn = dataSource.getConnection(); + conn.createStatement().execute(delSql); + conn.createStatement().execute(delSql2); + }finally { + if(conn != null){ + conn.close(); + } + } + } + + + + +} \ No newline at end of file diff --git a/server/src/test/java/io/seata/server/store/SessionStoreTest.java b/server/src/test/java/io/seata/server/store/SessionStoreTest.java index 45048d7f63d..37fecd0d6c4 100644 --- a/server/src/test/java/io/seata/server/store/SessionStoreTest.java +++ b/server/src/test/java/io/seata/server/store/SessionStoreTest.java @@ -15,6 +15,9 @@ */ package io.seata.server.store; +import java.io.File; + +import io.seata.common.XID; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; @@ -22,7 +25,7 @@ import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; import io.seata.server.lock.LockManager; -import io.seata.server.lock.LockManagerFactory; +import io.seata.server.lock.memory.MemoryLockManagerForTest; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionHelper; @@ -31,7 +34,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.File; /** * The type Session store test. @@ -63,7 +65,8 @@ public void clean() throws Exception { if (rootDataFileHis.exists()) { rootDataFileHis.delete(); } - LockManagerFactory.get().cleanAllLocks(); + LockManager lockManager = new MemoryLockManagerForTest(); + lockManager.cleanAllLocks(); } /** @@ -75,43 +78,48 @@ public void clean() throws Exception { public void testRestoredFromFile() throws Exception { SessionHolder.init("file"); GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID, "ta:1,2;tb:3", "xxx"); + branchSession1.setXid(xid); branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2")); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3")); + String otherXID = XID.generateXID(0L); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:4")); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:5")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:2")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:3")); + + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:4")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:5")); lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:2")); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:3")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:2")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:3")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); + GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); Assertions.assertNotNull(reloadSession); Assertions.assertFalse(globalSession == reloadSession); Assertions.assertEquals(globalSession.getApplicationId(), reloadSession.getApplicationId()); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2")); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3")); - Assertions.assertTrue(lockManager.isLockable(globalSession.getTransactionId(), RESOURCE_ID, "tb:3")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:2")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:3")); + Assertions.assertTrue(lockManager.isLockable(xid, RESOURCE_ID, "tb:3")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -145,6 +153,9 @@ public void testRestoredFromFileAsyncCommitting() throws Exception { SessionHolder.init("file"); GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -153,29 +164,31 @@ public void testRestoredFromFileAsyncCommitting() throws Exception { Assertions.assertTrue(branchSession1.lock()); globalSession.addBranch(branchSession1); - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); + + String otherXID = XID.generateXID(0L); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.AsyncCommitting); lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); + GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.AsyncCommitting); GlobalSession sessionInAsyncCommittingQueue = SessionHolder.getAsyncCommittingSessionManager() - .findGlobalSession(tid); + .findGlobalSession(globalSession.getXid()); Assertions.assertTrue(reloadSession == sessionInAsyncCommittingQueue); // No locking for session in AsyncCommitting status - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -192,6 +205,9 @@ public void testRestoredFromFileCommitRetry() throws Exception { SessionHolder.init("file"); GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -200,9 +216,11 @@ public void testRestoredFromFileCommitRetry() throws Exception { branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); + + String otherXID = XID.generateXID(0L); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.Committing); globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Retryable); @@ -210,23 +228,23 @@ public void testRestoredFromFileCommitRetry() throws Exception { lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); + GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.CommitRetrying); GlobalSession sessionInRetryCommittingQueue = SessionHolder.getRetryCommittingSessionManager() - .findGlobalSession(tid); + .findGlobalSession(globalSession.getXid()); Assertions.assertTrue(reloadSession == sessionInRetryCommittingQueue); BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId()); Assertions.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_CommitFailed_Retryable); // Lock is held by session in CommitRetrying status - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -244,6 +262,9 @@ public void testRestoredFromFileRollbackRetry() throws Exception { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -252,9 +273,11 @@ public void testRestoredFromFileRollbackRetry() throws Exception { branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + String otherXID = XID.generateXID(0L); + + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.Rollbacking); globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_RollbackFailed_Retryable); @@ -262,23 +285,23 @@ public void testRestoredFromFileRollbackRetry() throws Exception { lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); + GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.RollbackRetrying); GlobalSession sessionInRetryRollbackingQueue = SessionHolder.getRetryRollbackingSessionManager() - .findGlobalSession(tid); + .findGlobalSession(globalSession.getXid()); Assertions.assertTrue(reloadSession == sessionInRetryRollbackingQueue); BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId()); Assertions.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_RollbackFailed_Retryable); // Lock is held by session in RollbackRetrying status - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -296,6 +319,9 @@ public void testRestoredFromFileRollbackFailed() throws Exception { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); + String xid = XID.generateXID(globalSession.getTransactionId()); + globalSession.setXid(xid); + globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -304,26 +330,28 @@ public void testRestoredFromFileRollbackFailed() throws Exception { branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = LockManagerFactory.get(); + LockManager lockManager = new MemoryLockManagerForTest(); + + String otherXID = XID.generateXID(0L); - Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.Rollbacking); globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Unretryable); SessionHelper.endRollbackFailed(globalSession); // Lock is released. - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); + GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); Assertions.assertNull(reloadSession); } } diff --git a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java b/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java index dddd5e83c29..0fe6860eb5a 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java @@ -17,9 +17,6 @@ import io.seata.common.util.StringUtils; -import java.util.HashMap; -import java.util.Map; - /** * the TCC method result * diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java b/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java index a4cda53d59a..2ff32ca4980 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java @@ -17,8 +17,6 @@ import io.seata.common.exception.FrameworkException; -import java.lang.reflect.InvocationTargetException; - /** * extract remoting bean info * diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java index d07050c5f34..c4764df599c 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java @@ -20,7 +20,6 @@ import io.seata.rm.tcc.api.LocalTCC; import io.seata.rm.tcc.remoting.Protocols; import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.rm.tcc.remoting.RemotingDesc; import java.util.Set; diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java index ff1cc8349cf..8af247f16f1 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java @@ -19,8 +19,6 @@ import io.seata.common.util.ReflectionUtil; import io.seata.rm.tcc.remoting.Protocols; import io.seata.rm.tcc.remoting.RemotingDesc; -import io.seata.rm.tcc.remoting.Protocols; -import io.seata.rm.tcc.remoting.RemotingDesc; /** * sofa-rpc remoting bean parsing diff --git a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java b/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java index dc5682b9b10..9f3a192b98f 100644 --- a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java +++ b/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java @@ -20,9 +20,6 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import io.seata.core.protocol.ResultCode; -import io.seata.core.protocol.transaction.BranchRegisterRequest; -import io.seata.core.protocol.transaction.BranchRegisterResponse; import io.seata.server.UUIDGenerator; import io.seata.server.coordinator.DefaultCoordinator; diff --git a/test/src/test/resources/file.conf b/test/src/test/resources/file.conf index 30801f29901..65573b25b31 100644 --- a/test/src/test/resources/file.conf +++ b/test/src/test/resources/file.conf @@ -70,3 +70,7 @@ client { } report.retry.count = 5 } + +transaction { + undo.data.validation = true +} \ No newline at end of file diff --git a/test/src/test/resources/registry.conf b/test/src/test/resources/registry.conf index 1cddea72194..5115876d916 100644 --- a/test/src/test/resources/registry.conf +++ b/test/src/test/resources/registry.conf @@ -45,7 +45,7 @@ registry { } config { - # file、nacos 、apollo、zk、consul + # file、nacos 、apollo、zk、consul、etcd3 type = "file" nacos { @@ -65,7 +65,10 @@ config { session.timeout = 6000 connect.timeout = 2000 } + etcd3 { + serverAddr = "http://localhost:2379" + } file { name = "file.conf" } -} +} \ No newline at end of file diff --git a/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java b/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java index f4deba4aaf0..9833634c61f 100644 --- a/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java +++ b/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java @@ -17,16 +17,10 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.core.exception.TransactionException; -import io.seata.core.exception.TransactionExceptionCode; -import io.seata.core.model.GlobalStatus; import io.seata.core.model.TransactionManager; -import io.seata.core.protocol.transaction.*; -import io.seata.core.rpc.netty.TmRpcClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.TimeoutException; /** * The type Default transaction manager. diff --git a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java index 2736c79d282..78e85d66e75 100644 --- a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java +++ b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java @@ -20,7 +20,6 @@ import io.seata.core.exception.TransactionException; import io.seata.core.model.GlobalStatus; import io.seata.core.model.TransactionManager; -import io.seata.tm.DefaultTransactionManager; import io.seata.tm.TransactionManagerHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From dc088cb9551d58acdf343f66166985e8fa8712fd Mon Sep 17 00:00:00 2001 From: jimin Date: Mon, 27 May 2019 10:27:47 +0800 Subject: [PATCH 2/5] Revert "Release 0.6.0 (#1106)" (#1107) --- .gitignore | 3 +- README.md | 2 +- all/pom.xml | 30 +- bom/pom.xml | 27 +- .../main/java/io/seata/common/Constants.java | 11 - .../common/loader/EnhancedServiceLoader.java | 80 +-- .../io/seata/common/loader/LoadLevel.java | 2 +- .../java/io/seata/common/util/BlobUtils.java | 46 +- .../io/seata/common/util/CollectionUtils.java | 44 -- .../io/seata/common/util/DurationUtil.java | 74 -- .../io/seata/common/util/StringUtils.java | 118 ++-- .../io/seata/common/util/BlobUtilsTest.java | 35 +- .../io/seata/common/util/StringUtilsTest.java | 56 +- config/pom.xml | 1 - config/seata-config-all/pom.xml | 5 - .../seata/config/AbstractConfiguration.java | 21 - .../main/java/io/seata/config/ConfigType.java | 6 +- .../java/io/seata/config/Configuration.java | 28 - .../io/seata/config/ConfigurationFactory.java | 22 +- .../src/main/resources/file.conf | 6 +- .../src/main/resources/registry.conf | 5 +- config/seata-config-etcd3/pom.xml | 49 -- .../seata/config/etcd/EtcdConfiguration.java | 318 --------- .../etcd/EtcdConfigurationProvider.java | 32 - .../io.seata.config.ConfigurationProvider | 1 - core/pom.xml | 11 - .../core/constants/ConfigurationKeys.java | 107 --- .../java/io/seata/core/constants/DBType.java | 93 --- .../exception/AbstractExceptionHandler.java | 7 - .../io/seata/core/lock/AbstractLocker.java | 85 --- .../io/seata/core/lock/LocalDBLocker.java | 42 -- .../java/io/seata/core/lock/LockMode.java | 37 - .../main/java/io/seata/core/lock/Locker.java | 59 -- .../main/java/io/seata/core/lock/RowLock.java | 193 ----- .../seata/core/protocol/AbstractMessage.java | 3 +- .../java/io/seata/core/protocol/Version.java | 2 +- .../io/seata/core/rpc/ChannelManager.java | 1 + .../java/io/seata/core/rpc/RpcContext.java | 1 + .../core/rpc/netty/AbstractRpcRemoting.java | 5 + .../core/rpc/netty/NettyClientConfig.java | 2 + .../core/rpc/netty/NettyPoolableFactory.java | 1 + .../rpc/netty/RegisterCheckAuthHandler.java | 2 + .../core/rpc/netty/RegisterMsgListener.java | 2 + .../seata/core/store/BranchTransactionDO.java | 277 -------- .../seata/core/store/GlobalTransactionDO.java | 256 ------- .../main/java/io/seata/core/store/LockDO.java | 178 ----- .../java/io/seata/core/store/LockStore.java | 68 -- .../java/io/seata/core/store/LogStore.java | 110 --- .../store/db/AbstractDataSourceGenerator.java | 148 ---- .../core/store/db/DataSourceGenerator.java | 35 - .../core/store/db/LockStoreDataBaseDAO.java | 356 ---------- .../io/seata/core/store/db/LockStoreSqls.java | 143 ---- .../core/store/db/LogStoreDataBaseDAO.java | 533 -------------- .../io/seata/core/store/db/LogStoreSqls.java | 323 --------- .../services/io.seata.core.store.LockStore | 1 - .../services/io.seata.core.store.LogStore | 1 - .../core/protocol/RegisterTMRequestTest.java | 192 ----- .../store/db/DataBaseLockStoreDAOTest.java | 300 -------- .../store/db/LogStoreDataBaseDAOTest.java | 659 ------------------ .../config/ConfigurationFactoryTest.java | 32 - .../eureka/EurekaRegistryProvider.java | 1 + .../registry/nacos/NacosRegistryProvider.java | 1 + .../registry/redis/RedisRegistryProvider.java | 2 + .../redis/RedisRegistryServiceImpl.java | 1 + pom.xml | 4 +- rm-datasource/pom.xml | 11 - .../AbstractPreparedStatementProxy.java | 1 + .../io/seata/rm/datasource/AsyncWorker.java | 4 +- .../rm/datasource/PreparedStatementProxy.java | 2 + .../seata/rm/datasource/StatementProxy.java | 2 + .../rm/datasource/exec/DeleteExecutor.java | 2 + .../rm/datasource/sql/WhereRecognizer.java | 1 + .../datasource/undo/AbstractUndoExecutor.java | 162 +---- .../rm/datasource/undo/UndoLogManager.java | 15 +- .../undo/AbstractUndoExecutorTest.java | 316 --------- .../rm/datasource/undo/UndoExecutorTest.java | 40 +- .../datasource/undo/UndoLogManagerTest.java | 16 +- .../keyword/MySQLKeywordCheckerTest.java | 1 + server/pom.xml | 18 - .../server/AbstractTCInboundHandler.java | 7 +- .../src/main/java/io/seata/server/Server.java | 2 +- .../coordinator/DefaultCoordinator.java | 215 ++---- .../seata/server/coordinator/DefaultCore.java | 39 +- .../server/lock/AbstractLockManager.java | 117 ---- .../seata/server/lock/DefaultLockManager.java | 103 --- .../server/lock/DefaultLockManagerImpl.java | 186 +++++ .../io/seata/server/lock/LockManager.java | 23 +- .../LockManagerFactory.java} | 36 +- .../io/seata/server/lock/LockerFactory.java | 99 --- .../seata/server/lock/db/DataBaseLocker.java | 101 --- .../server/lock/memory/MemoryLocker.java | 193 ----- .../session/AbstractSessionManager.java | 64 +- .../seata/server/session/BranchSession.java | 84 +-- .../server/session/DefaultSessionManager.java | 59 +- .../{file => }/FileBasedSessionManager.java | 82 +-- .../seata/server/session/GlobalSession.java | 120 +--- .../server/session/SessionCondition.java | 82 +-- .../seata/server/session/SessionHelper.java | 1 - .../seata/server/session/SessionHolder.java | 35 +- .../seata/server/session/SessionManager.java | 5 +- .../session/db/DataBaseSessionManager.java | 186 ----- .../AbstractTransactionStoreManager.java | 44 -- .../FileTransactionStoreManager.java | 60 +- .../server/store/TransactionStoreManager.java | 26 +- .../db/DatabaseTransactionStoreManager.java | 299 -------- .../store/db/DbcpDataSourceGenerator.java | 54 -- .../store/db/DruidDataSourceGenerator.java | 54 -- .../services/io.seata.core.lock.Locker | 2 - ...io.seata.core.store.db.DataSourceGenerator | 2 - .../io.seata.server.session.SessionManager | 3 - ...seata.server.store.TransactionStoreManager | 2 - server/src/main/resources/db_store.sql | 52 -- server/src/main/resources/file.conf | 47 +- server/src/main/resources/logback.xml | 2 +- server/src/main/resources/nacos-config.txt | 24 +- server/src/main/resources/registry.conf | 5 +- .../test/java/WriteStoreMultithreadTest.java | 5 +- server/src/test/java/WriteStoreTest.java | 14 +- .../coordinator/DefaultCoordinatorTest.java | 23 +- .../server/coordinator/DefaultCoreTest.java | 42 +- ...t.java => DefaultLockManagerImplTest.java} | 14 +- .../io/seata/server/lock/LockManagerTest.java | 11 +- .../lock/db/DataBaseLockManagerImplTest.java | 301 -------- .../lock/memory/MemoryLockManagerForTest.java | 32 - .../session/DefaultSessionManagerTest.java | 11 +- .../session/FileBasedSessionManagerTest.java | 21 +- .../db/DataBaseSessionManagerTest.java | 565 --------------- .../seata/server/store/SessionStoreTest.java | 108 ++- .../java/io/seata/rm/tcc/TwoPhaseResult.java | 3 + .../seata/rm/tcc/remoting/RemotingParser.java | 2 + .../parser/LocalTCCRemotingParser.java | 1 + .../parser/SofaRpcRemotingParser.java | 2 + .../seata/core/rpc/netty/TmRpcClientTest.java | 3 + test/src/test/resources/file.conf | 4 - test/src/test/resources/registry.conf | 7 +- .../io/seata/tm/TransactionManagerHolder.java | 6 + .../tm/api/DefaultGlobalTransaction.java | 1 + 137 files changed, 845 insertions(+), 8733 deletions(-) delete mode 100644 common/src/main/java/io/seata/common/util/DurationUtil.java delete mode 100644 config/seata-config-etcd3/pom.xml delete mode 100644 config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java delete mode 100644 config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java delete mode 100644 config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider delete mode 100644 core/src/main/java/io/seata/core/constants/DBType.java delete mode 100644 core/src/main/java/io/seata/core/lock/AbstractLocker.java delete mode 100644 core/src/main/java/io/seata/core/lock/LocalDBLocker.java delete mode 100644 core/src/main/java/io/seata/core/lock/LockMode.java delete mode 100644 core/src/main/java/io/seata/core/lock/Locker.java delete mode 100644 core/src/main/java/io/seata/core/lock/RowLock.java delete mode 100644 core/src/main/java/io/seata/core/store/BranchTransactionDO.java delete mode 100644 core/src/main/java/io/seata/core/store/GlobalTransactionDO.java delete mode 100644 core/src/main/java/io/seata/core/store/LockDO.java delete mode 100644 core/src/main/java/io/seata/core/store/LockStore.java delete mode 100644 core/src/main/java/io/seata/core/store/LogStore.java delete mode 100644 core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java delete mode 100644 core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java delete mode 100644 core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java delete mode 100644 core/src/main/java/io/seata/core/store/db/LockStoreSqls.java delete mode 100644 core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java delete mode 100644 core/src/main/java/io/seata/core/store/db/LogStoreSqls.java delete mode 100644 core/src/main/resources/META-INF/services/io.seata.core.store.LockStore delete mode 100644 core/src/main/resources/META-INF/services/io.seata.core.store.LogStore delete mode 100644 core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java delete mode 100644 core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java delete mode 100644 core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java delete mode 100644 discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java delete mode 100644 rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java delete mode 100644 server/src/main/java/io/seata/server/lock/AbstractLockManager.java delete mode 100644 server/src/main/java/io/seata/server/lock/DefaultLockManager.java create mode 100644 server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java rename server/src/main/java/io/seata/server/{store/ReloadableStore.java => lock/LockManagerFactory.java} (54%) delete mode 100644 server/src/main/java/io/seata/server/lock/LockerFactory.java delete mode 100644 server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java delete mode 100644 server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java rename server/src/main/java/io/seata/server/session/{file => }/FileBasedSessionManager.java (71%) delete mode 100644 server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java delete mode 100644 server/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java rename server/src/main/java/io/seata/server/store/{file => }/FileTransactionStoreManager.java (92%) delete mode 100644 server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java delete mode 100644 server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java delete mode 100644 server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java delete mode 100644 server/src/main/resources/META-INF/services/io.seata.core.lock.Locker delete mode 100644 server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator delete mode 100644 server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager delete mode 100644 server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager delete mode 100644 server/src/main/resources/db_store.sql rename server/src/test/java/io/seata/server/lock/{memory/MemoryLockManagerImplTest.java => DefaultLockManagerImplTest.java} (87%) delete mode 100644 server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java delete mode 100644 server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java delete mode 100644 server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java diff --git a/.gitignore b/.gitignore index 44b06f93f74..e34b7b267cd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ target/ *.tar.gz *.class .flattened-pom.xml -dependency-reduced-pom.xml # eclipse ignore .settings/ @@ -37,4 +36,4 @@ dependency-reduced-pom.xml # system ignore .DS_Store Thumbs.db -*.orig +*.orig \ No newline at end of file diff --git a/README.md b/README.md index 766f5739690..a4676b789b6 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ For more details about principle and design, please go to [Seata wiki page](http ## Maven dependency ```xml -0.5.2 +0.5.1 io.seata diff --git a/all/pom.xml b/all/pom.xml index e05b28dcc51..8f092f4971d 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -21,7 +21,7 @@ io.seata seata-all - 0.6.0 + 0.5.2 Seata All-in-one ${project.version} http://seata.io @@ -112,11 +112,6 @@ seata-config-consul ${project.version} - - io.seata - seata-config-etcd3 - ${project.version} - io.seata seata-core @@ -428,7 +423,7 @@ true false false - true + false io.seata:seata-common @@ -438,7 +433,6 @@ io.seata:seata-config-nacos io.seata:seata-config-zk io.seata:seata-config-consul - io.seata:seata-config-etcd3 io.seata:seata-discovery-core io.seata:seata-discovery-consul io.seata:seata-discovery-eureka @@ -479,12 +473,6 @@ registry.conf - - *:* - - META-INF/maven/** - - @@ -509,12 +497,20 @@ maven-javadoc-plugin 2.10.4 - ${project.build.sourceEncoding} - false + ${project.build.sourceEncoding} + true + true + false + true + true + true + + io.seata:seata-* + - package + attach-javadocs jar diff --git a/bom/pom.xml b/bom/pom.xml index 76b370961a0..dc5ca5ed57d 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -20,7 +20,7 @@ io.seata seata-bom - 0.6.0 + 0.5.2 4.0.0 pom @@ -30,28 +30,29 @@ 4.3.23.RELEASE 4.1.24.Final + 4.12 2.7.0 2.6.5 5.5.3 - 1.2.58 + 1.2.48 1.2.1 1.7.22 1.2.0 2.6 2.4.2 1.6 - 1.3 3.1 1.0 0.10 2.9.1 1.0.2 + 6.4 0.8.3 1.1.0 2.9.0 1.9.5 1.4.2 - 1.0.0 + 0.9.1 0.3.0 1.11.2 27.0.1-jre @@ -62,9 +63,6 @@ 4.4.11 1.1.12 2.7.0 - 10.2.0.3.0 - 5.1.30 - 1.4.181 @@ -272,21 +270,6 @@ caffeine ${caffeine.version} - - commons-dbcp - commons-dbcp - ${commons-dbcp.version} - - - com.h2database - h2 - ${h2.version} - - - mysql - mysql-connector-java - ${mysql.client.version} - diff --git a/common/src/main/java/io/seata/common/Constants.java b/common/src/main/java/io/seata/common/Constants.java index e39d856f5b9..a76bacb155d 100644 --- a/common/src/main/java/io/seata/common/Constants.java +++ b/common/src/main/java/io/seata/common/Constants.java @@ -15,8 +15,6 @@ */ package io.seata.common; -import java.nio.charset.Charset; - /** * The type Constants. * @@ -99,13 +97,4 @@ public class Constants { */ public final static String TCC_ACTION_CONTEXT = "actionContext"; - /** - * default charset name - */ - public static final String DEFAULT_CHARSET_NAME = "UTF-8"; - - /** - * default charset is utf-8 - */ - public static final Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_CHARSET_NAME); } diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index 4c80b9c59f3..d10d95999bc 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -18,8 +18,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -29,7 +27,6 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import io.seata.common.Constants; import io.seata.common.executor.Initialize; import io.seata.common.util.CollectionUtils; @@ -105,48 +102,12 @@ public static S load(Class service, String activateName, ClassLoader load return loadFile(service, activateName, loader); } - /** - * Load s. - * - * @param the type parameter - * @param service the service - * @param activateName the activate name - * @param args the args - * @return the s - * @throws EnhancedServiceNotFoundException the enhanced service not found exception - */ - public static S load(Class service, String activateName, Object[] args) throws EnhancedServiceNotFoundException { - Class[] argsType = null; - if(args != null && args.length > 0){ - argsType = new Class[args.length]; - for(int i = 0; i < args.length; i ++){ - argsType[i] = args[i].getClass(); - } - } - return loadFile(service, activateName, findClassLoader(), argsType, args); - } - - /** - * Load s. - * - * @param the type parameter - * @param service the service - * @param activateName the activate name - * @param argsType the args type - * @param args the args - * @return the s - * @throws EnhancedServiceNotFoundException the enhanced service not found exception - */ - public static S load(Class service, String activateName, Class[] argsType, Object[] args) throws EnhancedServiceNotFoundException { - return loadFile(service, activateName, findClassLoader(), argsType, args); - } - /** * get all implements * * @param the type parameter * @param service the service - * @return list list + * @return list */ public static List loadAll(Class service) { List allInstances = new ArrayList<>(); @@ -156,7 +117,7 @@ public static List loadAll(Class service) { } try { for (Class clazz : allClazzs) { - allInstances.add(initInstance(service, clazz, null, null)); + allInstances.add(initInstance(service, clazz)); } } catch (Throwable t) { throw new EnhancedServiceNotFoundException(t); @@ -189,12 +150,8 @@ public static List getAllExtensionClass(Class service, ClassLoader return findAllExtensionClass(service, null, loader); } + @SuppressWarnings("rawtypes") private static S loadFile(Class service, String activateName, ClassLoader loader) { - return loadFile(service, activateName, loader, null, null); - } - - @SuppressWarnings("rawtypes") - private static S loadFile(Class service, String activateName, ClassLoader loader, Class[] argTypes, Object[] args) { try { boolean foundFromCache = true; List extensions = providers.get(service); @@ -216,7 +173,7 @@ private static S loadFile(Class service, String activateName, ClassLoader Class clz = extensions.get(i); @SuppressWarnings("unchecked") LoadLevel activate = (LoadLevel)clz.getAnnotation(LoadLevel.class); - if (activate != null && activateName.equalsIgnoreCase(activate.name())) { + if (activate != null && activateName.equals(activate.name())) { activateExtensions.add(clz); } } @@ -230,7 +187,7 @@ private static S loadFile(Class service, String activateName, ClassLoader + "] and classloader : " + ObjectUtils.toString(loader)); } Class extension = extensions.get(extensions.size() - 1); - S result = initInstance(service, extension, argTypes, args); + S result = initInstance(service, extension); if (!foundFromCache && LOGGER.isInfoEnabled()) { LOGGER.info("load " + service.getSimpleName() + "[" + activateName + "] extension by class[" + extension .getName() + "]"); @@ -302,7 +259,7 @@ private static void loadFile(Class service, String dir, ClassLoader classLoad java.net.URL url = urls.nextElement(); BufferedReader reader = null; try { - reader = new BufferedReader(new InputStreamReader(url.openStream(), Constants.DEFAULT_CHARSET)); + reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8")); String line = null; while ((line = reader.readLine()) != null) { final int ci = line.indexOf('#'); @@ -335,26 +292,13 @@ private static void loadFile(Class service, String dir, ClassLoader classLoad * @param the type parameter * @param service the service * @param implClazz the impl clazz - * @param argTypes the arg types - * @param args the args - * @return s s - * @throws IllegalAccessException the illegal access exception - * @throws InstantiationException the instantiation exception - * @throws NoSuchMethodException the no such method exception - * @throws InvocationTargetException the invocation target exception + * @return s + * @throws IllegalAccessException the illegal access exception + * @throws InstantiationException the instantiation exception */ - protected static S initInstance(Class service, Class implClazz, Class[] argTypes, Object[] args) - throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { - S s = null; - if(argTypes != null && args != null){ - // Constructor with arguments - Constructor constructor = implClazz.getDeclaredConstructor(argTypes); - constructor.setAccessible(true); - s = service.cast(constructor.newInstance(args)); - }else { - // default Constructor - s = service.cast(implClazz.newInstance()); - } + protected static S initInstance(Class service, Class implClazz) + throws IllegalAccessException, InstantiationException { + S s = service.cast(implClazz.newInstance()); if (s instanceof Initialize) { ((Initialize)s).init(); } diff --git a/common/src/main/java/io/seata/common/loader/LoadLevel.java b/common/src/main/java/io/seata/common/loader/LoadLevel.java index b887ed509b0..b01ebf76c74 100644 --- a/common/src/main/java/io/seata/common/loader/LoadLevel.java +++ b/common/src/main/java/io/seata/common/loader/LoadLevel.java @@ -43,5 +43,5 @@ * * @return the int */ - int order() default 0; + int order(); } diff --git a/common/src/main/java/io/seata/common/util/BlobUtils.java b/common/src/main/java/io/seata/common/util/BlobUtils.java index 60ddc7eaabc..3eb62aa0c28 100644 --- a/common/src/main/java/io/seata/common/util/BlobUtils.java +++ b/common/src/main/java/io/seata/common/util/BlobUtils.java @@ -15,18 +15,19 @@ */ package io.seata.common.util; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.sql.Blob; import javax.sql.rowset.serial.SerialBlob; -import io.seata.common.Constants; +import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.exception.ShouldNeverHappenException; /** * The type Blob utils. * * @author jimin.jm @alibaba-inc.com - * @author Geng Zhang */ public class BlobUtils { @@ -46,7 +47,7 @@ public static Blob string2blob(String str) { } try { - return new SerialBlob(str.getBytes(Constants.DEFAULT_CHARSET)); + return new SerialBlob(str.getBytes()); } catch (Exception e) { throw new ShouldNeverHappenException(e); } @@ -64,43 +65,26 @@ public static String blob2string(Blob blob) { } try { - return new String(blob.getBytes((long) 1, (int) blob.length()), Constants.DEFAULT_CHARSET); - } catch (Exception e) { - throw new ShouldNeverHappenException(e); - } - } - - /** - * Byte array to blob - * - * @param bytes the byte array - * @return the blob - */ - public static Blob bytes2Blob(byte[] bytes) { - if (bytes == null) { - return null; - } - - try { - return new SerialBlob(bytes); + return new String(blob.getBytes((long)1, (int)blob.length())); } catch (Exception e) { throw new ShouldNeverHappenException(e); } } /** - * Blob to byte array. + * Input stream 2 string string. * - * @param blob the blob - * @return the byte array + * @param is the is + * @return the string */ - public static byte[] blob2Bytes(Blob blob) { - if (blob == null) { - return null; - } - + public static String inputStream2String(InputStream is) { try { - return blob.getBytes((long) 1, (int) blob.length()); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int i = -1; + while ((i = is.read()) != -1) { + baos.write(i); + } + return baos.toString(); } catch (Exception e) { throw new ShouldNeverHappenException(e); } diff --git a/common/src/main/java/io/seata/common/util/CollectionUtils.java b/common/src/main/java/io/seata/common/util/CollectionUtils.java index d56b80eb1ec..76126fc4cf4 100644 --- a/common/src/main/java/io/seata/common/util/CollectionUtils.java +++ b/common/src/main/java/io/seata/common/util/CollectionUtils.java @@ -16,7 +16,6 @@ package io.seata.common.util; import java.util.Collection; -import java.util.Iterator; /** * The type Collection utils. @@ -46,49 +45,6 @@ public static boolean isNotEmpty(Collection col){ return col != null && col.size() > 0; } - /** - * Is empty boolean. - * - * @param array the array - * @return the boolean - */ - public static boolean isEmpty(Object[] array){ - return !isNotEmpty(array); - } - - /** - * Is not empty boolean. - * - * @param array the array - * @return the boolean - */ - public static boolean isNotEmpty(Object[] array){ - return array != null && array.length > 0; - } - - /** - * To string string. - * - * @param col the col - * @return the string - */ - public static String toString(Collection col){ - if(isEmpty(col)){ - return ""; - } - StringBuffer sb = new StringBuffer(); - sb.append("["); - Iterator it = col.iterator(); - while (it.hasNext()){ - Object obj = it.next(); - sb.append(StringUtils.toString(obj)); - sb.append(","); - } - sb.deleteCharAt(sb.length() - 1); - sb.append("]"); - return sb.toString(); - } - /** * Is size equals boolean. * diff --git a/common/src/main/java/io/seata/common/util/DurationUtil.java b/common/src/main/java/io/seata/common/util/DurationUtil.java deleted file mode 100644 index 567fc85e3f5..00000000000 --- a/common/src/main/java/io/seata/common/util/DurationUtil.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.common.util; - -import java.time.Duration; - -/** - * @author XCXCXCXCX - */ -public class DurationUtil { - - public static final Duration DEFAULT_DURATION = Duration.ofMillis(-1); - - public static final String DAY_UNIT = "d"; - public static final String HOUR_UNIT = "h"; - public static final String MINIUTE_UNIT = "m"; - public static final String SECOND_UNIT = "s"; - public static final String MILLIS_SECOND_UNIT = "ms"; - - public static Duration parse(String str) { - if(StringUtils.isBlank(str)){ - return DEFAULT_DURATION; - } - - if (str.contains(MILLIS_SECOND_UNIT)) { - Long value = doParse(MILLIS_SECOND_UNIT, str); - return value == null ? null : Duration.ofMillis(value); - } else if (str.contains(DAY_UNIT)) { - Long value = doParse(DAY_UNIT, str); - return value == null ? null : Duration.ofDays(value); - } else if (str.contains(HOUR_UNIT)) { - Long value = doParse(HOUR_UNIT, str); - return value == null ? null : Duration.ofHours(value); - } else if (str.contains(MINIUTE_UNIT)) { - Long value = doParse(MINIUTE_UNIT, str); - return value == null ? null : Duration.ofMinutes(value); - } else if (str.contains(SECOND_UNIT)) { - Long value = doParse(SECOND_UNIT, str); - return value == null ? null : Duration.ofSeconds(value); - } - try { - int millis = Integer.parseInt(str); - return Duration.ofMillis(millis); - }catch (Exception e){ - throw new UnsupportedOperationException(str + " can't parse to duration", e); - } - } - - private static Long doParse(String unit, String str) { - str = str.replace(unit, ""); - if ("".equals(str)) { - return null; - } - try { - return Long.parseLong(str); - } catch (NumberFormatException e) { - throw new UnsupportedOperationException("\"" + str + "\" can't parse to Duration", e); - } - } - -} diff --git a/common/src/main/java/io/seata/common/util/StringUtils.java b/common/src/main/java/io/seata/common/util/StringUtils.java index e6a1714e78b..217538aae17 100644 --- a/common/src/main/java/io/seata/common/util/StringUtils.java +++ b/common/src/main/java/io/seata/common/util/StringUtils.java @@ -15,17 +15,19 @@ */ package io.seata.common.util; -import io.seata.common.Constants; -import io.seata.common.exception.ShouldNeverHappenException; - import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; +import java.sql.Blob; +import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.Map; +import javax.sql.rowset.serial.SerialBlob; + /** * The type String utils. * @@ -35,6 +37,7 @@ public class StringUtils { private StringUtils() { + } /** @@ -51,7 +54,7 @@ public static boolean isNullOrEmpty(String str) { * Is blank string ? * * @param str the str - * @return boolean boolean + * @return boolean */ public static boolean isBlank(String str) { int length; @@ -71,7 +74,7 @@ public static boolean isBlank(String str) { * Is Not blank string ? * * @param str the str - * @return boolean boolean + * @return boolean */ public static boolean isNotBlank(String str) { int length; @@ -88,83 +91,56 @@ public static boolean isNotBlank(String str) { return false; } - /** - * Equals boolean. - * - * @param a the a - * @param b the b - * @return boolean - */ - public static boolean equals(String a, String b) { - if (a == null) { - return b == null; - } - return a.equals(b); - } - /** - * Equals ignore case boolean. + * String 2 blob blob. * - * @param a the a - * @param b the b - * @return the boolean + * @param str the str + * @return the blob + * @throws SQLException the sql exception */ - public static boolean equalsIgnoreCase(String a, String b) { - if (a == null) { - return b == null; + public static Blob string2blob(String str) throws SQLException { + if (str == null) { + return null; } - return a.equalsIgnoreCase(b); + return new SerialBlob(str.getBytes()); } /** - * Input stream 2 string string. + * Blob 2 string string. * - * @param is the is + * @param blob the blob * @return the string + * @throws SQLException the sql exception */ - public static String inputStream2String(InputStream is) { - if (is == null) { + public static String blob2string(Blob blob) throws SQLException { + if (blob == null) { return null; } - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int i = -1; - while ((i = is.read()) != -1) { - baos.write(i); - } - return baos.toString(Constants.DEFAULT_CHARSET_NAME); - } catch (Exception e) { - throw new ShouldNeverHappenException(e); - } + + return new String(blob.getBytes((long)1, (int)blob.length())); } /** - * Input stream to byte array + * Input stream 2 string string. * * @param is the is - * @return the byte array + * @return the string + * @throws IOException the io exception */ - public static byte[] inputStream2Bytes(InputStream is) { - if (is == null) { - return null; - } - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int i = -1; - while ((i = is.read()) != -1) { - baos.write(i); - } - return baos.toByteArray(); - } catch (Exception e) { - throw new ShouldNeverHappenException(e); + public static String inputStream2String(InputStream is) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int i = -1; + while ((i = is.read()) != -1) { + baos.write(i); } + return baos.toString(); } /** * Object.toString() * * @param obj the obj - * @return string string + * @return string */ public static String toString(Object obj){ if (obj == null){ @@ -221,4 +197,32 @@ public static String toString(Object obj){ } return sb.toString(); } + + /** + * Equals boolean. + * + * @param a the a + * @param b the b + * @return boolean + */ + public static boolean equals(String a, String b) { + if (a == null) { + return b == null; + } + return a.equals(b); + } + + /** + * Equals ignore case boolean. + * + * @param a the a + * @param b the b + * @return the boolean + */ + public static boolean equalsIgnoreCase(String a, String b) { + if (a == null) { + return b == null; + } + return a.equalsIgnoreCase(b); + } } diff --git a/common/src/test/java/io/seata/common/util/BlobUtilsTest.java b/common/src/test/java/io/seata/common/util/BlobUtilsTest.java index f643ad49caa..53a0a6217ae 100644 --- a/common/src/test/java/io/seata/common/util/BlobUtilsTest.java +++ b/common/src/test/java/io/seata/common/util/BlobUtilsTest.java @@ -15,22 +15,21 @@ */ package io.seata.common.util; -import java.io.UnsupportedEncodingException; +import java.io.InputStream; +import java.nio.charset.Charset; import java.sql.SQLException; import javax.sql.rowset.serial.SerialBlob; -import io.seata.common.Constants; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertNull; /** * The type Blob utils test. * * @author Otis.z - * @author Geng Zhang * @date 2019 /2/26 */ public class BlobUtilsTest { @@ -42,9 +41,8 @@ public class BlobUtilsTest { */ @Test public void testString2blob() throws SQLException { - assertNull(BlobUtils.string2blob(null)); assertThat(BlobUtils.string2blob("123abc")).isEqualTo( - new SerialBlob("123abc".getBytes(Constants.DEFAULT_CHARSET))); + new SerialBlob("123abc".getBytes(Charset.forName("UTF-8")))); } /** @@ -54,24 +52,19 @@ public void testString2blob() throws SQLException { */ @Test public void testBlob2string() throws SQLException { - assertNull(BlobUtils.blob2string(null)); - assertThat(BlobUtils.blob2string(new SerialBlob("123absent".getBytes(Constants.DEFAULT_CHARSET)))).isEqualTo( + assertThat(BlobUtils.blob2string(new SerialBlob("123absent".getBytes(Charset.forName("UTF-8"))))).isEqualTo( "123absent"); } + /** + * Test input stream 2 string. + */ @Test - void bytes2Blob() throws UnsupportedEncodingException, SQLException { - assertNull(BlobUtils.bytes2Blob(null)); - byte[] bs = "xxa哈哈dd".getBytes(Constants.DEFAULT_CHARSET_NAME); - assertThat(BlobUtils.bytes2Blob(bs)).isEqualTo( - new SerialBlob(bs)); - } - - @Test - void blob2Bytes() throws UnsupportedEncodingException, SQLException { - assertNull(BlobUtils.blob2Bytes(null)); - byte[] bs = "xxa哈哈dd".getBytes(Constants.DEFAULT_CHARSET_NAME); - assertThat(BlobUtils.blob2Bytes(new SerialBlob(bs))).isEqualTo( - bs); + @Disabled + public void testInputStream2String() { + InputStream inputStream = BlobUtilsTest.class.getClassLoader().getResourceAsStream("test.txt"); + assertThat(BlobUtils.inputStream2String(inputStream)).isEqualTo("abc\n" + + ":\"klsdf\n" + + "2ks,x:\".,-3sd˚ø≤ø¬≥"); } } diff --git a/common/src/test/java/io/seata/common/util/StringUtilsTest.java b/common/src/test/java/io/seata/common/util/StringUtilsTest.java index c816c0358cb..1eae80462bf 100644 --- a/common/src/test/java/io/seata/common/util/StringUtilsTest.java +++ b/common/src/test/java/io/seata/common/util/StringUtilsTest.java @@ -15,15 +15,17 @@ */ package io.seata.common.util; -import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; +import java.sql.SQLException; + +import javax.sql.rowset.serial.SerialBlob; -import io.seata.common.Constants; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertNull; /** * The type String utils test. @@ -46,25 +48,43 @@ public void testIsNullOrEmpty() { assertThat(StringUtils.isNullOrEmpty(" ")).isFalse(); } + /** + * Test string 2 blob. + * + * @throws SQLException the sql exception + */ @Test - public void testInputStream2String() throws IOException { - assertNull(StringUtils.inputStream2String(null)); - String data = "abc\n" - + ":\"klsdf\n" - + "2ks,x:\".,-3sd˚ø≤ø¬≥"; - ByteArrayInputStream inputStream = new ByteArrayInputStream(data.getBytes(Constants.DEFAULT_CHARSET)); - assertThat(StringUtils.inputStream2String(inputStream)).isEqualTo(data); + public void testString2blob() throws SQLException { + assertThat(StringUtils.string2blob(null)).isNull(); + String[] strs = new String[] {"abc", "", " "}; + for (String str : strs) { + assertThat(StringUtils.string2blob(str)).isEqualTo(new SerialBlob(str.getBytes())); + } } + /** + * Test blob 2 string. + * + * @throws SQLException the sql exception + */ @Test - void inputStream2Bytes() { - assertNull(StringUtils.inputStream2Bytes(null)); - String data = "abc\n" - + ":\"klsdf\n" - + "2ks,x:\".,-3sd˚ø≤ø¬≥"; - byte[] bs = data.getBytes(Constants.DEFAULT_CHARSET); - ByteArrayInputStream inputStream = new ByteArrayInputStream(data.getBytes(Constants.DEFAULT_CHARSET)); - assertThat(StringUtils.inputStream2Bytes(inputStream)).isEqualTo(bs); + public void testBlob2string() throws SQLException { + String[] strs = new String[] {"abc", " "}; + for (String str : strs) { + assertThat(StringUtils.blob2string(new SerialBlob(str.getBytes()))).isEqualTo(str); + + } + } + + /** + * Test input stream 2 string. + */ + @Test + @Disabled + public void testInputStream2String() throws IOException { + InputStream inputStream = StringUtilsTest.class.getClassLoader().getResourceAsStream("test.txt"); + assertThat(StringUtils.inputStream2String(inputStream)) + .isEqualTo("abc\n" + ":\"klsdf\n" + "2ks,x:\".,-3sd˚ø≤ø¬≥"); } @Test diff --git a/config/pom.xml b/config/pom.xml index 36b384ebda6..cfdf735708d 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -32,7 +32,6 @@ seata-config-nacos seata-config-zk seata-config-all - seata-config-etcd3 seata-config-consul diff --git a/config/seata-config-all/pom.xml b/config/seata-config-all/pom.xml index 46da42a13db..3cf62928e1b 100644 --- a/config/seata-config-all/pom.xml +++ b/config/seata-config-all/pom.xml @@ -41,11 +41,6 @@ seata-config-nacos ${project.version} - - ${project.groupId} - seata-config-etcd3 - ${project.version} - ${project.groupId} seata-config-consul diff --git a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java index 0092f4f36ac..7cd509eccdd 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java @@ -15,11 +15,6 @@ */ package io.seata.config; - -import io.seata.common.util.DurationUtil; - -import java.time.Duration; - /** * The type Abstract configuration. * @@ -66,22 +61,6 @@ public long getLong(String dataId) { return getLong(dataId, 0L); } - @Override - public Duration getDuration(String dataId) { - return getDuration(dataId, Duration.ZERO); - } - - @Override - public Duration getDuration(String dataId, Duration defaultValue) { - return getDuration(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); - } - - @Override - public Duration getDuration(String dataId, Duration defaultValue, long timeoutMills) { - String result = getConfig(dataId, String.valueOf(defaultValue.toMillis() + "ms"), timeoutMills); - return DurationUtil.parse(result); - } - @Override public boolean getBoolean(String dataId, boolean defaultValue, long timeoutMills) { String result = getConfig(dataId, String.valueOf(defaultValue), timeoutMills); diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java index 6f8cf55a4ed..866fddb8d67 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java @@ -41,11 +41,7 @@ public enum ConfigType { /** * Consul config type */ - Consul, - /** - * Etcd3 config type - */ - Etcd3; + Consul; /** * Gets type. diff --git a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java index 67ec8679191..bb3e1a7c18c 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java @@ -15,7 +15,6 @@ */ package io.seata.config; -import java.time.Duration; import java.util.List; /** @@ -81,33 +80,6 @@ public interface Configuration { */ long getLong(String dataId); - /** - * Gets duration. - * - * @param dataId - * @return the duration - */ - Duration getDuration(String dataId); - - /** - * Gets duration. - * - * @param dataId - * @param defaultValue - * @return the duration - */ - Duration getDuration(String dataId, Duration defaultValue); - - /** - * Gets duration. - * - * @param dataId - * @param defaultValue - * @param timeoutMills - * @return he duration - */ - Duration getDuration(String dataId, Duration defaultValue, long timeoutMills); - /** * Gets boolean. * diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java index cd5ea345d5c..0b802b3d344 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java @@ -17,6 +17,8 @@ import io.seata.common.exception.NotSupportYetException; import io.seata.common.loader.EnhancedServiceLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Objects; @@ -24,9 +26,10 @@ * The type Configuration factory. * * @author jimin.jm @alibaba-inc.com - * @author Geng Zhang + * @date 2018 /12/24 */ public final class ConfigurationFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationFactory.class); private static final String REGISTRY_CONF = "registry.conf"; /** * The constant FILE_INSTANCE. @@ -35,33 +38,20 @@ public final class ConfigurationFactory { private static final String NAME_KEY = "name"; private static final String FILE_TYPE = "file"; - private static volatile Configuration CONFIG_INSTANCE = null; - /** * Gets instance. * * @return the instance */ public static Configuration getInstance() { - if (CONFIG_INSTANCE == null) { - synchronized (Configuration.class) { - if (CONFIG_INSTANCE == null) { - CONFIG_INSTANCE = buildConfiguration(); - } - } - } - return CONFIG_INSTANCE; - } - - private static Configuration buildConfiguration() { ConfigType configType = null; String configTypeName = null; try { configTypeName = FILE_INSTANCE.getConfig(ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + ConfigurationKeys.FILE_ROOT_TYPE); configType = ConfigType.getType(configTypeName); - } catch (Exception e) { - throw new NotSupportYetException("not support register type: " + configTypeName, e); + } catch (Exception exx) { + throw new NotSupportYetException("not support register type: " + configTypeName); } if (ConfigType.File == configType) { String pathDataId = ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR diff --git a/config/seata-config-core/src/main/resources/file.conf b/config/seata-config-core/src/main/resources/file.conf index a166f8d5c5c..dc09514d367 100644 --- a/config/seata-config-core/src/main/resources/file.conf +++ b/config/seata-config-core/src/main/resources/file.conf @@ -69,8 +69,4 @@ client { retry.times = 30 } report.retry.count = 5 -} - -transaction { - undo.data.validation = true -} +} \ No newline at end of file diff --git a/config/seata-config-core/src/main/resources/registry.conf b/config/seata-config-core/src/main/resources/registry.conf index 5115876d916..1d6c3598256 100644 --- a/config/seata-config-core/src/main/resources/registry.conf +++ b/config/seata-config-core/src/main/resources/registry.conf @@ -45,7 +45,7 @@ registry { } config { - # file、nacos 、apollo、zk、consul、etcd3 + # file、nacos 、apollo、zk、consul type = "file" nacos { @@ -65,9 +65,6 @@ config { session.timeout = 6000 connect.timeout = 2000 } - etcd3 { - serverAddr = "http://localhost:2379" - } file { name = "file.conf" } diff --git a/config/seata-config-etcd3/pom.xml b/config/seata-config-etcd3/pom.xml deleted file mode 100644 index beb590dfffe..00000000000 --- a/config/seata-config-etcd3/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - io.seata - seata-config - ${revision} - - 4.0.0 - seata-config-etcd3 - seata-config-etcd3 ${project.version} - - - - io.seata - seata-config-core - ${project.parent.version} - - - io.etcd - jetcd-core - - - com.google.guava - guava - - - - - com.google.guava - guava - - - diff --git a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java deleted file mode 100644 index 6eed7d53035..00000000000 --- a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfiguration.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.config.etcd; - -import io.etcd.jetcd.ByteSequence; -import io.etcd.jetcd.Client; -import io.etcd.jetcd.KeyValue; -import io.etcd.jetcd.Watch; -import io.etcd.jetcd.kv.DeleteResponse; -import io.etcd.jetcd.kv.GetResponse; -import io.etcd.jetcd.kv.PutResponse; -import io.etcd.jetcd.kv.TxnResponse; -import io.etcd.jetcd.op.Cmp; -import io.etcd.jetcd.op.CmpTarget; -import io.etcd.jetcd.op.Op; -import io.etcd.jetcd.options.PutOption; -import io.etcd.jetcd.watch.WatchResponse; -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.CollectionUtils; -import io.seata.config.AbstractConfiguration; -import io.seata.config.ConfigChangeListener; -import io.seata.config.ConfigFuture; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static io.netty.util.CharsetUtil.UTF_8; -import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; -import static io.seata.config.ConfigurationKeys.FILE_ROOT_CONFIG; - -/** - * @author xingfudeshi@gmail.com - * @date 2019/05/10 - */ -public class EtcdConfiguration extends AbstractConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(EtcdConfiguration.class); - private static volatile EtcdConfiguration instance; - private static volatile Client client; - - private static final Configuration FILE_CONFIG = ConfigurationFactory.FILE_INSTANCE; - private static final String SERVER_ADDR_KEY = "serverAddr"; - private static final String CONFIG_TYPE = "etcd3"; - private static final String FILE_CONFIG_KEY_PREFIX = FILE_ROOT_CONFIG + FILE_CONFIG_SPLIT_CHAR + CONFIG_TYPE + FILE_CONFIG_SPLIT_CHAR; - private static final int THREAD_POOL_NUM = 1; - private static final int MAP_INITIAL_CAPACITY = 8; - private static ExecutorService etcdConfigExecutor = null; - private static ExecutorService etcdNotifierExecutor = null; - private static ConcurrentMap> configListenersMap = null; - private static ConcurrentHashMap> configChangeNotifiersMap = null; - - private static final long VERSION_NOT_EXIST = 0; - - private EtcdConfiguration() { - } - - /** - * get instance - * - * @return - */ - public static EtcdConfiguration getInstance() { - if (null == instance) { - synchronized (EtcdConfiguration.class) { - if (null == instance) { - etcdConfigExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM, - Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("etcd-config-executor", THREAD_POOL_NUM)); - etcdNotifierExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM, - Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("etcd-config-notifier-executor", THREAD_POOL_NUM)); - configListenersMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); - configChangeNotifiersMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); - instance = new EtcdConfiguration(); - } - } - } - return instance; - } - - - @Override - public String getTypeName() { - return CONFIG_TYPE; - } - - @Override - public String getConfig(String dataId, String defaultValue, long timeoutMills) { - ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigFuture.ConfigOperation.GET, timeoutMills); - etcdConfigExecutor.execute(() -> { - complete(getClient().getKVClient().get(ByteSequence.from(dataId, UTF_8)), configFuture); - }); - return (String) configFuture.get(); - } - - @Override - public boolean putConfig(String dataId, String content, long timeoutMills) { - ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigFuture.ConfigOperation.PUT, timeoutMills); - etcdConfigExecutor.execute(() -> { - complete(getClient().getKVClient().put(ByteSequence.from(dataId, UTF_8), ByteSequence.from(content, UTF_8)), configFuture); - }); - return (Boolean) configFuture.get(); - } - - @Override - public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) { - ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigFuture.ConfigOperation.PUTIFABSENT, timeoutMills); - etcdConfigExecutor.execute(() -> { - //use etcd transaction to ensure the atomic operation - complete(client.getKVClient().txn() - //whether the key exists - .If(new Cmp(ByteSequence.from(dataId, UTF_8), Cmp.Op.EQUAL, CmpTarget.version(VERSION_NOT_EXIST))) - //not exist,then will create - .Then(Op.put(ByteSequence.from(dataId, UTF_8), ByteSequence.from(content, UTF_8), PutOption.DEFAULT)) - .commit(), configFuture); - }); - return (Boolean) configFuture.get(); - } - - @Override - public boolean removeConfig(String dataId, long timeoutMills) { - ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigFuture.ConfigOperation.REMOVE, timeoutMills); - etcdConfigExecutor.execute(() -> { - complete(getClient().getKVClient().delete(ByteSequence.from(dataId, UTF_8)), configFuture); - }); - return (Boolean) configFuture.get(); - } - - @Override - public void addConfigListener(String dataId, ConfigChangeListener listener) { - configListenersMap.putIfAbsent(dataId, new ArrayList<>()); - configChangeNotifiersMap.putIfAbsent(dataId, new ArrayList<>()); - ConfigChangeNotifier configChangeNotifier = new ConfigChangeNotifier(dataId, listener); - configChangeNotifiersMap.get(dataId).add(configChangeNotifier); - if (null != listener.getExecutor()) { - listener.getExecutor().submit(configChangeNotifier); - } else { - etcdNotifierExecutor.submit(configChangeNotifier); - } - } - - @Override - public void removeConfigListener(String dataId, ConfigChangeListener listener) { - List configChangeListeners = getConfigListeners(dataId); - if (configChangeListeners == null) { - return; - } - List newChangeListenerList = new ArrayList<>(); - for (ConfigChangeListener changeListener : configChangeListeners) { - if (!changeListener.equals(listener)) { - newChangeListenerList.add(changeListener); - } - } - configListenersMap.put(dataId, newChangeListenerList); - if (null != listener.getExecutor()) { - listener.getExecutor().shutdownNow(); - } - //remove and stop the configChangeNotifier - List configChangeNotifiers = configChangeNotifiersMap.get(dataId); - List newConfigChangeNotifiers = new ArrayList<>(); - for (ConfigChangeNotifier configChangeNotifier : configChangeNotifiers) { - if (!listener.equals(configChangeNotifier.getListener())) { - newConfigChangeNotifiers.add(configChangeNotifier); - } else { - configChangeNotifier.stop(); - } - } - configChangeNotifiersMap.put(dataId, newConfigChangeNotifiers); - } - - @Override - public List getConfigListeners(String dataId) { - return configListenersMap.get(dataId); - } - - /** - * get client - * - * @return client - */ - private static Client getClient() { - if (null == client) { - synchronized (EtcdConfiguration.class) { - if (null == client) { - client = Client.builder().endpoints(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)).build(); - } - } - } - return client; - } - - /** - * complete the future - * - * @param completableFuture - * @param configFuture - * @param - */ - private void complete(CompletableFuture completableFuture, ConfigFuture configFuture) { - try { - T response = completableFuture.get(); - if (response instanceof GetResponse) { - List keyValues = ((GetResponse) response).getKvs(); - if (CollectionUtils.isNotEmpty(keyValues)) { - ByteSequence value = keyValues.get(0).getValue(); - if (null != value) { - configFuture.setResult(value.toString(UTF_8)); - } - } - } else if (response instanceof PutResponse) { - configFuture.setResult(Boolean.TRUE); - } else if (response instanceof TxnResponse) { - boolean result = ((TxnResponse) response).isSucceeded(); - //create key if file does not exist) - if (result) { - configFuture.setResult(Boolean.TRUE); - } - } else if (response instanceof DeleteResponse) { - configFuture.setResult(Boolean.TRUE); - } else { - throw new ShouldNeverHappenException("unsupported response type"); - } - } catch (Exception e) { - LOGGER.error("error occurred while completing the future{}", e.getMessage()); - } - } - - /** - * the type config change notifier - */ - private static class ConfigChangeNotifier implements Runnable { - private final String dataId; - private final ConfigChangeListener listener; - private Watch.Watcher watcher; - - ConfigChangeNotifier(String dataId, ConfigChangeListener listener) { - this.dataId = dataId; - this.listener = listener; - } - - /** - * get the listener - * - * @return ConfigChangeListener - */ - ConfigChangeListener getListener() { - return this.listener; - } - - @Override - public void run() { - Watch watchClient = getClient().getWatchClient(); - watcher = watchClient.watch(ByteSequence.from(dataId, UTF_8), new Watch.Listener() { - @Override - public void onNext(WatchResponse response) { - notifyListeners(); - } - - @Override - public void onError(Throwable throwable) { - - } - - @Override - public void onCompleted() { - - } - }); - } - - /** - * notify listeners - */ - private void notifyListeners() { - try { - GetResponse getResponse = getClient().getKVClient().get(ByteSequence.from(dataId, UTF_8)).get(); - List keyValues = getResponse.getKvs(); - if (CollectionUtils.isNotEmpty(keyValues)) { - for (ConfigChangeListener listener : configListenersMap.get(this.dataId)) { - listener.receiveConfigInfo(keyValues.get(0).getValue().toString(UTF_8)); - } - } - } catch (Exception e) { - LOGGER.error("error occurred while getting value{}", e.getMessage()); - } - } - - - /** - * stop the notifier - */ - public void stop() { - this.watcher.close(); - } - } -} diff --git a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java deleted file mode 100644 index acb7e28db96..00000000000 --- a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd/EtcdConfigurationProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.config.etcd; - -import io.seata.common.loader.LoadLevel; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationProvider; - -/** - * @author xingfudeshi@gmail.com - * @date 2019/04/12 - */ -@LoadLevel(name = "Etcd3", order = 1) -public class EtcdConfigurationProvider implements ConfigurationProvider { - @Override - public Configuration provide() { - return EtcdConfiguration.getInstance(); - } -} diff --git a/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index ce01ac19760..00000000000 --- a/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.etcd.EtcdConfigurationProvider \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml index 9670f9fd495..a6a71f8e60d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -55,17 +55,6 @@ commons-pool commons-pool - - commons-dbcp - commons-dbcp - test - - - com.h2database - h2 - test - - diff --git a/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java b/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java index dc6f93fef8c..4df7b3f11c6 100644 --- a/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java +++ b/core/src/main/java/io/seata/core/constants/ConfigurationKeys.java @@ -92,111 +92,4 @@ public class ConfigurationKeys { * The constant CLIENT_REPORT_RETRY_COUNT. */ public static final String CLIENT_REPORT_RETRY_COUNT = CLIENT_PREFIX + "report.retry.count"; - - /** - * The constant STORE_DB_GLOBAL_TABLE. - */ - public static final String STORE_DB_GLOBAL_TABLE = "store.db.global.table"; - - /** - * The constant STORE_DB_BRANCH_TABLE. - */ - public static final String STORE_DB_BRANCH_TABLE = "store.db.branch.table"; - - /** - * The constant STORE_DB_GLOBAL_DEFAULT_TABLE. - */ - public static final String STORE_DB_GLOBAL_DEFAULT_TABLE = "global_table"; - - /** - * The constant STORE_DB_BRANCH_DEFAULT_TABLE. - */ - public static final String STORE_DB_BRANCH_DEFAULT_TABLE = "branch_table"; - - /** - * The constant STORE_DB_DATASOURCE_TYPE. - */ - public static final String STORE_DB_DATASOURCE_TYPE = "store.db.datasource"; - - - /** - * The constant STORE_DB_TYPE. - */ - public static final String STORE_DB_TYPE = "store.db.db-type"; - - /** - * The constant STORE_DB_URL. - */ - public static final String STORE_DB_URL = "store.db.url"; - - /** - * The constant STORE_DB_USER. - */ - public static final String STORE_DB_USER = "store.db.user"; - - /** - * The constant STORE_DB_PASSWORD. - */ - public static final String STORE_DB_PASSWORD = "store.db.password"; - - /** - * The constant STORE_DB_MIN_CONN. - */ - public static final String STORE_DB_MIN_CONN = "store.db.min-conn"; - - /** - * The constant STORE_DB_MAX_CONN. - */ - public static final String STORE_DB_MAX_CONN = "store.db.max-conn"; - - /** - * The constant STORE_DB_LOG_QUERY_LIMIT. - */ - public static final String STORE_DB_LOG_QUERY_LIMIT = "store.db.query-limit"; - - /** - * The constant LOCK_MODE. - */ - public static final String LOCK_MODE = "lock.mode"; - - /** - * The constant LOCK_DB_TABLE. - */ - public static final String LOCK_DB_TABLE = "lock.db.lock-table"; - - /** - * The constant LOCK_DB_DEFAULT_TABLE. - */ - public static final String LOCK_DB_DEFAULT_TABLE = "lock_table"; - - /** - * The constant COMMITING_RETRY_DELAY. - */ - public static final String COMMITING_RETRY_DELAY = "recovery.committing-retry-delay"; - - /** - * The constant ASYN_COMMITING_RETRY_DELAY. - */ - public static final String ASYN_COMMITING_RETRY_DELAY = "recovery.asyn-committing-retry-delay"; - - /** - * The constant ROLLBACKING_RETRY_DELAY. - */ - public static final String ROLLBACKING_RETRY_DELAY = "recovery.rollbacking-retry-delay"; - - /** - * The constant TIMEOUT_RETRY_DELAY. - */ - public static final String TIMEOUT_RETRY_DELAY = "recovery.timeout-retry-delay"; - - - /** - * The constant TRANSACTION_PREFIX. - */ - public static final String TRANSACTION_PREFIX = "transaction."; - - /** - * The constant RM_DATASOURCE_UNOD_VALIDATION. - */ - public static final String TRANSACTION_UNOD_DATA_VALIDATION = TRANSACTION_PREFIX + "undo.data.validation"; } diff --git a/core/src/main/java/io/seata/core/constants/DBType.java b/core/src/main/java/io/seata/core/constants/DBType.java deleted file mode 100644 index cdb0174b985..00000000000 --- a/core/src/main/java/io/seata/core/constants/DBType.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.constants; - -import io.seata.common.util.StringUtils; - -/** - * database type - * - * @author zhangsen - * @data 2019 /4/2 - */ -public enum DBType { - - /** - * Mysql db type. - */ - MYSQL, - - /** - * Oracle db type. - */ - ORACLE, - - /** - * Db 2 db type. - */ - DB2, - - /** - * Sqlserver db type. - */ - SQLSERVER, - - /** - * Sybaee db type. - */ - SYBAEE, - - /** - * H2 db type. - */ - H2, - - /** - * Sqlite db type. - */ - SQLITE, - - /** - * Access db type. - */ - ACCESS, - - /** - * Postgresql db type. - */ - POSTGRESQL, - - /** - * Oceanbase db type. - */ - OCEANBASE; - - /** - * Valueof db type. - * - * @param dbType the db type - * @return the db type - */ - public static DBType valueof (String dbType){ - for(DBType dt : values()){ - if(StringUtils.equalsIgnoreCase(dt.name(),dbType)){ - return dt; - } - } - throw new IllegalArgumentException("unknown dbtype:" + dbType); - } - -} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java index a8501be705a..9aa741dd28d 100644 --- a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java +++ b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java @@ -15,8 +15,6 @@ */ package io.seata.core.exception; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; import io.seata.core.protocol.ResultCode; import io.seata.core.protocol.transaction.AbstractTransactionRequest; import io.seata.core.protocol.transaction.AbstractTransactionResponse; @@ -28,11 +26,6 @@ */ public abstract class AbstractExceptionHandler { - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - /** * The interface Callback. * diff --git a/core/src/main/java/io/seata/core/lock/AbstractLocker.java b/core/src/main/java/io/seata/core/lock/AbstractLocker.java deleted file mode 100644 index ddb0dd073ef..00000000000 --- a/core/src/main/java/io/seata/core/lock/AbstractLocker.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.lock; - -import io.seata.common.util.CollectionUtils; -import io.seata.core.store.LockDO; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -/** - * The type Abstract locker. - * - * @author zhangsen - * @data 2019 -05-15 - */ -public abstract class AbstractLocker implements Locker { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractLocker.class); - - /** - * The constant LOCK_SPLIT. - */ - protected static final String LOCK_SPLIT = "^^^"; - - /** - * Convert to lock do list. - * - * @param locks the locks - * @return the list - */ - protected List convertToLockDO(List locks){ - List lockDOs = new ArrayList<>(); - if(CollectionUtils.isEmpty(locks)){ - return lockDOs; - } - for(RowLock rowLock : locks){ - LockDO lockDO = new LockDO(); - lockDO.setBranchId(rowLock.getBranchId()); - lockDO.setPk(rowLock.getPk()); - lockDO.setResourceId(rowLock.getResourceId()); - lockDO.setRowKey(getRowKey(rowLock.getResourceId(), rowLock.getTableName(), rowLock.getPk())); - lockDO.setXid(rowLock.getXid()); - lockDO.setTransactionId(rowLock.getTransactionId()); - lockDO.setTableName(rowLock.getTableName()); - lockDOs.add(lockDO); - } - return lockDOs; - } - - /** - * Get row key string. - * - * @param resourceId the resource id - * @param tableName the table name - * @param pk the pk - * @return the string - */ - protected String getRowKey(String resourceId, String tableName, String pk){ - return new StringBuilder().append(resourceId).append(LOCK_SPLIT).append(tableName).append(LOCK_SPLIT).append(pk).toString(); - } - - @Override - public void cleanAllLocks() { - - } -} diff --git a/core/src/main/java/io/seata/core/lock/LocalDBLocker.java b/core/src/main/java/io/seata/core/lock/LocalDBLocker.java deleted file mode 100644 index c342e8f6ecf..00000000000 --- a/core/src/main/java/io/seata/core/lock/LocalDBLocker.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.lock; - -import java.util.List; - -/** - * The type Local db locker. - * - * @author zhangsen - * @data 2019 -05-15 - */ -public class LocalDBLocker extends AbstractLocker { - - @Override - public boolean acquireLock(List rowLock) { - return false; - } - - @Override - public boolean releaseLock(List rowLock) { - return false; - } - - @Override - public boolean isLockable(List rowLock) { - return false; - } -} diff --git a/core/src/main/java/io/seata/core/lock/LockMode.java b/core/src/main/java/io/seata/core/lock/LockMode.java deleted file mode 100644 index f1a11d0b9ea..00000000000 --- a/core/src/main/java/io/seata/core/lock/LockMode.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.lock; - -/** - * lock mode - * - * @author zhangsen - * @data 2019 /4/25 - */ -public enum LockMode { - - /** - * store the lock in memory of server - */ - MEMORY, - - /** - * store the lock in db of server - */ - DB; - - -} diff --git a/core/src/main/java/io/seata/core/lock/Locker.java b/core/src/main/java/io/seata/core/lock/Locker.java deleted file mode 100644 index 8990699d317..00000000000 --- a/core/src/main/java/io/seata/core/lock/Locker.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.lock; - -import java.util.List; - -/** - * The interface Locker. - * - * @author zhangsen - * @data 2019 -05-15 - */ -public interface Locker { - - /** - * Acquire lock boolean. - * - * @param rowLock the row lock - * @return the boolean - */ - boolean acquireLock(List rowLock) ; - - /** - * Un lock boolean. - * - * @param rowLock the row lock - * @return the boolean - */ - boolean releaseLock(List rowLock); - - /** - * Is lockable boolean. - * - * @param rowLock the row lock - * @return the boolean - */ - boolean isLockable(List rowLock); - - /** - * Clean all locks boolean. - * - * @return the boolean - */ - void cleanAllLocks(); -} - diff --git a/core/src/main/java/io/seata/core/lock/RowLock.java b/core/src/main/java/io/seata/core/lock/RowLock.java deleted file mode 100644 index 9675cb9011d..00000000000 --- a/core/src/main/java/io/seata/core/lock/RowLock.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.lock; - -import io.seata.common.util.StringUtils; - -/** - * The type Row lock. - * - * @author zhangsen - * @data 2019 -05-15 - */ -public class RowLock { - - private String xid; - - private Long transactionId; - - private Long branchId; - - private String resourceId; - - private String tableName; - - private String pk; - - private String rowKey; - - private String feature; - - /** - * Gets xid. - * - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - - /** - * Gets transaction id. - * - * @return the transaction id - */ - public Long getTransactionId() { - return transactionId; - } - - /** - * Sets transaction id. - * - * @param transactionId the transaction id - */ - public void setTransactionId(Long transactionId) { - this.transactionId = transactionId; - } - - /** - * Gets branch id. - * - * @return the branch id - */ - public Long getBranchId() { - return branchId; - } - - /** - * Sets branch id. - * - * @param branchId the branch id - */ - public void setBranchId(Long branchId) { - this.branchId = branchId; - } - - /** - * Gets resource id. - * - * @return the resource id - */ - public String getResourceId() { - return resourceId; - } - - /** - * Sets resource id. - * - * @param resourceId the resource id - */ - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - /** - * Gets table name. - * - * @return the table name - */ - public String getTableName() { - return tableName; - } - - /** - * Sets table name. - * - * @param tableName the table name - */ - public void setTableName(String tableName) { - this.tableName = tableName; - } - - /** - * Gets pk. - * - * @return the pk - */ - public String getPk() { - return pk; - } - - /** - * Sets pk. - * - * @param pk the pk - */ - public void setPk(String pk) { - this.pk = pk; - } - - /** - * Gets row key. - * - * @return the row key - */ - public String getRowKey() { - return rowKey; - } - - /** - * Sets row key. - * - * @param rowKey the row key - */ - public void setRowKey(String rowKey) { - this.rowKey = rowKey; - } - - /** - * Gets feature. - * - * @return the feature - */ - public String getFeature() { - return feature; - } - - /** - * Sets feature. - * - * @param feature the feature - */ - public void setFeature(String feature) { - this.feature = feature; - } - - @Override - public String toString(){ - return StringUtils.toString(this); - } -} - diff --git a/core/src/main/java/io/seata/core/protocol/AbstractMessage.java b/core/src/main/java/io/seata/core/protocol/AbstractMessage.java index 60ec91b978d..e6f3dd07e09 100644 --- a/core/src/main/java/io/seata/core/protocol/AbstractMessage.java +++ b/core/src/main/java/io/seata/core/protocol/AbstractMessage.java @@ -18,7 +18,6 @@ import java.io.Serializable; import java.nio.charset.Charset; -import io.seata.common.Constants; import io.seata.core.protocol.transaction.BranchCommitRequest; import io.seata.core.protocol.transaction.BranchCommitResponse; import io.seata.core.protocol.transaction.BranchRegisterRequest; @@ -153,7 +152,7 @@ public abstract class AbstractMessage implements MessageCodec, Serializable { /** * The constant UTF8. */ - protected static final Charset UTF8 = Constants.DEFAULT_CHARSET; + protected static final Charset UTF8 = Charset.forName("utf-8"); /** * The Ctx. */ diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java index de8dcf726bd..3f5a40470e7 100644 --- a/core/src/main/java/io/seata/core/protocol/Version.java +++ b/core/src/main/java/io/seata/core/protocol/Version.java @@ -31,7 +31,7 @@ public class Version { /** * The constant CURRENT. */ - public static final String CURRENT = "0.6.0"; + public static final String CURRENT = "0.5.2"; /** * The constant VERSION_MAP. diff --git a/core/src/main/java/io/seata/core/rpc/ChannelManager.java b/core/src/main/java/io/seata/core/rpc/ChannelManager.java index 9de2904e93e..d63086ea251 100644 --- a/core/src/main/java/io/seata/core/rpc/ChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/ChannelManager.java @@ -29,6 +29,7 @@ import io.seata.core.protocol.RegisterRMRequest; import io.seata.core.protocol.RegisterTMRequest; import io.seata.core.protocol.Version; +import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; import io.netty.channel.Channel; import io.seata.core.rpc.netty.NettyPoolKey; diff --git a/core/src/main/java/io/seata/core/rpc/RpcContext.java b/core/src/main/java/io/seata/core/rpc/RpcContext.java index 6ba531eb16a..b605b72d067 100644 --- a/core/src/main/java/io/seata/core/rpc/RpcContext.java +++ b/core/src/main/java/io/seata/core/rpc/RpcContext.java @@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentMap; import io.seata.common.Constants; +import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; import io.netty.channel.Channel; import io.seata.core.rpc.netty.NettyPoolKey; diff --git a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java b/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java index d5bf8625ca7..44c33d31fdf 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java +++ b/core/src/main/java/io/seata/core/rpc/netty/AbstractRpcRemoting.java @@ -35,7 +35,12 @@ import io.seata.common.exception.FrameworkErrorCode; import io.seata.common.exception.FrameworkException; import io.seata.common.thread.NamedThreadFactory; +import io.seata.core.protocol.HeartbeatMessage; +import io.seata.core.protocol.MergeMessage; +import io.seata.core.protocol.MessageFuture; +import io.seata.core.protocol.RpcMessage; +import io.seata.core.rpc.Disposable; import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelFuture; diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java index 24c7a0f7c51..2ae97ced878 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java @@ -15,6 +15,8 @@ */ package io.seata.core.rpc.netty; +import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; + import io.netty.channel.Channel; /** diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java b/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java index 9d69006f9fb..db29b780465 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyPoolableFactory.java @@ -21,6 +21,7 @@ import io.seata.common.util.NetUtil; import io.seata.core.protocol.RegisterRMResponse; import io.seata.core.protocol.RegisterTMResponse; +import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole; import io.netty.channel.Channel; import org.apache.commons.pool.KeyedPoolableObjectFactory; diff --git a/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java b/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java index ef0afc75f63..d078a4df0da 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RegisterCheckAuthHandler.java @@ -15,6 +15,8 @@ */ package io.seata.core.rpc.netty; +import io.seata.core.protocol.RegisterRMRequest; +import io.seata.core.protocol.RegisterTMRequest; import io.seata.core.protocol.RegisterRMRequest; import io.seata.core.protocol.RegisterTMRequest; diff --git a/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java b/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java index 98ba76fad03..42a9eedbac5 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RegisterMsgListener.java @@ -15,6 +15,8 @@ */ package io.seata.core.rpc.netty; +import io.seata.core.protocol.AbstractMessage; + import io.netty.channel.Channel; import io.seata.core.protocol.AbstractMessage; diff --git a/core/src/main/java/io/seata/core/store/BranchTransactionDO.java b/core/src/main/java/io/seata/core/store/BranchTransactionDO.java deleted file mode 100644 index 63c784daf6c..00000000000 --- a/core/src/main/java/io/seata/core/store/BranchTransactionDO.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store; - - -import io.seata.common.util.StringUtils; -import io.seata.core.model.BranchStatus; - -import java.util.Date; - -/** - * branch transaction data object - * - * @author zhangsen - * @data 2019 /3/26 - */ -public class BranchTransactionDO { - - private String xid; - - private long transactionId; - - private long branchId; - - private String resourceGroupId; - - private String resourceId; - - private String lockKey; - - private String branchType; - - private int status = BranchStatus.Unknown.getCode(); - - private String clientId; - - private String applicationData; - - private Date gmtCreate; - - private Date gmtModified; - - /** - * Gets xid. - * - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - - /** - * Gets transaction id. - * - * @return the transaction id - */ - public long getTransactionId() { - return transactionId; - } - - /** - * Sets transaction id. - * - * @param transactionId the transaction id - */ - public void setTransactionId(long transactionId) { - this.transactionId = transactionId; - } - - /** - * Gets branch id. - * - * @return the branch id - */ - public long getBranchId() { - return branchId; - } - - /** - * Sets branch id. - * - * @param branchId the branch id - */ - public void setBranchId(long branchId) { - this.branchId = branchId; - } - - /** - * Gets resource group id. - * - * @return the resource group id - */ - public String getResourceGroupId() { - return resourceGroupId; - } - - /** - * Sets resource group id. - * - * @param resourceGroupId the resource group id - */ - public void setResourceGroupId(String resourceGroupId) { - this.resourceGroupId = resourceGroupId; - } - - /** - * Gets resource id. - * - * @return the resource id - */ - public String getResourceId() { - return resourceId; - } - - /** - * Sets resource id. - * - * @param resourceId the resource id - */ - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - /** - * Gets lock key. - * - * @return the lock key - */ - public String getLockKey() { - return lockKey; - } - - /** - * Sets lock key. - * - * @param lockKey the lock key - */ - public void setLockKey(String lockKey) { - this.lockKey = lockKey; - } - - /** - * Gets branch type. - * - * @return the branch type - */ - public String getBranchType() { - return branchType; - } - - /** - * Sets branch type. - * - * @param branchType the branch type - */ - public void setBranchType(String branchType) { - this.branchType = branchType; - } - - /** - * Gets status. - * - * @return the status - */ - public int getStatus() { - return status; - } - - /** - * Sets status. - * - * @param status the status - */ - public void setStatus(int status) { - this.status = status; - } - - /** - * Gets client id. - * - * @return the client id - */ - public String getClientId() { - return clientId; - } - - /** - * Sets client id. - * - * @param clientId the client id - */ - public void setClientId(String clientId) { - this.clientId = clientId; - } - - /** - * Gets application data. - * - * @return the application data - */ - public String getApplicationData() { - return applicationData; - } - - /** - * Sets application data. - * - * @param applicationData the application data - */ - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } - - /** - * Gets gmt create. - * - * @return the gmt create - */ - public Date getGmtCreate() { - return gmtCreate; - } - - /** - * Sets gmt create. - * - * @param gmtCreate the gmt create - */ - public void setGmtCreate(Date gmtCreate) { - this.gmtCreate = gmtCreate; - } - - /** - * Gets gmt modified. - * - * @return the gmt modified - */ - public Date getGmtModified() { - return gmtModified; - } - - /** - * Sets gmt modified. - * - * @param gmtModified the gmt modified - */ - public void setGmtModified(Date gmtModified) { - this.gmtModified = gmtModified; - } - - @Override - public String toString(){ - return StringUtils.toString(this); - } - -} diff --git a/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java b/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java deleted file mode 100644 index 74c5e9ae13f..00000000000 --- a/core/src/main/java/io/seata/core/store/GlobalTransactionDO.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store; - - -import io.seata.common.util.StringUtils; - -import java.util.Date; - -/** - * Global Transaction data object - * - * @author zhangsen - * @data 2019 /3/26 - */ -public class GlobalTransactionDO { - - private String xid; - - private long transactionId; - - private int status; - - private String applicationId; - - private String transactionServiceGroup; - - private String transactionName; - - private int timeout; - - private long beginTime; - - private String applicationData; - - private Date gmtCreate; - - private Date gmtModified; - - /** - * Gets xid. - * - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - - /** - * Gets status. - * - * @return the status - */ - public int getStatus() { - return status; - } - - /** - * Sets status. - * - * @param status the status - */ - public void setStatus(int status) { - this.status = status; - } - - /** - * Gets application id. - * - * @return the application id - */ - public String getApplicationId() { - return applicationId; - } - - /** - * Sets application id. - * - * @param applicationId the application id - */ - public void setApplicationId(String applicationId) { - this.applicationId = applicationId; - } - - /** - * Gets transaction service group. - * - * @return the transaction service group - */ - public String getTransactionServiceGroup() { - return transactionServiceGroup; - } - - /** - * Sets transaction service group. - * - * @param transactionServiceGroup the transaction service group - */ - public void setTransactionServiceGroup(String transactionServiceGroup) { - this.transactionServiceGroup = transactionServiceGroup; - } - - /** - * Gets transaction name. - * - * @return the transaction name - */ - public String getTransactionName() { - return transactionName; - } - - /** - * Sets transaction name. - * - * @param transactionName the transaction name - */ - public void setTransactionName(String transactionName) { - this.transactionName = transactionName; - } - - /** - * Gets timeout. - * - * @return the timeout - */ - public int getTimeout() { - return timeout; - } - - /** - * Sets timeout. - * - * @param timeout the timeout - */ - public void setTimeout(int timeout) { - this.timeout = timeout; - } - - /** - * Gets begin time. - * - * @return the begin time - */ - public long getBeginTime() { - return beginTime; - } - - /** - * Sets begin time. - * - * @param beginTime the begin time - */ - public void setBeginTime(long beginTime) { - this.beginTime = beginTime; - } - - /** - * Gets transaction id. - * - * @return the transaction id - */ - public long getTransactionId() { - return transactionId; - } - - /** - * Sets transaction id. - * - * @param transactionId the transaction id - */ - public void setTransactionId(long transactionId) { - this.transactionId = transactionId; - } - - /** - * Gets application data. - * - * @return the application data - */ - public String getApplicationData() { - return applicationData; - } - - /** - * Sets application data. - * - * @param applicationData the application data - */ - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } - - /** - * Gets gmt create. - * - * @return the gmt create - */ - public Date getGmtCreate() { - return gmtCreate; - } - - /** - * Sets gmt create. - * - * @param gmtCreate the gmt create - */ - public void setGmtCreate(Date gmtCreate) { - this.gmtCreate = gmtCreate; - } - - /** - * Gets gmt modified. - * - * @return the gmt modified - */ - public Date getGmtModified() { - return gmtModified; - } - - /** - * Sets gmt modified. - * - * @param gmtModified the gmt modified - */ - public void setGmtModified(Date gmtModified) { - this.gmtModified = gmtModified; - } - - @Override - public String toString(){ - return StringUtils.toString(this); - } - -} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/LockDO.java b/core/src/main/java/io/seata/core/store/LockDO.java deleted file mode 100644 index 51b242de627..00000000000 --- a/core/src/main/java/io/seata/core/store/LockDO.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store; - -import io.seata.common.util.StringUtils; - -/** - * The type Lock do. - * - * @author zhangsen - * @data 2019 /4/25 - */ -public class LockDO { - - private String xid; - - private Long transactionId; - - private Long branchId; - - private String resourceId; - - private String tableName; - - private String pk; - - private String rowKey; - - /** - * Instantiates a new Lock do. - */ - public LockDO() { - } - - /** - * Gets xid. - * - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - - /** - * Gets transaction id. - * - * @return the transaction id - */ - public Long getTransactionId() { - return transactionId; - } - - /** - * Sets transaction id. - * - * @param transactionId the transaction id - */ - public void setTransactionId(Long transactionId) { - this.transactionId = transactionId; - } - - /** - * Gets resource id. - * - * @return the resource id - */ - public String getResourceId() { - return resourceId; - } - - /** - * Sets resource id. - * - * @param resourceId the resource id - */ - public void setResourceId(String resourceId) { - this.resourceId = resourceId; - } - - /** - * Gets row key. - * - * @return the row key - */ - public String getRowKey() { - return rowKey; - } - - /** - * Sets row key. - * - * @param rowKey the row key - */ - public void setRowKey(String rowKey) { - this.rowKey = rowKey; - } - - /** - * Gets table name. - * - * @return the table name - */ - public String getTableName() { - return tableName; - } - - /** - * Sets table name. - * - * @param tableName the table name - */ - public void setTableName(String tableName) { - this.tableName = tableName; - } - - /** - * Gets pk. - * - * @return the pk - */ - public String getPk() { - return pk; - } - - /** - * Sets pk. - * - * @param pk the pk - */ - public void setPk(String pk) { - this.pk = pk; - } - - /** - * Gets branch id. - * - * @return the branch id - */ - public Long getBranchId() { - return branchId; - } - - /** - * Sets branch id. - * - * @param branchId the branch id - */ - public void setBranchId(Long branchId) { - this.branchId = branchId; - } - - @Override - public String toString() { - return StringUtils.toString(this); - } -} diff --git a/core/src/main/java/io/seata/core/store/LockStore.java b/core/src/main/java/io/seata/core/store/LockStore.java deleted file mode 100644 index 49e92e6ab10..00000000000 --- a/core/src/main/java/io/seata/core/store/LockStore.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store; - -import java.util.List; - -/** - * The interface Lock store. - * - * @author zhangsen - * @data 2019 /4/25 - */ -public interface LockStore { - - /** - * Acquire lock boolean. - * - * @param lockDO the lock do - * @return the boolean - */ - boolean acquireLock(LockDO lockDO); - - - /** - * Acquire lock boolean. - * - * @param lockDOs the lock d os - * @return the boolean - */ - boolean acquireLock(List lockDOs); - - /** - * Un lock boolean. - * - * @param lockDO the lock do - * @return the boolean - */ - boolean unLock(LockDO lockDO); - - /** - * Un lock boolean. - * - * @param lockDOs the lock d os - * @return the boolean - */ - boolean unLock(List lockDOs); - - /** - * Is lockable boolean. - * - * @param lockDOs the lock do - * @return the boolean - */ - boolean isLockable(List lockDOs); -} diff --git a/core/src/main/java/io/seata/core/store/LogStore.java b/core/src/main/java/io/seata/core/store/LogStore.java deleted file mode 100644 index f02b0ddc6d2..00000000000 --- a/core/src/main/java/io/seata/core/store/LogStore.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store; - - -import java.util.List; - -/** - * the transaction log store - * - * @author zhangsen - * @data 2019 /3/26 - */ -public interface LogStore { - - /** - * Query global transaction do global transaction do. - * - * @param xid the xid - * @return the global transaction do - */ - GlobalTransactionDO queryGlobalTransactionDO(String xid); - - /** - * Query global transaction do global transaction do. - * - * @param transactionId the transaction id - * @return the global transaction do - */ - GlobalTransactionDO queryGlobalTransactionDO(long transactionId); - - /** - * Query global transaction do list. - * - * @param status the status - * @param limit the limit - * @return the list - */ - List queryGlobalTransactionDO(int[] status, int limit); - - /** - * Insert global transaction do boolean. - * - * @param globalTransactionDO the global transaction do - * @return the boolean - */ - boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO); - - /** - * Update global transaction do boolean. - * - * @param globalTransactionDO the global transaction do - * @return the boolean - */ - boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO); - - /** - * Delete global transaction do boolean. - * - * @param globalTransactionDO the global transaction do - * @return the boolean - */ - boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO); - - /** - * Query branch transaction do boolean. - * - * @param xid the xid - * @return the boolean - */ - List queryBranchTransactionDO(String xid); - - /** - * Insert branch transaction do boolean. - * - * @param branchTransactionDO the branch transaction do - * @return the boolean - */ - boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO); - - /** - * Update branch transaction do boolean. - * - * @param branchTransactionDO the branch transaction do - * @return the boolean - */ - boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO); - - /** - * Delete branch transaction do boolean. - * - * @param branchTransactionDO the branch transaction do - * @return the boolean - */ - boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO); - -} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java b/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java deleted file mode 100644 index 2cdbcb00ce6..00000000000 --- a/core/src/main/java/io/seata/core/store/db/AbstractDataSourceGenerator.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - -import io.seata.common.exception.StoreException; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.constants.DBType; - -/** - * The type Abstract data source generator. - * - * @author zhangsen - * @data 2019 /4/24 - */ -public abstract class AbstractDataSourceGenerator implements DataSourceGenerator { - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * Get db type db type. - * - * @return the db type - */ - protected DBType getDBType(){ - return DBType.valueof(CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE)); - } - - /** - * Get url string. - * - * @return the string - */ - protected String getUrl(){ - String url = CONFIG.getConfig(ConfigurationKeys.STORE_DB_URL); - if(StringUtils.isBlank(url)){ - throw new StoreException("the {store.db.url} can't empty."); - } - return url; - } - - /** - * Get user string. - * - * @return the string - */ - protected String getUser(){ - String user = CONFIG.getConfig(ConfigurationKeys.STORE_DB_USER); - if(StringUtils.isBlank(user)){ - throw new StoreException("the {store.db.user} can't empty."); - } - return user; - } - - /** - * Get password string. - * - * @return the string - */ - protected String getPassword(){ - String password = CONFIG.getConfig(ConfigurationKeys.STORE_DB_PASSWORD); - return password; - } - - /** - * Get min conn int. - * - * @return the int - */ - protected int getMinConn(){ - int minConn = CONFIG.getInt(ConfigurationKeys.STORE_DB_MIN_CONN); - return minConn<0?0:minConn; - } - - /** - * Get max conn int. - * - * @return the int - */ - protected int getMaxConn(){ - int maxConn = CONFIG.getInt(ConfigurationKeys.STORE_DB_MAX_CONN); - return maxConn<0?1:maxConn; - } - - - /** - * Get driver name string. - * - * @param dbType the db type - * @return the string - */ - protected static String getDriverName(DBType dbType){ - if(DBType.H2.equals(dbType)){ - return "org.h2.Driver"; - }else if(DBType.MYSQL.equals(dbType)){ - return "com.mysql.jdbc.Driver"; - }else if(DBType.ORACLE.equals(dbType)){ - return "oracle.jdbc.OracleDriver"; - }else if(DBType.SYBAEE.equals(dbType)){ - return "com.sybase.jdbc2.jdbc.SybDriver"; - }else if(DBType.SQLSERVER.equals(dbType)){ - return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; - }else if(DBType.SQLITE.equals(dbType)){ - return "org.sqlite.JDBC"; - }else if(DBType.POSTGRESQL.equals(dbType)){ - return "org.postgresql.Driver"; - }else if(DBType.ACCESS.equals(dbType)){ - return "com.hxtt.sql.access.AccessDriver"; - }else if(DBType.DB2.equals(dbType)){ - return "com.ibm.db2.jcc.DB2Driver"; - }else { - throw new StoreException("Unsupported database type, dbType:" + dbType); - } - } - - /** - * Get validation query string. - * - * @param dbType the db type - * @return the string - */ - protected String getValidationQuery(DBType dbType){ - if(DBType.ORACLE.equals(dbType)){ - return "select sysdate from dual"; - }else { - return "select 1"; - } - } - -} diff --git a/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java b/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java deleted file mode 100644 index 5687513969b..00000000000 --- a/core/src/main/java/io/seata/core/store/db/DataSourceGenerator.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - -import javax.sql.DataSource; - -/** - * The interface Data source generator. - * - * @author zhangsen - * @data 2019 /4/24 - */ -public interface DataSourceGenerator { - - /** - * create DataSource from config - * - * @return data source - */ - DataSource generateDataSource(); - -} diff --git a/core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java b/core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java deleted file mode 100644 index b1aac288814..00000000000 --- a/core/src/main/java/io/seata/core/store/db/LockStoreDataBaseDAO.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - -import io.seata.common.exception.StoreException; -import io.seata.common.executor.Initialize; -import io.seata.common.loader.LoadLevel; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.store.LockDO; -import io.seata.core.store.LockStore; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -/** - * The type Data base lock store. - * - * @author zhangsen - * @data 2019 /4/25 - */ -@LoadLevel(name = "db") -public class LockStoreDataBaseDAO implements LockStore, Initialize { - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The Log store data source. - */ - protected DataSource logStoreDataSource = null; - - /** - * The Lock table. - */ - protected String lockTable; - - /** - * The Db type. - */ - protected String dbType; - - /** - * Instantiates a new Data base lock store dao. - * - * @param logStoreDataSource the log store data source - */ - public LockStoreDataBaseDAO(DataSource logStoreDataSource) { - this.logStoreDataSource = logStoreDataSource; - } - - @Override - public void init() { - lockTable = CONFIG.getConfig(ConfigurationKeys.LOCK_DB_TABLE, ConfigurationKeys.LOCK_DB_DEFAULT_TABLE); - dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); - if (StringUtils.isBlank(dbType)) { - throw new StoreException("there must be db type."); - } - if (logStoreDataSource == null) { - throw new StoreException("there must be logStoreDataSource."); - } - } - - @Override - public boolean acquireLock(LockDO lockDO) { - List locks = new ArrayList<>(); - locks.add(lockDO); - return acquireLock(locks); - } - - @Override - public boolean acquireLock(List lockDOs) { - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(false); - - //check lock - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < lockDOs.size(); i++){ - sb.append("?"); - if( i != (lockDOs.size() - 1)){ - sb.append(", "); - } - } - boolean canLock = true, isReLock = false; - //query - String checkLockSQL = LockStoreSqls.getCheckLockableSql(lockTable, sb.toString(), dbType); - ps = conn.prepareStatement(checkLockSQL); - for (int i = 0; i < lockDOs.size(); i++){ - ps.setString(i+1, lockDOs.get(i).getRowKey()); - } - rs = ps.executeQuery(); - while (rs.next()) { - if(StringUtils.equals(rs.getString("xid"), lockDOs.get(0).getXid())){ - isReLock = true; - }else { - canLock &= false; - } - } - - if(!canLock){ - conn.rollback(); - return false; - } - - if(isReLock){ - conn.rollback(); - return true; - } - - //lock - for(LockDO lockDO : lockDOs){ - if(!doAcquireLock(conn, lockDO)) { - conn.rollback(); - return false; - } - } - conn.commit(); - return true; - } catch (SQLException e) { - throw new StoreException(e); - } finally { - if (rs != null) { - try { - rs.close(); - } catch (SQLException e) { - } - } - if (ps != null) { - try { - ps.close(); - } catch (SQLException e) { - } - } - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean unLock(LockDO lockDO) { - List locks = new ArrayList<>(); - locks.add(lockDO); - return unLock(locks); - } - - @Override - public boolean unLock(List lockDOs) { - Connection conn = null; - PreparedStatement ps = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - - StringBuilder sb = new StringBuilder(); - for(int i = 0; i< lockDOs.size(); i++){ - sb.append("?"); - if(i != (lockDOs.size() - 1)){ - sb.append(", "); - } - } - //batch release lock - String batchDeleteSQL = LockStoreSqls.getBatchDeleteLockSql(lockTable, sb.toString(), dbType); - ps = conn.prepareStatement(batchDeleteSQL); - ps.setString(1, lockDOs.get(0).getXid()); - for(int i = 0; i< lockDOs.size(); i++){ - ps.setString(i+2, lockDOs.get(i).getRowKey()); - } - return ps.executeUpdate() > 0; - } catch (SQLException e) { - throw new StoreException(e); - } finally { - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean isLockable(List lockDOs) { - Connection conn = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - if(!checkLockable(conn, lockDOs)){ - return false; - } - return true; - } catch (SQLException e) { - throw new StoreException(e); - } finally { - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - /** - * Do acquire lock boolean. - * - * @param conn the conn - * @param lockDO the lock do - * @return the boolean - */ - protected boolean doAcquireLock(Connection conn, LockDO lockDO) { - PreparedStatement ps = null; - ResultSet rs = null; - try { - //insert - String insertLockSQL = LockStoreSqls.getInsertLockSQL(lockTable, dbType); - ps = conn.prepareStatement(insertLockSQL); - ps.setString(1, lockDO.getXid()); - ps.setLong(2, lockDO.getTransactionId()); - ps.setLong(3, lockDO.getBranchId()); - ps.setString(4, lockDO.getResourceId()); - ps.setString(5, lockDO.getTableName()); - ps.setString(6, lockDO.getPk()); - ps.setString(7, lockDO.getRowKey()); - return ps.executeUpdate() > 0; - } catch (SQLException e) { - throw new StoreException(e); - } finally { - if (rs != null) { - try { - rs.close(); - } catch (SQLException e) { - } - } - if (ps != null) { - try { - ps.close(); - } catch (SQLException e) { - } - } - } - } - - /** - * Check lock boolean. - * - * @param conn the conn - * @param lockDOs the lock do - * @return the boolean - */ - protected boolean checkLockable(Connection conn, List lockDOs){ - PreparedStatement ps = null; - ResultSet rs = null; - try { - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < lockDOs.size(); i++){ - sb.append("?"); - if( i != (lockDOs.size() - 1)){ - sb.append(", "); - } - } - - //query - String checkLockSQL = LockStoreSqls.getCheckLockableSql(lockTable, sb.toString(), dbType); - ps = conn.prepareStatement(checkLockSQL); - for (int i = 0; i < lockDOs.size(); i++){ - ps.setString(i+1, lockDOs.get(i).getRowKey()); - } - rs = ps.executeQuery(); - while (rs.next()) { - String xid = rs.getString("xid"); - if(!StringUtils.equals(xid, lockDOs.get(0).getXid())){ - return false; - } - } - return true; - }catch (SQLException e) { - throw new StoreException(e); - } finally { - if (rs != null) { - try { - rs.close(); - } catch (SQLException e) { - } - } - if (ps != null) { - try { - ps.close(); - } catch (SQLException e) { - } - } - } - } - - /** - * Sets lock table. - * - * @param lockTable the lock table - */ - public void setLockTable(String lockTable) { - this.lockTable = lockTable; - } - - /** - * Sets db type. - * - * @param dbType the db type - */ - public void setDbType(String dbType) { - this.dbType = dbType; - } - - /** - * Sets log store data source. - * - * @param logStoreDataSource the log store data source - */ - public void setLogStoreDataSource(DataSource logStoreDataSource) { - this.logStoreDataSource = logStoreDataSource; - } -} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/db/LockStoreSqls.java b/core/src/main/java/io/seata/core/store/db/LockStoreSqls.java deleted file mode 100644 index 7c95473e269..00000000000 --- a/core/src/main/java/io/seata/core/store/db/LockStoreSqls.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - -import io.seata.common.exception.NotSupportYetException; -import io.seata.core.constants.DBType; - -/** - * The type Lock store sqls. - * - * @author zhangsen - * @data 2019 /4/26 - */ -public class LockStoreSqls { - - /** - * The constant LOCK_TABLE_PLACEHOLD. - */ - public static final String LOCK_TABLE_PLACEHOLD = " #lock_table# "; - - /** - * The constant IN_PARAMS_PLACEHOLD. - */ - public static final String IN_PARAMS_PLACEHOLD = " #in_params# "; - - /** - * The constant ALL_COLUMNS. - */ - public static final String ALL_COLUMNS = "xid, transaction_id, branch_id, resource_id, table_name, pk, row_key, gmt_create, gmt_modified"; - - /** - * The constant INSERT_LOCK_SQL_MYSQL. - */ - public static final String INSERT_LOCK_SQL_MYSQL = "insert into " + LOCK_TABLE_PLACEHOLD + "("+ ALL_COLUMNS +")" + - "values (?, ?, ?, ?, ?, ?, ?, now(), now())"; - - /** - * The constant INSERT_LOCK_SQL_ORACLE. - */ - public static final String INSERT_LOCK_SQL_ORACLE = "insert into " + LOCK_TABLE_PLACEHOLD + "("+ ALL_COLUMNS +")" + - "values (?, ?, ?, ?, ?, ?, ?, sysdate, sysdate)"; - - /** - * The constant DELETE_LOCK_SQL. - */ - public static final String DELETE_LOCK_SQL = "delete from " + LOCK_TABLE_PLACEHOLD + " where row_key = ? and xid = ?"; - - /** - * The constant BATCH_DELETE_LOCK_SQL. - */ - public static final String BATCH_DELETE_LOCK_SQL = "delete from " + LOCK_TABLE_PLACEHOLD + " where xid = ? and row_key in ("+ IN_PARAMS_PLACEHOLD +") "; - - /** - * The constant QUERY_LOCK_SQL. - */ - public static final String QUERY_LOCK_SQL = "select " + ALL_COLUMNS + " from " + LOCK_TABLE_PLACEHOLD - + " where row_key = ? "; - - /** - * The constant CHECK_LOCK_SQL. - */ - public static final String CHECK_LOCK_SQL = "select " + ALL_COLUMNS + " from " + LOCK_TABLE_PLACEHOLD - + " where row_key in ("+ IN_PARAMS_PLACEHOLD +")" ; - - /** - * Get insert lock sql string. - * - * @param lockTable the lock table - * @param dbType the db type - * @return the string - */ - public static String getInsertLockSQL(String lockTable, String dbType){ - if(DBType.MYSQL.name().equalsIgnoreCase(dbType) - || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) - || DBType.H2.name().equalsIgnoreCase(dbType)){ - return INSERT_LOCK_SQL_MYSQL.replace(LOCK_TABLE_PLACEHOLD, lockTable); - }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ - return INSERT_LOCK_SQL_ORACLE.replace(LOCK_TABLE_PLACEHOLD, lockTable); - }else{ - throw new NotSupportYetException("unknown dbType:" + dbType); - } - } - - /** - * Get delete lock sql string. - * - * @param lockTable the lock table - * @param dbType the db type - * @return the string - */ - public static String getDeleteLockSql(String lockTable, String dbType){ - return DELETE_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable); - } - - /** - * Get batch delete lock sql string. - * - * @param lockTable the lock table - * @param paramPlaceHold the param place hold - * @param dbType the db type - * @return the string - */ - public static String getBatchDeleteLockSql(String lockTable, String paramPlaceHold, String dbType){ - return BATCH_DELETE_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable).replace(IN_PARAMS_PLACEHOLD, paramPlaceHold); - } - - /** - * Get query lock sql string. - * - * @param lockTable the lock table - * @param dbType the db type - * @return the string - */ - public static String getQueryLockSql(String lockTable, String dbType){ - return QUERY_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable); - } - - /** - * Get check lock sql string. - * - * @param lockTable the lock table - * @param paramPlaceHold the param place hold - * @param dbType the db type - * @return the string - */ - public static String getCheckLockableSql(String lockTable, String paramPlaceHold, String dbType){ - return CHECK_LOCK_SQL.replace(LOCK_TABLE_PLACEHOLD, lockTable).replace(IN_PARAMS_PLACEHOLD, paramPlaceHold); - } - -} diff --git a/core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java b/core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java deleted file mode 100644 index 4248ce45929..00000000000 --- a/core/src/main/java/io/seata/core/store/db/LogStoreDataBaseDAO.java +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - -import io.seata.common.exception.StoreException; -import io.seata.common.executor.Initialize; -import io.seata.common.loader.LoadLevel; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import io.seata.core.store.LogStore; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -/** - * The type Log store data base dao. - * - * @author zhangsen - * @data 2019 /4/2 - */ -@LoadLevel(name = "db") -public class LogStoreDataBaseDAO implements LogStore, Initialize { - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The Log store data source. - */ - protected DataSource logStoreDataSource = null; - - /** - * The Global table. - */ - protected String globalTable; - - /** - * The Brach table. - */ - protected String brachTable; - - private String dbType; - - /** - * Instantiates a new Log store data base dao. - */ - public LogStoreDataBaseDAO(){ - } - - /** - * Instantiates a new Log store data base dao. - * - * @param logStoreDataSource the log store data source - */ - public LogStoreDataBaseDAO(DataSource logStoreDataSource) { - this.logStoreDataSource = logStoreDataSource; - } - - @Override - public void init() { - globalTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, ConfigurationKeys.STORE_DB_GLOBAL_DEFAULT_TABLE); - brachTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, ConfigurationKeys.STORE_DB_BRANCH_DEFAULT_TABLE); - dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); - if(StringUtils.isBlank(dbType)){ - throw new StoreException("there must be db type."); - } - if(logStoreDataSource == null){ - throw new StoreException("there must be logStoreDataSource."); - } - } - - @Override - public GlobalTransactionDO queryGlobalTransactionDO(String xid) { - String sql = LogStoreSqls.getQueryGlobalTransactionSQL(globalTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, xid); - rs = ps.executeQuery(); - if(rs.next()){ - return convertGlobalTransactionDO(rs); - }else { - return null; - } - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(rs != null){ - try { - rs.close(); - } catch (SQLException e) { - } - } - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - - @Override - public GlobalTransactionDO queryGlobalTransactionDO(long transactionId){ - String sql = LogStoreSqls.getQueryGlobalTransactionSQLByTransactionId(globalTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setLong(1, transactionId); - rs = ps.executeQuery(); - if(rs.next()){ - return convertGlobalTransactionDO(rs); - }else { - return null; - } - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(rs != null){ - try { - rs.close(); - } catch (SQLException e) { - } - } - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public List queryGlobalTransactionDO(int[] statuses, int limit) { - List ret = new ArrayList(); - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < statuses.length; i ++){ - sb.append("?"); - if(i != (statuses.length -1)){ - sb.append(", "); - } - } - - String sql = LogStoreSqls.getQueryGlobalTransactionSQLByStatus(globalTable, dbType, sb.toString()); - ps = conn.prepareStatement(sql); - for(int i = 0; i < statuses.length; i ++){ - int status = statuses[i]; - ps.setInt(i+1, status); - } - ps.setInt(statuses.length +1, limit); - rs = ps.executeQuery(); - while(rs.next()){ - ret.add(convertGlobalTransactionDO(rs)); - } - return ret; - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(rs != null){ - try { - rs.close(); - } catch (SQLException e) { - } - } - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String sql = LogStoreSqls.getInsertGlobalTransactionSQL(globalTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - try{ - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, globalTransactionDO.getXid()); - ps.setLong(2, globalTransactionDO.getTransactionId()); - ps.setInt(3, globalTransactionDO.getStatus()); - ps.setString(4, globalTransactionDO.getApplicationId()); - ps.setString(5, globalTransactionDO.getTransactionServiceGroup()); - ps.setString(6, globalTransactionDO.getTransactionName()); - ps.setInt(7, globalTransactionDO.getTimeout()); - ps.setLong(8, globalTransactionDO.getBeginTime()); - ps.setString(9, globalTransactionDO.getApplicationData()); - return ps.executeUpdate() > 0; - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String sql = LogStoreSqls.getUpdateGlobalTransactionStatusSQL(globalTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - try{ - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setInt(1, globalTransactionDO.getStatus()); - ps.setString(2, globalTransactionDO.getXid()); - return ps.executeUpdate() > 0; - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean deleteGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) { - String sql = LogStoreSqls.getDeleteGlobalTransactionSQL(globalTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - try{ - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, globalTransactionDO.getXid()); - return ps.executeUpdate() > 0; - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public List queryBranchTransactionDO(String xid) { - List rets = new ArrayList<>(); - String sql = LogStoreSqls.getQureyBranchTransaction(brachTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - - ps = conn.prepareStatement(sql); - ps.setString(1, xid); - - ResultSet rs = ps.executeQuery(); - while(rs.next()){ - rets.add(convertBranchTransactionDO(rs)); - } - return rets; - } catch (SQLException e) { - throw new StoreException(e); - } finally { - if (ps != null) { - try { - ps.close(); - } catch (SQLException e) { - } - } - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean insertBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqls.getInsertBranchTransactionSQL(brachTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - try { - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, branchTransactionDO.getXid()); - ps.setLong(2, branchTransactionDO.getTransactionId()); - ps.setLong(3, branchTransactionDO.getBranchId()); - ps.setString(4, branchTransactionDO.getResourceGroupId()); - ps.setString(5, branchTransactionDO.getResourceId()); - ps.setString(6, branchTransactionDO.getLockKey()); - ps.setString(7, branchTransactionDO.getBranchType()); - ps.setInt(8, branchTransactionDO.getStatus()); - ps.setString(9, branchTransactionDO.getClientId()); - ps.setString(10, branchTransactionDO.getApplicationData()); - return ps.executeUpdate() > 0; - } catch (SQLException e) { - throw new StoreException(e); - } finally { - if (ps != null) { - try { - ps.close(); - } catch (SQLException e) { - } - } - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean updateBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqls.getUpdateBranchTransactionStatusSQL(brachTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - try{ - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setInt(1, branchTransactionDO.getStatus()); - ps.setString(2, branchTransactionDO.getXid()); - ps.setLong(3, branchTransactionDO.getBranchId()); - return ps.executeUpdate() > 0; - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Override - public boolean deleteBranchTransactionDO(BranchTransactionDO branchTransactionDO) { - String sql = LogStoreSqls.getDeleteBranchTransactionByBranchIdSQL(brachTable, dbType); - Connection conn = null; - PreparedStatement ps = null; - try{ - conn = logStoreDataSource.getConnection(); - conn.setAutoCommit(true); - ps = conn.prepareStatement(sql); - ps.setString(1, branchTransactionDO.getXid()); - ps.setLong(2, branchTransactionDO.getBranchId()); - return ps.executeUpdate() > 0; - }catch (SQLException e){ - throw new StoreException(e); - }finally { - if(ps != null){ - try { - ps.close(); - } catch (SQLException e) { - } - } - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - - private GlobalTransactionDO convertGlobalTransactionDO(ResultSet rs) throws SQLException { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid(rs.getString("xid")); - globalTransactionDO.setStatus(rs.getInt("status")); - globalTransactionDO.setApplicationId(rs.getString("application_id")); - globalTransactionDO.setBeginTime(rs.getLong("begin_time")); - globalTransactionDO.setTimeout(rs.getInt("timeout")); - globalTransactionDO.setTransactionId(rs.getLong("transaction_id")); - globalTransactionDO.setTransactionName(rs.getString("transaction_name")); - globalTransactionDO.setTransactionServiceGroup(rs.getString("transaction_service_group")); - globalTransactionDO.setApplicationData(rs.getString("application_data")); - globalTransactionDO.setGmtCreate(rs.getTimestamp("gmt_create")); - globalTransactionDO.setGmtModified(rs.getTimestamp("gmt_modified")); - return globalTransactionDO; - } - - private BranchTransactionDO convertBranchTransactionDO(ResultSet rs) throws SQLException { - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setResourceGroupId(rs.getString("resource_group_id")); - branchTransactionDO.setStatus(rs.getInt("status")); - branchTransactionDO.setApplicationData(rs.getString("application_data")); - branchTransactionDO.setClientId(rs.getString("client_id")); - branchTransactionDO.setLockKey(rs.getString("lock_key")); - branchTransactionDO.setXid(rs.getString("xid")); - branchTransactionDO.setResourceId(rs.getString("resource_id")); - branchTransactionDO.setBranchId(rs.getLong("branch_id")); - branchTransactionDO.setBranchType(rs.getString("branch_type")); - branchTransactionDO.setTransactionId(rs.getLong("transaction_id")); - branchTransactionDO.setGmtCreate(rs.getTimestamp("gmt_create")); - branchTransactionDO.setGmtModified(rs.getTimestamp("gmt_modified")); - return branchTransactionDO; - } - - /** - * Sets log store data source. - * - * @param logStoreDataSource the log store data source - */ - public void setLogStoreDataSource(DataSource logStoreDataSource) { - this.logStoreDataSource = logStoreDataSource; - } - - /** - * Sets global table. - * - * @param globalTable the global table - */ - public void setGlobalTable(String globalTable) { - this.globalTable = globalTable; - } - - /** - * Sets brach table. - * - * @param brachTable the brach table - */ - public void setBrachTable(String brachTable) { - this.brachTable = brachTable; - } - - /** - * Sets db type. - * - * @param dbType the db type - */ - public void setDbType(String dbType) { - this.dbType = dbType; - } -} \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/store/db/LogStoreSqls.java b/core/src/main/java/io/seata/core/store/db/LogStoreSqls.java deleted file mode 100644 index 69308324d63..00000000000 --- a/core/src/main/java/io/seata/core/store/db/LogStoreSqls.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - - -import io.seata.common.exception.NotSupportYetException; -import io.seata.core.constants.DBType; - -/** - * database log store SQLs - * - * @author zhangsen - * @data 2019 /4/2 - */ -public class LogStoreSqls { - - /** - * The constant GLOBAL_TABLE_PLACEHOLD. - */ - public static final String GLOBAL_TABLE_PLACEHOLD = " #global_table# "; - - /** - * The constant BRANCH_TABLE_PLACEHOLD. - */ - public static final String BRANCH_TABLE_PLACEHOLD = " #branch_table# "; - - - /** - * The constant PRAMETER_PLACEHOLD. - */ - public static final String PRAMETER_PLACEHOLD = " #PRAMETER_PLACEHOLD# "; - - /** - * The constant ALL_GLOBAL_COLUMNS. - */ - public static final String ALL_GLOBAL_COLUMNS = "xid, transaction_id, status, application_id, transaction_service_group, transaction_name, timeout, begin_time, application_data, gmt_create, gmt_modified "; - - /** - * The constant ALL_BRANCH_COLUMNS. - */ - protected static final String ALL_BRANCH_COLUMNS = "xid, transaction_id, branch_id, resource_group_id, resource_id, lock_key, branch_type, status, client_id, application_data, gmt_create, gmt_modified "; - - /** - * The constant INSERT_GLOBAL_TRANSACTION_MYSQL. - */ - public static final String INSERT_GLOBAL_TRANSACTION_MYSQL = "insert into " + GLOBAL_TABLE_PLACEHOLD + "("+ ALL_GLOBAL_COLUMNS +")" + - "values(?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now()) "; - - /** - * The constant INSERT_GLOBAL_TRANSACTION_ORACLE. - */ - public static final String INSERT_GLOBAL_TRANSACTION_ORACLE = "insert into " + GLOBAL_TABLE_PLACEHOLD + "("+ ALL_GLOBAL_COLUMNS +")" + - "values(?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate, sysdate) "; - - /** - * The constant UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL. - */ - public static final String UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL = "update "+ GLOBAL_TABLE_PLACEHOLD + " set status = ?, gmt_modified = now() where xid = ?"; - - /** - * The constant UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE. - */ - public static final String UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE = "update "+ GLOBAL_TABLE_PLACEHOLD + " set status = ?, gmt_modified = sysdate where xid = ?"; - - /** - * The constant DELETE_GLOBAL_TRANSACTION. - */ - public static final String DELETE_GLOBAL_TRANSACTION = "delete from " + GLOBAL_TABLE_PLACEHOLD + " where xid = ?"; - - /** - * The constant QUERY_GLOBAL_TRANSACTION. - */ - public static final String QUERY_GLOBAL_TRANSACTION = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where xid = ?"; - - - /** - * The constant QUERY_GLOBAL_TRANSACTION_ID. - */ - public static final String QUERY_GLOBAL_TRANSACTION_BY_ID = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where transaction_id = ?"; - - - /** - * The constant QUERY_GLOBAL_TRANSACTION_BY_STATUS. - */ - public static final String QUERY_GLOBAL_TRANSACTION_BY_STATUS = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + - " where status in (" + PRAMETER_PLACEHOLD + ") order by gmt_modified limit ?"; - /** - * The constant QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL. - */ - public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL = "select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where status in (" + - "0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14) order by gmt_modified limit ?"; - - /** - * The constant QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE. - */ - public static final String QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE = "select A.* from ( select "+ALL_GLOBAL_COLUMNS+" from " + GLOBAL_TABLE_PLACEHOLD + " where status in (" + - "0, 2, 3, 4, 5, 6, 7, 8, 10 ,12, 14) order by gmt_modified ) A where ROWNUM <= ?" ; - - - /** - * The constant INSERT_BRANCH_TRANSACTION_MYSQL. - */ - public static final String INSERT_BRANCH_TRANSACTION_MYSQL = "insert into " + BRANCH_TABLE_PLACEHOLD + "("+ ALL_BRANCH_COLUMNS +")" + - "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now())"; - - /** - * The constant INSERT_BRANCH_TRANSACTION_ORACLE. - */ - public static final String INSERT_BRANCH_TRANSACTION_ORACLE = "insert into " + BRANCH_TABLE_PLACEHOLD + "("+ ALL_BRANCH_COLUMNS +")" + - "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate, sysdate)"; - - /** - * The constant UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL. - */ - public static final String UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL = "update "+ BRANCH_TABLE_PLACEHOLD + " set status = ?, gmt_modified = now() where xid = ? and branch_id = ?"; - - /** - * The constant UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE. - */ - public static final String UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE = "update "+ BRANCH_TABLE_PLACEHOLD + " set status = ?, gmt_modified = sysdate where xid = ? and branch_id = ?" ; - - /** - * The constant DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID. - */ - public static final String DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID = "delete from " + BRANCH_TABLE_PLACEHOLD + " where xid = ? and branch_id = ?"; - - /** - * The constant DELETE_BRANCH_TRANSACTION_BY_XID. - */ - public static final String DELETE_BRANCH_TRANSACTION_BY_XID = "delete from " + BRANCH_TABLE_PLACEHOLD + " where xid = ?"; - - /** - * The constant QUREY_BRANCH_TRANSACTION. - */ - public static final String QUREY_BRANCH_TRANSACTION = "select "+ALL_BRANCH_COLUMNS+" from " + BRANCH_TABLE_PLACEHOLD + " where xid = ?"; - - /** - * Get insert global transaction sql string. - * - * @param globalTable the global table - * @param dbType the db type - * @return the string - */ - public static String getInsertGlobalTransactionSQL(String globalTable, String dbType){ - if(DBType.MYSQL.name().equalsIgnoreCase(dbType) - || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) - || DBType.H2.name().equalsIgnoreCase(dbType)){ - return INSERT_GLOBAL_TRANSACTION_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ - return INSERT_GLOBAL_TRANSACTION_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - }else{ - throw new NotSupportYetException("unknown dbType:" + dbType); - } - } - - /** - * Get update global transaction status sql string. - * - * @param globalTable the global table - * @param dbType the db type - * @return the string - */ - public static String getUpdateGlobalTransactionStatusSQL(String globalTable, String dbType){ - if(DBType.MYSQL.name().equalsIgnoreCase(dbType) - || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) - || DBType.H2.name().equalsIgnoreCase(dbType)){ - return UPDATE_GLOBAL_TRANSACTION_STATUS_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ - return UPDATE_GLOBAL_TRANSACTION_STATUS_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - }else{ - throw new NotSupportYetException("unknown dbType:" + dbType); - } - } - - /** - * Get delete global transaction sql string. - * - * @param globalTable the global table - * @param dbType the db type - * @return the string - */ - public static String getDeleteGlobalTransactionSQL(String globalTable, String dbType){ - return DELETE_GLOBAL_TRANSACTION.replace(GLOBAL_TABLE_PLACEHOLD, globalTable ); - } - - /** - * Get query global transaction sql string. - * - * @param globalTable the global table - * @param dbType the db type - * @return the string - */ - public static String getQueryGlobalTransactionSQL(String globalTable, String dbType){ - return QUERY_GLOBAL_TRANSACTION.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - } - - /** - * Get query global transaction sql by transaction id string. - * - * @param globalTable the global table - * @param dbType the db type - * @return the string - */ - public static String getQueryGlobalTransactionSQLByTransactionId(String globalTable, String dbType){ - return QUERY_GLOBAL_TRANSACTION_BY_ID.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - } - - - /** - * Get query global transaction sql by status string. - * - * @param globalTable the global table - * @param dbType the db type - * @param paramsPlaceHolder the params place holder - * @return the string - */ - public static String getQueryGlobalTransactionSQLByStatus(String globalTable, String dbType, String paramsPlaceHolder){ - return QUERY_GLOBAL_TRANSACTION_BY_STATUS.replace(GLOBAL_TABLE_PLACEHOLD, globalTable).replace(PRAMETER_PLACEHOLD, paramsPlaceHolder); - } - - /** - * Get query global transaction for recovery sql string. - * - * @param globalTable the global table - * @param dbType the db type - * @return the string - */ - public static String getQueryGlobalTransactionForRecoverySQL(String globalTable, String dbType){ - if(DBType.MYSQL.name().equalsIgnoreCase(dbType) - || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) - || DBType.H2.name().equalsIgnoreCase(dbType)){ - return QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_MYSQL.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ - return QUERY_GLOBAL_TRANSACTION_FOR_RECOVERY_ORACLE.replace(GLOBAL_TABLE_PLACEHOLD, globalTable); - }else{ - throw new NotSupportYetException("unknown dbType:" + dbType); - } - } - - /** - * Get insert branch transaction sql string. - * - * @param branchTable the branch table - * @param dbType the db type - * @return the string - */ - public static String getInsertBranchTransactionSQL(String branchTable, String dbType){ - if(DBType.MYSQL.name().equalsIgnoreCase(dbType) - || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) - || DBType.H2.name().equalsIgnoreCase(dbType)){ - return INSERT_BRANCH_TRANSACTION_MYSQL.replace(BRANCH_TABLE_PLACEHOLD, branchTable); - }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ - return INSERT_BRANCH_TRANSACTION_ORACLE.replace(BRANCH_TABLE_PLACEHOLD, branchTable); - }else{ - throw new NotSupportYetException("unknown dbType:" + dbType); - } - } - - /** - * Get update branch transaction status sql string. - * - * @param branchTable the branch table - * @param dbType the db type - * @return the string - */ - public static String getUpdateBranchTransactionStatusSQL(String branchTable, String dbType){ - if(DBType.MYSQL.name().equalsIgnoreCase(dbType) - || DBType.OCEANBASE.name().equalsIgnoreCase(dbType) - || DBType.H2.name().equalsIgnoreCase(dbType)){ - return UPDATE_BRANCH_TRANSACTION_STATUS_MYSQL.replace(BRANCH_TABLE_PLACEHOLD, branchTable); - }else if(DBType.ORACLE.name().equalsIgnoreCase(dbType)){ - return UPDATE_BRANCH_TRANSACTION_STATUS_ORACLE.replace(BRANCH_TABLE_PLACEHOLD, branchTable); - }else{ - throw new NotSupportYetException("unknown dbType:" + dbType); - } - } - - /** - * Get delete branch transaction by branch id sql string. - * - * @param branchTable the branch table - * @param dbType the db type - * @return the string - */ - public static String getDeleteBranchTransactionByBranchIdSQL(String branchTable, String dbType){ - return DELETE_BRANCH_TRANSACTION_BY_BRANCH_ID.replace(BRANCH_TABLE_PLACEHOLD, branchTable); - } - - /** - * Get delete branch transaction by x id string. - * - * @param branchTable the branch table - * @param dbType the db type - * @return the string - */ - public static String getDeleteBranchTransactionByXId(String branchTable, String dbType){ - return DELETE_BRANCH_TRANSACTION_BY_XID.replace(BRANCH_TABLE_PLACEHOLD, branchTable); - } - - /** - * Get qurey branch transaction string. - * - * @param branchTable the branch table - * @param dbType the db type - * @return the string - */ - public static String getQureyBranchTransaction(String branchTable, String dbType){ - return QUREY_BRANCH_TRANSACTION.replace(BRANCH_TABLE_PLACEHOLD, branchTable); - } -} \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/io.seata.core.store.LockStore b/core/src/main/resources/META-INF/services/io.seata.core.store.LockStore deleted file mode 100644 index bd6ff3d994a..00000000000 --- a/core/src/main/resources/META-INF/services/io.seata.core.store.LockStore +++ /dev/null @@ -1 +0,0 @@ -io.seata.core.store.db.LockStoreDataBaseDAO \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/io.seata.core.store.LogStore b/core/src/main/resources/META-INF/services/io.seata.core.store.LogStore deleted file mode 100644 index f95309566f9..00000000000 --- a/core/src/main/resources/META-INF/services/io.seata.core.store.LogStore +++ /dev/null @@ -1 +0,0 @@ -io.seata.core.store.db.LogStoreDataBaseDAO \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java b/core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java deleted file mode 100644 index d76a6c79dc4..00000000000 --- a/core/src/test/java/io/seata/core/protocol/RegisterTMRequestTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.protocol; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import io.netty.buffer.ByteBuf; -import static io.netty.buffer.Unpooled.buffer; - -/** - * RegisterTMRequest Test - * - * @author kaitithoma - * @author Danaykap - * - * @date 2019/05/13 - * - */ - -public class RegisterTMRequestTest { - - private static RegisterTMRequest registerTMRequest; - private static AbstractIdentifyRequest air; - private static final String APP_ID = "applicationId"; - private static final String TSG = "transactionServiceGroup"; - private static final String ED = "extraData"; - private static final short TYPE_CODE = 101; - private static final ByteBuf BB = buffer(128); - - /** Constructor without arguments **/ - @BeforeAll - public static void setupNull() { - registerTMRequest = new RegisterTMRequest(); - air = Mockito.mock( - AbstractIdentifyRequest.class, - Mockito.CALLS_REAL_METHODS); - } - - /** Constructor with arguments **/ - @BeforeAll - public static void setupWithValues() { - registerTMRequest = new RegisterTMRequest(APP_ID, TSG, ED); - air = Mockito.mock( - AbstractIdentifyRequest.class, - Mockito.CALLS_REAL_METHODS); - } - - /** Test get type code **/ - @Test - public void testGetTypeCode() { - Assertions.assertEquals(TYPE_CODE, registerTMRequest.getTypeCode()); - } - - /** - * Test toString having all the parameters initialized to null - */ - @Test - public void testToStringNullValues() { - Assertions.assertEquals("RegisterTMRequest{" + "applicationId='" + null + '\'' + ", transactionServiceGroup='" - + null + '\'' + '}', registerTMRequest.toString()); - } - - /** - * Test decode method with empty parameter - */ - @Test - public void testDecodeEmpty() { - BB.clear(); - Assertions.assertFalse(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeLessThanTwo() { - BB.clear(); - for (int i = 0; i < 2; i++) { - BB.writeShort(i); - } - Assertions.assertFalse(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeMoreThanThree() { - BB.clear(); - for (int i = 0; i < 3; i++) { - BB.writeShort(i); - } - Assertions.assertFalse(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeLessThanFour() { - BB.clear(); - for (int i = 0; i < 4; i++) { - BB.writeShort(i); - } - Assertions.assertFalse(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeMoreLessThanOne() { - BB.clear(); - for (int i = 0; i < 1; i++) { - BB.writeShort(i); - } - Assertions.assertFalse(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeMoreLessThanFourWithZero() { - BB.clear(); - for (int i = 0; i < 4; i++) { - BB.writeZero(i); - } - Assertions.assertFalse(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeFalseLessThanTwoWithDifferentReadable() { - BB.clear(); - for (int i = 0; i < 1; i++) { - BB.writeZero(i); - } - for (int i = 1; i < 2; i++) { - BB.writeShort(i); - } - Assertions.assertFalse(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeTrueLessThanFive() { - BB.clear(); - for (int i = 0; i < 4; i++) { - BB.writeZero(i); - } - for (int i = 4; i < 5; i++) { - BB.writeShort(i); - } - Assertions.assertTrue(air.decode(BB)); - } - - /** - * Test decode method with initialized parameter - */ - @Test - public void testDecodeTrueLessThanSixteen() { - BB.clear(); - for (int i = 0; i < 15; i++) { - BB.writeZero(i); - } - for (int i = 15; i < 16; i++) { - BB.writeShort(i); - } - Assertions.assertTrue(air.decode(BB)); - } - -} diff --git a/core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java b/core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java deleted file mode 100644 index eee248eb8cd..00000000000 --- a/core/src/test/java/io/seata/core/store/db/DataBaseLockStoreDAOTest.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - -import io.seata.core.store.LockDO; -import org.apache.commons.dbcp.BasicDataSource; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; - -/** - * @author zhangsen - * @data 2019/4/26 - */ -public class DataBaseLockStoreDAOTest { - - static LockStoreDataBaseDAO dataBaseLockStoreDAO = null; - - static BasicDataSource dataSource = null; - - @BeforeAll - public static void start(){ - dataSource = new BasicDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setUrl("jdbc:h2:./db_store/lock"); - dataSource.setUsername("sa"); - dataSource.setPassword(""); - - dataBaseLockStoreDAO = new LockStoreDataBaseDAO(dataSource); - dataBaseLockStoreDAO.setDbType("h2"); - dataBaseLockStoreDAO.setLockTable("lock_table"); - - prepareTable(dataSource); - } - - private static void prepareTable(BasicDataSource dataSource) { - Connection conn = null; - try { - conn = dataSource.getConnection(); - Statement s = conn.createStatement(); - try { - s.execute("drop table lock_table"); - } catch (Exception e) { - } - s.execute("CREATE TABLE lock_table ( xid varchar(96) , transaction_id long , branch_id long, resource_id varchar(32) ,table_name varchar(32) ,pk varchar(32) , row_key varchar(128) primary key not null, gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); - System.out.println("create table lock_table success."); - - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - } - } - - @Test - public void test_acquireLocks() throws SQLException { - List lockDOs = new ArrayList<>(); - for(int i = 0; i < 3; i++){ - LockDO lock = new LockDO(); - lock.setResourceId("abc"); - lock.setXid("abc-123:123"); - lock.setTransactionId(123L); - lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); - lock.setPk(String.valueOf(i)); - lock.setTableName("t"); - lockDOs.add(lock); - } - - boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); - Assertions.assertTrue(ret); - - String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - - Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); - - } - - - @Test - public void test_re_acquireLocks() throws SQLException { - List lockDOs = new ArrayList<>(); - for(int i = 0; i < 3; i++){ - LockDO lock = new LockDO(); - lock.setResourceId("abc"); - lock.setXid("abc-123:123"); - lock.setTransactionId(123L); - lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); - lock.setPk(String.valueOf(i)); - lock.setTableName("t"); - lockDOs.add(lock); - } - - boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); - Assertions.assertTrue(ret); - - String sql = "select * from lock_table where xid = 'abc-123:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - - //lock again - Assertions.assertTrue(dataBaseLockStoreDAO.acquireLock(lockDOs)); - - Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); - - } - - @Test - public void tes_unLocks() throws SQLException { - List lockDOs = new ArrayList<>(); - for(int i = 0; i < 3; i++){ - LockDO lock = new LockDO(); - lock.setResourceId("abc"); - lock.setXid("abc-456:123"); - lock.setTransactionId(123L); - lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); - lock.setPk(String.valueOf(i)); - lock.setTableName("t"); - lockDOs.add(lock); - } - - boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); - Assertions.assertTrue(ret); - - String sql = "select * from lock_table where xid = 'abc-456:123' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - rs.close(); - - //unlock - Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); - - rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(false); - }else { - Assertions.assertTrue(true); - } - - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - - - } - - - @Test - public void test_isLockable_can(){ - List lockDOs = new ArrayList<>(); - for(int i = 0; i < 3; i++){ - LockDO lock = new LockDO(); - lock.setResourceId("abc"); - lock.setXid("abc-678:123"); - lock.setTransactionId(123L); - lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); - lock.setPk(String.valueOf(i)); - lock.setTableName("t"); - lockDOs.add(lock); - } - - boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); - Assertions.assertTrue(ret); - - //unlock - Assertions.assertTrue(dataBaseLockStoreDAO.unLock(lockDOs)); - } - - @Test - public void test_isLockable_cannot() throws SQLException { - List lockDOs = new ArrayList<>(); - for(int i = 0; i < 3; i++){ - LockDO lock = new LockDO(); - lock.setResourceId("abc"); - lock.setXid("abc-123:222"); - lock.setTransactionId(222L); - lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); - lock.setPk(String.valueOf(i)); - lock.setTableName("t"); - lockDOs.add(lock); - } - - boolean ret = dataBaseLockStoreDAO.acquireLock(lockDOs); - Assertions.assertTrue(ret); - - String sql = "select * from lock_table where xid = 'abc-123:222' and table_name = 't' and row_key in ('abc-0','abc-1','abc-2')" ; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - - List lockDOs_2 = new ArrayList<>(); - for(int i = 0; i < 3; i++){ - LockDO lock = new LockDO(); - lock.setResourceId("abc"); - lock.setXid("abc-123:333"); - lock.setTransactionId(333L); - lock.setBranchId((long) i); - lock.setRowKey("abc-"+i); - lock.setPk(String.valueOf(i)); - lock.setTableName("t"); - lockDOs_2.add(lock); - } - - boolean ret2 = dataBaseLockStoreDAO.acquireLock(lockDOs_2); - Assertions.assertTrue(!ret2); - - } - - - -} \ No newline at end of file diff --git a/core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java b/core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java deleted file mode 100644 index 12aaf5259ea..00000000000 --- a/core/src/test/java/io/seata/core/store/db/LogStoreDataBaseDAOTest.java +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.core.store.db; - -import io.seata.common.util.CollectionUtils; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import org.apache.commons.dbcp.BasicDataSource; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; - - -/** - * @author zhangsen - * @data 2019/4/26 - */ -public class LogStoreDataBaseDAOTest { - - static LogStoreDataBaseDAO logStoreDataBaseDAO = null; - - static BasicDataSource dataSource = null; - - @BeforeAll - public static void start(){ - dataSource = new BasicDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setUrl("jdbc:h2:./db_store/log"); - dataSource.setUsername("sa"); - dataSource.setPassword(""); - - logStoreDataBaseDAO = new LogStoreDataBaseDAO(dataSource); - logStoreDataBaseDAO.setDbType("h2"); - logStoreDataBaseDAO.setGlobalTable("global_table"); - logStoreDataBaseDAO.setBrachTable("branch_table"); - - prepareTable(dataSource); - } - - private static void prepareTable(BasicDataSource dataSource) { - Connection conn = null; - try { - conn = dataSource.getConnection(); - Statement s = conn.createStatement(); - try { - s.execute("drop table global_table"); - } catch (Exception e) { - } -// xid, transaction_id, status, application_id, transaction_service_group, transaction_name, timeout, begin_time, application_data, gmt_create, gmt_modified - s.execute("CREATE TABLE global_table ( xid varchar(96) primary key, transaction_id long , STATUS int, application_id varchar(32), transaction_service_group varchar(32) ,transaction_name varchar(32) ,timeout int, begin_time long, application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); - System.out.println("create table global_table success."); - - try { - s.execute("drop table branch_table"); - } catch (Exception e) { - } -// xid, transaction_id, branch_id, resource_group_id, resource_id, lock_key, branch_type, status, client_id, application_data, gmt_create, gmt_modified - s.execute("CREATE TABLE branch_table ( xid varchar(96), transaction_id long , branch_id long primary key, resource_group_id varchar(32), resource_id varchar(32) ,lock_key varchar(64) ,branch_type varchar(32) , status int , client_id varchar(128), application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); - System.out.println("create table branch_table success."); - - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - } - } - - @Test - public void queryGlobalTransactionDO_by_xid() throws SQLException { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:978786"); - globalTransactionDO.setApplicationData("abc=87867978"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(143546567); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - - - GlobalTransactionDO globalTransactionDO_db = logStoreDataBaseDAO.queryGlobalTransactionDO("abc-123:978786"); - Assertions.assertNotNull(globalTransactionDO_db); - - Assertions.assertEquals(globalTransactionDO_db.getBeginTime(), globalTransactionDO_db.getBeginTime()); - Assertions.assertEquals(globalTransactionDO_db.getTransactionName(), globalTransactionDO_db.getTransactionName()); - Assertions.assertEquals(globalTransactionDO_db.getTransactionId(), globalTransactionDO_db.getTransactionId()); - Assertions.assertEquals(globalTransactionDO_db.getStatus(), globalTransactionDO_db.getStatus()); - Assertions.assertEquals(globalTransactionDO_db.getTimeout(), globalTransactionDO_db.getTimeout()); - Assertions.assertEquals(globalTransactionDO_db.getTransactionServiceGroup(), globalTransactionDO_db.getTransactionServiceGroup()); - Assertions.assertEquals(globalTransactionDO_db.getApplicationId(), globalTransactionDO_db.getApplicationId()); - Assertions.assertNotNull(globalTransactionDO_db.getGmtCreate()); - Assertions.assertNotNull(globalTransactionDO_db.getGmtModified()); - - - String delSql = "delete from global_table where xid= 'abc-123:978786'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - //delete - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - - } - - @Test - public void queryGlobalTransactionDO_by_transaction_id() throws SQLException { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:676787978"); - globalTransactionDO.setApplicationData("abc=234356"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(867978970); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - - GlobalTransactionDO globalTransactionDO_db = logStoreDataBaseDAO.queryGlobalTransactionDO(867978970L); - Assertions.assertNotNull(globalTransactionDO_db); - - Assertions.assertEquals(globalTransactionDO_db.getXid(), globalTransactionDO_db.getXid()); - Assertions.assertEquals(globalTransactionDO_db.getBeginTime(), globalTransactionDO_db.getBeginTime()); - Assertions.assertEquals(globalTransactionDO_db.getTransactionName(), globalTransactionDO_db.getTransactionName()); - Assertions.assertEquals(globalTransactionDO_db.getTransactionId(), globalTransactionDO_db.getTransactionId()); - Assertions.assertEquals(globalTransactionDO_db.getStatus(), globalTransactionDO_db.getStatus()); - Assertions.assertEquals(globalTransactionDO_db.getTimeout(), globalTransactionDO_db.getTimeout()); - Assertions.assertEquals(globalTransactionDO_db.getTransactionServiceGroup(), globalTransactionDO_db.getTransactionServiceGroup()); - Assertions.assertEquals(globalTransactionDO_db.getApplicationId(), globalTransactionDO_db.getApplicationId()); - Assertions.assertNotNull(globalTransactionDO_db.getGmtCreate()); - Assertions.assertNotNull(globalTransactionDO_db.getGmtModified()); - - String delSql = "delete from global_table where xid= 'abc-123:978786'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - //delete - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - - } - - @Test - public void queryGlobalTransactionDO_by_statuses() throws SQLException { - { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:1267"); - globalTransactionDO.setApplicationData("abc=234356"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(867978970); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - Assertions.assertTrue(logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO)); - } - { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:6978"); - globalTransactionDO.setApplicationData("abc=87867978"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(143546567); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(2); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - } - { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:5657"); - globalTransactionDO.setApplicationData("abc=5454"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(12345); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - } - - List globalTransactionDOs = logStoreDataBaseDAO.queryGlobalTransactionDO(new int[]{1}, 10); - Assertions.assertNotNull(globalTransactionDOs); - Assertions.assertEquals(2, globalTransactionDOs.size()); - - if("abc-123:5657".equals(globalTransactionDOs.get(0).getXid()) && "abc-123:1267".equals(globalTransactionDOs.get(1).getXid())){ - Assertions.assertTrue(true); - }else if("abc-123:5657".equals(globalTransactionDOs.get(1).getXid()) && "abc-123:1267".equals(globalTransactionDOs.get(0).getXid())){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - - String delSql = "delete from global_table where xid in ('abc-123:1267', 'abc-123:6978', 'abc-123:5657')"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void queryGlobalTransactionDO_by_statuses_limit() throws SQLException { - { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:1267"); - globalTransactionDO.setApplicationData("abc=234356"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(867978970); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - Assertions.assertTrue(logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO)); - } - { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:6978"); - globalTransactionDO.setApplicationData("abc=87867978"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(143546567); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(2); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - } - { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:5657"); - globalTransactionDO.setApplicationData("abc=5454"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(12345); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - } - - List globalTransactionDOs = logStoreDataBaseDAO.queryGlobalTransactionDO(new int[]{1}, 1); - Assertions.assertNotNull(globalTransactionDOs); - Assertions.assertEquals(1, globalTransactionDOs.size()); - - if("abc-123:1267".equals(globalTransactionDOs.get(0).getXid())){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - - String delSql = "delete from global_table where xid in ('abc-123:1267', 'abc-123:6978', 'abc-123:5657')"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - - } - - @Test - public void insertGlobalTransactionDO() throws SQLException { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:333"); - globalTransactionDO.setApplicationData("abc=5454"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(12345); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - - String sql = "select * from global_table where xid= 'abc-123:333'"; - String delSql = "delete from global_table where xid= 'abc-123:333'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else{ - Assertions.assertTrue(false); - } - - conn.createStatement().execute(delSql); - - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void updateGlobalTransactionDO() throws SQLException { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:222"); - globalTransactionDO.setApplicationData("abc=5454"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(12345); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - - String sql = "select * from global_table where xid= 'abc-123:222'"; - String delSql = "delete from global_table where xid= 'abc-123:222'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - Assertions.assertEquals(1, rs.getInt("status")); - }else{ - Assertions.assertTrue(false); - } - rs.close(); - - //update - globalTransactionDO.setStatus(2); - Assertions.assertTrue(logStoreDataBaseDAO.updateGlobalTransactionDO(globalTransactionDO)); - - rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - Assertions.assertEquals(2, rs.getInt("status")); - }else{ - Assertions.assertTrue(false); - } - rs.close(); - - //delete - conn.createStatement().execute(delSql); - - }finally { - if(conn != null){ - conn.close(); - } - } - - } - - @Test - public void deleteGlobalTransactionDO() throws SQLException { - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid("abc-123:555"); - globalTransactionDO.setApplicationData("abc=5454"); - globalTransactionDO.setTransactionServiceGroup("abc"); - globalTransactionDO.setTransactionName("test"); - globalTransactionDO.setTransactionId(12345); - globalTransactionDO.setTimeout(20); - globalTransactionDO.setBeginTime(System.currentTimeMillis()); - globalTransactionDO.setApplicationId("test"); - globalTransactionDO.setStatus(1); - - boolean ret = logStoreDataBaseDAO.insertGlobalTransactionDO(globalTransactionDO); - Assertions.assertTrue(ret); - - //delete - Assertions.assertTrue(logStoreDataBaseDAO.deleteGlobalTransactionDO(globalTransactionDO)); - - //check - - String sql = "select * from global_table where xid= 'abc-123:555'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(false); - }else{ - Assertions.assertTrue(true); - } - rs.close(); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void queryBranchTransactionDO() throws SQLException { - { - //creata data for test - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setResourceId("qqqq"); - branchTransactionDO.setXid("abc-123:6789"); - branchTransactionDO.setTransactionId(24234235); - branchTransactionDO.setBranchId(345465676); - branchTransactionDO.setBranchType("TCC"); - branchTransactionDO.setResourceGroupId("abc"); - branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); - branchTransactionDO.setResourceGroupId("a"); - branchTransactionDO.setClientId("1.1.1.1"); - branchTransactionDO.setStatus(1); - branchTransactionDO.setApplicationData("abc=123"); - branchTransactionDO.setResourceGroupId("test"); - - boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); - Assertions.assertTrue(ret); - } - { - //creata data for test - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setResourceId("qqqq"); - branchTransactionDO.setXid("abc-123:6789"); - branchTransactionDO.setTransactionId(24234235); - branchTransactionDO.setBranchId(78563453); - branchTransactionDO.setBranchType("TCC"); - branchTransactionDO.setResourceGroupId("abc"); - branchTransactionDO.setLockKey("t:6;t2:7"); - branchTransactionDO.setResourceGroupId("a"); - branchTransactionDO.setClientId("1.1.1.1"); - branchTransactionDO.setStatus(1); - branchTransactionDO.setApplicationData("abc=123"); - branchTransactionDO.setResourceGroupId("test"); - - boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); - Assertions.assertTrue(ret); - } - - List rets = logStoreDataBaseDAO.queryBranchTransactionDO("abc-123:6789"); - Assertions.assertTrue(CollectionUtils.isNotEmpty(rets)); - Assertions.assertEquals(2, rets.size()); - - if(78563453 == rets.get(0).getBranchId() && 345465676 == rets.get(1).getBranchId()){ - Assertions.assertTrue(true); - }else if(78563453 == rets.get(1).getBranchId() && 345465676 == rets.get(0).getBranchId()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - - String delSql = "delete from branch_table where xid= 'abc-123:6789' "; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - - conn.createStatement().execute(delSql); - - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void insertBranchTransactionDO() throws SQLException { - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setResourceId("qqqq"); - branchTransactionDO.setXid("abc-123:7777"); - branchTransactionDO.setTransactionId(1285343); - branchTransactionDO.setBranchId(1234508); - branchTransactionDO.setBranchType("TCC"); - branchTransactionDO.setResourceGroupId("abc"); - branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); - branchTransactionDO.setResourceGroupId("a"); - branchTransactionDO.setClientId("1.1.1.1"); - branchTransactionDO.setStatus(1); - branchTransactionDO.setApplicationData("abc=123"); - branchTransactionDO.setResourceGroupId("test"); - - boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); - Assertions.assertTrue(ret); - - - String sql = "select * from branch_table where xid= 'abc-123:7777' and branch_id = 1234508"; - String delSql = "delete from branch_table where xid= 'abc-123:7777' and branch_id = 1234508"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - - } - - @Test - public void updateBranchTransactionDO() throws SQLException { - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setResourceId("qqqq"); - branchTransactionDO.setXid("abc-123:8888"); - branchTransactionDO.setTransactionId(1285343); - branchTransactionDO.setBranchId(343434318); - branchTransactionDO.setBranchType("TCC"); - branchTransactionDO.setResourceGroupId("abc"); - branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); - branchTransactionDO.setResourceGroupId("a"); - branchTransactionDO.setClientId("1.1.1.1"); - branchTransactionDO.setStatus(1); - branchTransactionDO.setApplicationData("abc=123"); - branchTransactionDO.setResourceGroupId("test"); - - boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); - Assertions.assertTrue(ret); - - branchTransactionDO.setStatus(3); - Assertions.assertTrue(logStoreDataBaseDAO.updateBranchTransactionDO(branchTransactionDO)); - - String sql = "select * from branch_table where xid= 'abc-123:8888' and branch_id = 343434318"; - String delSql = "delete from branch_table where xid= 'abc-123:8888' and branch_id = 343434318"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - Assertions.assertEquals(3, rs.getInt("status")); - }else { - Assertions.assertTrue(false); - } - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void deleteBranchTransactionDO() throws SQLException { - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setResourceId("qqqq"); - branchTransactionDO.setXid("abc-123:9999"); - branchTransactionDO.setTransactionId(1285343); - branchTransactionDO.setBranchId(34567798); - branchTransactionDO.setBranchType("TCC"); - branchTransactionDO.setResourceGroupId("abc"); - branchTransactionDO.setLockKey("t:1,2,3;t2,4,5,6"); - branchTransactionDO.setResourceGroupId("a"); - branchTransactionDO.setClientId("1.1.1.1"); - branchTransactionDO.setStatus(1); - branchTransactionDO.setApplicationData("abc=123"); - branchTransactionDO.setResourceGroupId("test"); - - boolean ret = logStoreDataBaseDAO.insertBranchTransactionDO(branchTransactionDO); - Assertions.assertTrue(ret); - - - String sql = "select * from branch_table where xid= 'abc-123:9999' and branch_id = 34567798"; - String delSql = "delete from branch_table where xid= 'abc-123:9999' and branch_id = 34567798"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - rs.close(); - - //delete - logStoreDataBaseDAO.deleteBranchTransactionDO(branchTransactionDO); - - rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(false); - }else { - Assertions.assertTrue(true); - } - rs.close(); - - }finally { - if(conn != null){ - conn.close(); - } - } - } - -} \ No newline at end of file diff --git a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java deleted file mode 100644 index 663234beea1..00000000000 --- a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.config; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -/** - * @author Geng Zhang - */ -class ConfigurationFactoryTest { - - @Test - void getInstance() { - Configuration configuration = ConfigurationFactory.getInstance(); - // check singleton - Assertions.assertEquals(configuration, ConfigurationFactory.getInstance()); - } -} \ No newline at end of file diff --git a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java index ceedb26bd64..8687246b90f 100644 --- a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java +++ b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryProvider.java @@ -16,6 +16,7 @@ package io.seata.discovery.registry.eureka; import io.seata.common.loader.LoadLevel; +import io.seata.discovery.registry.RegistryProvider; import io.seata.discovery.registry.RegistryService; import io.seata.discovery.registry.RegistryProvider; diff --git a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java index d201ce29c22..1acd0db7f7e 100644 --- a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java +++ b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryProvider.java @@ -16,6 +16,7 @@ package io.seata.discovery.registry.nacos; import io.seata.common.loader.LoadLevel; +import io.seata.discovery.registry.RegistryProvider; import io.seata.discovery.registry.RegistryService; import io.seata.discovery.registry.RegistryProvider; diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java index 10bd29dcae9..4585a45b092 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryProvider.java @@ -18,6 +18,8 @@ import io.seata.common.loader.LoadLevel; import io.seata.discovery.registry.RegistryProvider; import io.seata.discovery.registry.RegistryService; +import io.seata.discovery.registry.RegistryProvider; +import io.seata.discovery.registry.RegistryService; /** * @author xingfudeshi@gmail.com diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java index 1ea76541b20..9c1d87a8810 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java @@ -34,6 +34,7 @@ import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; +import io.seata.discovery.registry.RegistryService; import io.seata.discovery.registry.RegistryService; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; diff --git a/pom.xml b/pom.xml index d657ed812a4..e3628dda535 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ - 0.6.0 + 0.5.2 1.8 @@ -107,7 +107,6 @@ 2.23.4 3.12.2 1.4.2 - @@ -143,6 +142,7 @@ test + diff --git a/rm-datasource/pom.xml b/rm-datasource/pom.xml index 3b1a0435f45..8ab21440bb4 100644 --- a/rm-datasource/pom.xml +++ b/rm-datasource/pom.xml @@ -48,17 +48,6 @@ caffeine - - commons-dbcp - commons-dbcp - test - - - com.h2database - h2 - test - - diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java index 40adc924fa6..b835dc354ab 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AbstractPreparedStatementProxy.java @@ -37,6 +37,7 @@ import java.util.Calendar; import java.util.List; +import io.seata.rm.datasource.sql.struct.Null; import io.seata.rm.datasource.sql.struct.Null; /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java index dd5f1baa2c3..f6076f88204 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java @@ -178,7 +178,7 @@ private void doBranchCommits() { int maxSize = xids.size() > branchIds.size() ? xids.size() : branchIds.size(); if(maxSize == UNDOLOG_DELETE_LIMIT_SIZE){ try { - UndoLogManager.batchDeleteUndoLog(xids, branchIds, conn); + UndoLogManager.batchDeleteUndoLog(xids, branchIds, UNDOLOG_DELETE_LIMIT_SIZE, conn); } catch (Exception ex) { LOGGER.warn("Failed to batch delete undo log [" + branchIds + "/" + xids + "]", ex); } @@ -192,7 +192,7 @@ private void doBranchCommits() { } try { - UndoLogManager.batchDeleteUndoLog(xids, branchIds, conn); + UndoLogManager.batchDeleteUndoLog(xids, branchIds, UNDOLOG_DELETE_LIMIT_SIZE, conn); }catch (Exception ex) { LOGGER.warn("Failed to batch delete undo log [" + branchIds + "/" + xids + "]", ex); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java index 492d59be5f2..5279ad772d7 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/PreparedStatementProxy.java @@ -20,6 +20,8 @@ import java.sql.SQLException; import java.util.ArrayList; +import io.seata.rm.datasource.exec.ExecuteTemplate; +import io.seata.rm.datasource.exec.StatementCallback; import io.seata.rm.datasource.exec.ExecuteTemplate; import io.seata.rm.datasource.exec.StatementCallback; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java index 955fc81c058..e0b1eb7ab68 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/StatementProxy.java @@ -19,6 +19,8 @@ import java.sql.SQLException; import java.sql.Statement; +import io.seata.rm.datasource.exec.ExecuteTemplate; +import io.seata.rm.datasource.exec.StatementCallback; import io.seata.rm.datasource.exec.ExecuteTemplate; import io.seata.rm.datasource.exec.StatementCallback; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java index 26507eb74f3..6a3f3f848b5 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/DeleteExecutor.java @@ -29,6 +29,8 @@ import io.seata.rm.datasource.sql.SQLRecognizer; import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; +import io.seata.rm.datasource.undo.KeywordChecker; +import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.rm.datasource.undo.KeywordChecker; import io.seata.rm.datasource.undo.KeywordCheckerFactory; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java index 26d87cd1d38..be6537bfe12 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/WhereRecognizer.java @@ -17,6 +17,7 @@ import java.util.ArrayList; +import io.seata.rm.datasource.ParametersHolder; import io.seata.rm.datasource.ParametersHolder; /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java index 36f14f97203..779da87c8d1 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java @@ -15,25 +15,16 @@ */ package io.seata.rm.datasource.undo; -import com.alibaba.fastjson.JSON; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; + import io.seata.rm.datasource.DataCompareUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.KeyType; import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; import io.seata.rm.datasource.sql.struct.TableRecords; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; /** * The type Abstract undo executor. @@ -43,24 +34,6 @@ */ public abstract class AbstractUndoExecutor { - /** - * Logger for AbstractUndoExecutor - **/ - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractUndoExecutor.class); - - /** - * template of check sql - * - * TODO support multiple primary key - */ - private static final String CHECK_SQL_TEMPLATE = "SELECT * FROM %s WHERE %s in (%s)"; - - /** - * Switch of undo data validation - */ - public static final boolean IS_UNDO_DATA_VALIDATION_ENABLE = ConfigurationFactory.getInstance() - .getBoolean(ConfigurationKeys.TRANSACTION_UNOD_DATA_VALIDATION, true); - /** * The Sql undo log. */ @@ -99,10 +72,11 @@ public SQLUndoLog getSqlUndoLog() { */ public void executeOn(Connection conn) throws SQLException { - if (IS_UNDO_DATA_VALIDATION_ENABLE && !dataValidationAndGoOn(conn)) { + // no need undo if the before data snapshot is equivalent to the after data snapshot. + if (DataCompareUtils.isRecordsEquals(sqlUndoLog.getBeforeImage(), sqlUndoLog.getAfterImage())) { return; } - + dataValidation(conn); try { String undoSQL = buildUndoSQL(); @@ -171,125 +145,9 @@ protected void undoPrepare(PreparedStatement undoPST, ArrayList undoValue * Data validation. * * @param conn the conn - * @return return true if data validation is ok and need continue undo, and return false if no need continue undo. - * @throws SQLException the sql exception such as has dirty data - */ - protected boolean dataValidationAndGoOn(Connection conn) throws SQLException { - - TableRecords beforeRecords = sqlUndoLog.getBeforeImage(); - TableRecords afterRecords = sqlUndoLog.getAfterImage(); - - // Compare current data with before data - // No need undo if the before data snapshot is equivalent to the after data snapshot. - if (DataCompareUtils.isRecordsEquals(beforeRecords, afterRecords)) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Stop rollback because there is no data change " + - "between the before data snapshot and the after data snapshot."); - } - // no need continue undo. - return false; - } - - // Validate if data is dirty. - TableRecords currentRecords = queryCurrentRecords(conn); - // compare with current data and after image. - if (!DataCompareUtils.isRecordsEquals(afterRecords, currentRecords)) { - - // If current data is not equivalent to the after data, then compare the current data with the before - // data, too. No need continue to undo if current data is equivalent to the before data snapshot - if (DataCompareUtils.isRecordsEquals(beforeRecords, currentRecords)) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Stop rollback because there is no data change " + - "between the before data snapshot and the current data snapshot."); - } - // no need continue undo. - return false; - } else { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("check dirty datas failed, old and new data are not equal," + - "tableName:[" + sqlUndoLog.getTableName() + "]," + - "oldRows:[" + JSON.toJSONString(afterRecords.getRows()) + "]," + - "newRows:[" + JSON.toJSONString(currentRecords.getRows()) + "]."); - } - throw new SQLException("Has dirty records when undo."); - } - } - return true; - } - - /** - * Query current records. - * - * @param conn the conn - * @return the table records * @throws SQLException the sql exception */ - protected TableRecords queryCurrentRecords(Connection conn) throws SQLException { - TableRecords undoRecords = getUndoRows(); - TableMeta tableMeta = undoRecords.getTableMeta(); - String pkName = tableMeta.getPkName(); - int pkType = tableMeta.getColumnMeta(pkName).getDataType(); - - // pares pk values - Object[] pkValues = parsePkValues(getUndoRows()); - if (pkValues.length == 0) { - return TableRecords.empty(tableMeta); - } - StringBuffer replace = new StringBuffer(); - for (int i = 0; i < pkValues.length; i++) { - replace.append("?,"); - } - // build check sql - String checkSQL = String.format(CHECK_SQL_TEMPLATE, sqlUndoLog.getTableName(), pkName, - replace.substring(0, replace.length() - 1)); - - PreparedStatement statement = null; - ResultSet checkSet = null; - TableRecords currentRecords; - try { - statement = conn.prepareStatement(checkSQL); - for (int i = 1; i <= pkValues.length; i++) { - statement.setObject(i, pkValues[i - 1], pkType); - } - checkSet = statement.executeQuery(); - currentRecords = TableRecords.buildRecords(tableMeta, checkSet); - } finally { - if (checkSet != null) { - try { - checkSet.close(); - } catch (Exception e) { - } - } - if (statement != null) { - try { - statement.close(); - } catch (Exception e) { - } - } - } - return currentRecords; - } - - /** - * Parse pk values object [ ]. - * - * @param records the records - * @return the object [ ] - */ - protected Object[] parsePkValues(TableRecords records) { - String pkName = records.getTableMeta().getPkName(); - List undoRows = records.getRows(); - Object[] pkValues = new Object[undoRows.size()]; - for (int i = 0; i < undoRows.size(); i++) { - List fields = undoRows.get(i).getFields(); - if (fields != null) { - for (Field field : fields) { - if (StringUtils.equalsIgnoreCase(pkName, field.getName())) { - pkValues[i] = field.getValue(); - } - } - } - } - return pkValues; + protected void dataValidation(Connection conn) throws SQLException { + // Validate if data is dirty. } } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java index deadf563778..ab278f2e71f 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogManager.java @@ -18,6 +18,7 @@ import com.alibaba.druid.util.JdbcConstants; import io.seata.common.exception.NotSupportYetException; import io.seata.common.util.BlobUtils; +import io.seata.common.util.StringUtils; import io.seata.core.exception.TransactionException; import io.seata.rm.datasource.ConnectionContext; import io.seata.rm.datasource.ConnectionProxy; @@ -160,7 +161,7 @@ public static void undo(DataSourceProxy dataSourceProxy, String xid, long branch } Blob b = rs.getBlob("rollback_info"); - String rollbackInfo = BlobUtils.blob2string(b); + String rollbackInfo = StringUtils.blob2string(b); BranchUndoLog branchUndoLog = UndoLogParserFactory.getInstance().decode(rollbackInfo); for (SQLUndoLog sqlUndoLog : branchUndoLog.getSqlUndoLogs()) { @@ -233,12 +234,13 @@ public static void undo(DataSourceProxy dataSourceProxy, String xid, long branch * * @param xids * @param branchIds + * @param limitSize * @param conn */ - public static void batchDeleteUndoLog(Set xids, Set branchIds, Connection conn) throws SQLException { + public static void batchDeleteUndoLog(Set xids, Set branchIds, int limitSize, Connection conn) throws SQLException { int xidSize = xids.size(); int branchIdSize = branchIds.size(); - String batchDeleteSql = toBatchDeleteUndoLogSql(xidSize, branchIdSize); + String batchDeleteSql = toBatchDeleteUndoLogSql(xidSize, branchIdSize,limitSize); PreparedStatement deletePST = null; try { deletePST = conn.prepareStatement(batchDeleteSql); @@ -266,14 +268,15 @@ public static void batchDeleteUndoLog(Set xids, Set branchIds, Con } - protected static String toBatchDeleteUndoLogSql(int xidSize, int branchIdSize) { + protected static String toBatchDeleteUndoLogSql(int xidSize, int branchIdSize,int limitSize) { StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.append("DELETE FROM ") .append(UNDO_LOG_TABLE_NAME) .append(" WHERE branch_id IN "); - appendInParam(branchIdSize, sqlBuilder); - sqlBuilder.append(" AND xid IN "); appendInParam(xidSize, sqlBuilder); + sqlBuilder.append(" AND xid IN "); + appendInParam(branchIdSize, sqlBuilder); + sqlBuilder.append(" LIMIT ").append(limitSize); return sqlBuilder.toString(); } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java deleted file mode 100644 index 0d79fa178d0..00000000000 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/AbstractUndoExecutorTest.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.rm.datasource.undo; - -import io.seata.rm.datasource.sql.SQLType; -import io.seata.rm.datasource.sql.struct.ColumnMeta; -import io.seata.rm.datasource.sql.struct.Field; -import io.seata.rm.datasource.sql.struct.Row; -import io.seata.rm.datasource.sql.struct.TableMeta; -import io.seata.rm.datasource.sql.struct.TableRecords; -import org.apache.commons.dbcp.BasicDataSource; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Geng Zhang - */ -public class AbstractUndoExecutorTest extends BaseExecutorTest { - - static BasicDataSource dataSource = null; - - static Connection connection = null; - - static TableMeta tableMeta = null; - - @BeforeAll - public static void start() throws SQLException { - dataSource = new BasicDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setUrl("jdbc:h2:./db_store/test_undo"); - dataSource.setUsername("sa"); - dataSource.setPassword(""); - - connection = dataSource.getConnection(); - - tableMeta = mockTableMeta(); - } - - @AfterAll - public static void stop() { - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { - } - } - if (dataSource != null) { - try { - dataSource.close(); - } catch (SQLException e) { - } - } - } - - @BeforeEach - private void prepareTable() { - execSQL("DROP TABLE table_name"); - execSQL("CREATE TABLE table_name ( `id` int(8), `name` varchar(64), PRIMARY KEY (`id`))"); - } - - @Test - public void dataValidationUpdate() throws SQLException { - execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); - execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); - - TableRecords beforeImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - - execSQL("update table_name set name = 'xxx' where id in (12345, 12346);"); - - TableRecords afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - - SQLUndoLog sqlUndoLog = new SQLUndoLog(); - sqlUndoLog.setSqlType(SQLType.UPDATE); - sqlUndoLog.setTableMeta(tableMeta); - sqlUndoLog.setTableName("table_name"); - sqlUndoLog.setBeforeImage(beforeImage); - sqlUndoLog.setAfterImage(afterImage); - - TestUndoExecutor spy = new TestUndoExecutor(sqlUndoLog, false); - - // case1: normal case before:aaa -> after:xxx -> current:xxx - Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); - - // case2: dirty data before:aaa -> after:xxx -> current:yyy - execSQL("update table_name set name = 'yyy' where id in (12345, 12346);"); - try { - spy.dataValidationAndGoOn(connection); - Assertions.fail(); - } catch (Exception e) { - Assertions.assertTrue(e instanceof SQLException); - } - - // case 3: before == current before:aaa -> after:xxx -> current:aaa - execSQL("update table_name set name = 'aaa' where id in (12345, 12346);"); - Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); - - // case 4: before == after before:aaa -> after:aaa - afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - sqlUndoLog.setAfterImage(afterImage); - Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); - } - - @Test - public void dataValidationInsert() throws SQLException { - TableRecords beforeImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - - execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); - execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); - - TableRecords afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - - SQLUndoLog sqlUndoLog = new SQLUndoLog(); - sqlUndoLog.setSqlType(SQLType.INSERT); - sqlUndoLog.setTableMeta(tableMeta); - sqlUndoLog.setTableName("table_name"); - sqlUndoLog.setBeforeImage(beforeImage); - sqlUndoLog.setAfterImage(afterImage); - - TestUndoExecutor spy = new TestUndoExecutor(sqlUndoLog, false); - - // case1: normal case before:0 -> after:2 -> current:2 - Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); - - // case2: dirty data before:0 -> after:2 -> current:2' - execSQL("update table_name set name = 'yyy' where id in (12345, 12346);"); - try { - Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); - Assertions.fail(); - } catch (Exception e) { - Assertions.assertTrue(e instanceof SQLException); - } - - // case3: before == current before:0 -> after:2 -> current:0 - execSQL("delete from table_name where id in (12345, 12346);"); - Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); - - // case 4: before == after before:0 -> after:0 - afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - sqlUndoLog.setAfterImage(afterImage); - Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); - } - - @Test - public void dataValidationDelete() throws SQLException { - execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); - execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); - - TableRecords beforeImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - - execSQL("delete from table_name where id in (12345, 12346);"); - - TableRecords afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - - SQLUndoLog sqlUndoLog = new SQLUndoLog(); - sqlUndoLog.setSqlType(SQLType.INSERT); - sqlUndoLog.setTableMeta(tableMeta); - sqlUndoLog.setTableName("table_name"); - sqlUndoLog.setBeforeImage(beforeImage); - sqlUndoLog.setAfterImage(afterImage); - - TestUndoExecutor spy = new TestUndoExecutor(sqlUndoLog, true); - - // case1: normal case before:2 -> after:0 -> current:0 - Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); - - // case2: dirty data before:2 -> after:0 -> current:1 - execSQL("INSERT INTO table_name(id, name) VALUES (12345,'aaa');"); - try { - Assertions.assertTrue(spy.dataValidationAndGoOn(connection)); - Assertions.fail(); - } catch (Exception e) { - Assertions.assertTrue(e instanceof SQLException); - } - - // case3: before == current before:2 -> after:0 -> current:2 - execSQL("INSERT INTO table_name(id, name) VALUES (12346,'aaa');"); - Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); - - // case 4: before == after before:2 -> after:2 - afterImage = execQuery(tableMeta, "SELECT * FROM table_name WHERE id IN (12345, 12346);"); - sqlUndoLog.setAfterImage(afterImage); - Assertions.assertFalse(spy.dataValidationAndGoOn(connection)); - } - - @Test - public void testParsePK() { - TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("id"); - Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); - - TableRecords beforeImage = new TableRecords(); - beforeImage.setTableName("table_name"); - beforeImage.setTableMeta(tableMeta); - - List beforeRows = new ArrayList<>(); - Row row0 = new Row(); - Field field01 = addField(row0, "id", 1, "12345"); - Field field02 = addField(row0, "age", 1, "2"); - beforeRows.add(row0); - Row row1 = new Row(); - Field field11 = addField(row1, "id", 1, "12346"); - Field field12 = addField(row1, "age", 1, "2"); - beforeRows.add(row1); - beforeImage.setRows(beforeRows); - - SQLUndoLog sqlUndoLog = new SQLUndoLog(); - sqlUndoLog.setSqlType(SQLType.UPDATE); - sqlUndoLog.setTableMeta(tableMeta); - sqlUndoLog.setTableName("table_name"); - sqlUndoLog.setBeforeImage(beforeImage); - sqlUndoLog.setAfterImage(null); - - TestUndoExecutor executor = new TestUndoExecutor(sqlUndoLog, true); - Object[] pkValues = executor.parsePkValues(beforeImage); - Assertions.assertEquals(2, pkValues.length); - } - - - private static TableMeta mockTableMeta() { - TableMeta tableMeta = Mockito.mock(TableMeta.class); - Mockito.when(tableMeta.getPkName()).thenReturn("ID"); - Mockito.when(tableMeta.getTableName()).thenReturn("table_name"); - ColumnMeta meta0 = Mockito.mock(ColumnMeta.class); - Mockito.when(meta0.getDataType()).thenReturn(Types.INTEGER); - Mockito.when(meta0.getColumnName()).thenReturn("ID"); - Mockito.when(tableMeta.getColumnMeta("ID")).thenReturn(meta0); - ColumnMeta meta1 = Mockito.mock(ColumnMeta.class); - Mockito.when(meta1.getDataType()).thenReturn(Types.VARCHAR); - Mockito.when(meta1.getColumnName()).thenReturn("NAME"); - Mockito.when(tableMeta.getColumnMeta("NAME")).thenReturn(meta1); - return tableMeta; - } - - private void execSQL(String sql) { - Statement s = null; - try { - s = connection.createStatement(); - s.execute(sql); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (s != null) { - try { - s.close(); - } catch (SQLException e) { - } - } - } - } - - private TableRecords execQuery(TableMeta tableMeta, String sql) throws SQLException { - Statement s = null; - ResultSet set = null; - try { - s = connection.createStatement(); - set = s.executeQuery(sql); - return TableRecords.buildRecords(tableMeta, set); - } finally { - if (set != null) { - try { - set.close(); - } catch (Exception e) { - } - } - if (s != null) { - try { - s.close(); - } catch (SQLException e) { - } - } - } - } -} - -class TestUndoExecutor extends AbstractUndoExecutor { - private boolean isDelete; - public TestUndoExecutor(SQLUndoLog sqlUndoLog, boolean isDelete) { - super(sqlUndoLog); - this.isDelete = isDelete; - } - - @Override - protected String buildUndoSQL() { - return null; - } - - @Override - protected TableRecords getUndoRows() { - return isDelete ? sqlUndoLog.getBeforeImage() : sqlUndoLog.getAfterImage(); - } -} diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java index ae1174c8c5c..eb7a0324bb2 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java @@ -59,7 +59,6 @@ import io.seata.rm.datasource.sql.struct.TableRecords; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; /** * The type Undo executor test. @@ -89,7 +88,7 @@ public void testField() { * Test update. */ @Test - public void testUpdate() throws SQLException { + public void testUpdate() { SQLUndoLog SQLUndoLog = new SQLUndoLog(); SQLUndoLog.setTableName("my_test_table"); SQLUndoLog.setSqlType(SQLType.UPDATE); @@ -148,18 +147,19 @@ public void testUpdate() throws SQLException { SQLUndoLog.setAfterImage(afterImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - MockConnection connection = new MockConnection(); - AbstractUndoExecutor spy = Mockito.spy(executor); - // skip data validation - Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); - spy.executeOn(connection); + + try { + executor.executeOn(new MockConnection()); + } catch (SQLException e) { + e.printStackTrace(); + } } /** * Test insert. */ @Test - public void testInsert() throws SQLException { + public void testInsert() { SQLUndoLog SQLUndoLog = new SQLUndoLog(); SQLUndoLog.setTableName("my_test_table"); SQLUndoLog.setSqlType(SQLType.INSERT); @@ -217,18 +217,19 @@ public void testInsert() throws SQLException { SQLUndoLog.setAfterImage(afterImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - MockConnection connection = new MockConnection(); - AbstractUndoExecutor spy = Mockito.spy(executor); - // skip data validation - Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); - spy.executeOn(connection); + + try { + executor.executeOn(new MockConnection()); + } catch (SQLException e) { + e.printStackTrace(); + } } /** * Test delete. */ @Test - public void testDelete() throws SQLException { + public void testDelete() { SQLUndoLog SQLUndoLog = new SQLUndoLog(); SQLUndoLog.setTableName("my_test_table"); SQLUndoLog.setSqlType(SQLType.DELETE); @@ -286,11 +287,12 @@ public void testDelete() throws SQLException { SQLUndoLog.setBeforeImage(beforeImage); AbstractUndoExecutor executor = UndoExecutorFactory.getUndoExecutor(JdbcConstants.MYSQL, SQLUndoLog); - MockConnection connection = new MockConnection(); - AbstractUndoExecutor spy = Mockito.spy(executor); - // skip data validation - Mockito.doReturn(true).when(spy).dataValidationAndGoOn(connection); - spy.executeOn(connection); + + try { + executor.executeOn(new MockConnection()); + } catch (SQLException e) { + e.printStackTrace(); + } } /** diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java index e8fe5504dc9..dcc8f5d4ddc 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java @@ -40,10 +40,9 @@ public class UndoLogManagerTest { private static final int APPEND_IN_SIZE = 10; + private static final int LIMIT_SIZE = 10; - private static final String THE_APPEND_IN_SIZE_PARAM_STRING = " (?,?,?,?,?,?,?,?,?,?) "; - - private static final String THE_DOUBLE_APPEND_IN_SIZE_PARAM_STRING = " (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "; + private static final String THE_APPEND_IN_SIZE_PARAM_String = " (?,?,?,?,?,?,?,?,?,?) "; @Test public void testBatchDeleteUndoLog() throws Exception { @@ -58,7 +57,7 @@ public void testBatchDeleteUndoLog() throws Exception { Connection connection = mock(Connection.class); PreparedStatement preparedStatement = mock(PreparedStatement.class); when(connection.prepareStatement(anyString())).thenReturn(preparedStatement); - UndoLogManager.batchDeleteUndoLog(xids, branchIds, connection); + UndoLogManager.batchDeleteUndoLog(xids, branchIds, LIMIT_SIZE, connection); //verify for (int i = 1;i <= APPEND_IN_SIZE;i++){ @@ -73,10 +72,11 @@ public void testBatchDeleteUndoLog() throws Exception { @Test public void testToBatchDeleteUndoLogSql() { String expectedSqlString="DELETE FROM undo_log WHERE branch_id IN " + - THE_APPEND_IN_SIZE_PARAM_STRING + + THE_APPEND_IN_SIZE_PARAM_String + " AND xid IN " + - THE_DOUBLE_APPEND_IN_SIZE_PARAM_STRING; - String batchDeleteUndoLogSql = UndoLogManager.toBatchDeleteUndoLogSql(APPEND_IN_SIZE * 2, APPEND_IN_SIZE); + THE_APPEND_IN_SIZE_PARAM_String + + " LIMIT " + LIMIT_SIZE; + String batchDeleteUndoLogSql = UndoLogManager.toBatchDeleteUndoLogSql(APPEND_IN_SIZE, APPEND_IN_SIZE, LIMIT_SIZE); System.out.println(batchDeleteUndoLogSql); assertThat(batchDeleteUndoLogSql).isEqualTo(expectedSqlString); } @@ -85,7 +85,7 @@ public void testToBatchDeleteUndoLogSql() { public void testAppendInParam() { StringBuilder sqlBuilder = new StringBuilder(); UndoLogManager.appendInParam(APPEND_IN_SIZE, sqlBuilder); - assertThat(sqlBuilder.toString()).isEqualTo(THE_APPEND_IN_SIZE_PARAM_STRING); + assertThat(sqlBuilder.toString()).isEqualTo(THE_APPEND_IN_SIZE_PARAM_String); } } diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java index a3fd52afb1a..879b77a88cd 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java @@ -26,6 +26,7 @@ import io.seata.rm.datasource.undo.KeywordChecker; import io.seata.rm.datasource.undo.KeywordCheckerFactory; import io.seata.rm.datasource.undo.SQLUndoLog; +import io.seata.rm.datasource.undo.UndoExecutorTest; import io.seata.rm.datasource.undo.mysql.MySQLUndoDeleteExecutor; import io.seata.rm.datasource.undo.mysql.MySQLUndoInsertExecutor; import io.seata.rm.datasource.undo.mysql.MySQLUndoUpdateExecutor; diff --git a/server/pom.xml b/server/pom.xml index 870f8187e7a..55290bec0ee 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -45,24 +45,6 @@ ${project.version} - - - com.alibaba - druid - - - commons-dbcp - commons-dbcp - - - com.h2database - h2 - - - mysql - mysql-connector-java - - diff --git a/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java b/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java index 89fcbe94740..d6655196eee 100644 --- a/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java +++ b/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java @@ -15,6 +15,7 @@ */ package io.seata.server; +import io.seata.common.XID; import io.seata.core.exception.AbstractExceptionHandler; import io.seata.core.exception.TransactionException; import io.seata.core.model.GlobalStatus; @@ -105,7 +106,8 @@ public void execute(GlobalRollbackRequest request, GlobalRollbackResponse respon public void onTransactionException(GlobalRollbackRequest request, GlobalRollbackResponse response, TransactionException tex) { super.onTransactionException(request, response, tex); - GlobalSession globalSession = SessionHolder.findGlobalSession(request.getXid()); + GlobalSession globalSession = SessionHolder.findGlobalSession( + XID.getTransactionId(request.getXid())); if (globalSession != null) { response.setGlobalStatus(globalSession.getStatus()); } else { @@ -116,7 +118,8 @@ public void onTransactionException(GlobalRollbackRequest request, GlobalRollback @Override public void onException(GlobalRollbackRequest request, GlobalRollbackResponse response, Exception rex) { super.onException(request, response, rex); - GlobalSession globalSession = SessionHolder.findGlobalSession(request.getXid()); + GlobalSession globalSession = SessionHolder.findGlobalSession( + XID.getTransactionId(request.getXid())); if (globalSession != null) { response.setGlobalStatus(globalSession.getStatus()); } else { diff --git a/server/src/main/java/io/seata/server/Server.java b/server/src/main/java/io/seata/server/Server.java index 0cec9d18b87..92273a3e68f 100644 --- a/server/src/main/java/io/seata/server/Server.java +++ b/server/src/main/java/io/seata/server/Server.java @@ -42,7 +42,7 @@ public class Server { private static final int SERVER_DEFAULT_PORT = 8091; private static final ThreadPoolExecutor WORKING_THREADS = new ThreadPoolExecutor(MIN_SERVER_POOL_SIZE, MAX_SERVER_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, - new LinkedBlockingQueue<>(MAX_TASK_QUEUE_SIZE), + new LinkedBlockingQueue(MAX_TASK_QUEUE_SIZE), new NamedThreadFactory("ServerHandlerThread", MAX_SERVER_POOL_SIZE), new ThreadPoolExecutor.CallerRunsPolicy()); /** diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java index 18c1e80395f..15063da2cb2 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java @@ -16,17 +16,13 @@ package io.seata.server.coordinator; import java.io.IOException; -import java.time.Duration; import java.util.Collection; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import io.seata.common.XID; import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.CollectionUtils; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.common.util.DurationUtil; -import io.seata.config.ConfigurationFactory; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; @@ -82,44 +78,6 @@ public class DefaultCoordinator extends AbstractTCInboundHandler private static final int TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS = 5000; - /** - * The Committing retry delay. - */ - protected int committingRetryDelay = CONFIG.getInt(ConfigurationKeys.COMMITING_RETRY_DELAY, 5); - - /** - * The Asyn committing retry delay. - */ - protected int asynCommittingRetryDelay = CONFIG.getInt(ConfigurationKeys.ASYN_COMMITING_RETRY_DELAY, 5); - - /** - * The Rollbacking retry delay. - */ - protected int rollbackingRetryDelay = CONFIG.getInt(ConfigurationKeys.ROLLBACKING_RETRY_DELAY, 5); - - /** - * The Timeout retry delay. - */ - protected int timeoutRetryDelay = CONFIG.getInt(ConfigurationKeys.TIMEOUT_RETRY_DELAY, 5); - - private static final int ALWAYS_RETRY_BOUNDARY = 0; - - private static final Duration MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration(ConfigurationKeys.SERVICE_PREFIX + "max.commit.retry.timeout", DurationUtil.DEFAULT_DURATION, 100); - - private static final Duration MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getDuration(ConfigurationKeys.SERVICE_PREFIX + "max.rollback.retry.timeout", DurationUtil.DEFAULT_DURATION, 100); - - private ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("RetryRollbacking", 1)); - - private ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("RetryCommitting", 1)); - - private ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("AsyncCommitting", 1)); - - private ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1, - new NamedThreadFactory("TxTimeoutCheck", 1)); - private ServerMessageSender messageSender; private Core core = CoreFactory.get(); @@ -198,7 +156,7 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI request.setApplicationData(applicationData); request.setBranchType(branchType); - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); if(globalSession == null){ return BranchStatus.PhaseTwo_Committed; } @@ -207,7 +165,9 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI BranchCommitResponse response = (BranchCommitResponse)messageSender.sendSyncRequest(resourceId, branchSession.getClientId(), request); return response.getBranchStatus(); - } catch (IOException | TimeoutException e) { + } catch (IOException e) { + throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e); + } catch (TimeoutException e) { throw new TransactionException(FailedToSendBranchCommitRequest, branchId + "/" + xid, e); } } @@ -225,7 +185,7 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc request.setApplicationData(applicationData); request.setBranchType(branchType); - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); if(globalSession == null){ return BranchStatus.PhaseTwo_Rollbacked; } @@ -234,34 +194,27 @@ public BranchStatus branchRollback(BranchType branchType, String xid, long branc BranchRollbackResponse response = (BranchRollbackResponse)messageSender.sendSyncRequest(resourceId, branchSession.getClientId(), request); return response.getBranchStatus(); - } catch (IOException | TimeoutException e) { + } catch (IOException e) { + throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e); + } catch (TimeoutException e) { throw new TransactionException(FailedToSendBranchRollbackRequest, branchId + "/" + xid, e); } } - /** - * Timeout check. - * - * @throws TransactionException the transaction exception - */ - protected void timeoutCheck() throws TransactionException { + private void timeoutCheck() throws TransactionException { Collection allSessions = SessionHolder.getRootSessionManager().allSessions(); - if(CollectionUtils.isEmpty(allSessions)){ - return; - } if (allSessions.size() > 0 && LOGGER.isDebugEnabled()) { LOGGER.debug("Transaction Timeout Check Begin: " + allSessions.size()); } for (GlobalSession globalSession : allSessions) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(globalSession.getXid() + " " + globalSession.getStatus() + " " + + LOGGER.debug(globalSession.getTransactionId() + " " + globalSession.getStatus() + " " + globalSession.getBeginTime() + " " + globalSession.getTimeout()); } boolean shouldTimeout = globalSession.lockAndExcute(() -> { if (globalSession.getStatus() != GlobalStatus.Begin || !globalSession.isTimeout()) { return false; } - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.close(); globalSession.changeStatus(GlobalStatus.TimeoutRollbacking); return true; @@ -270,7 +223,7 @@ protected void timeoutCheck() throws TransactionException { continue; } LOGGER.info( - "Global transaction[" + globalSession.getXid() + "] is timeout and will be rolled back."); + "Global transaction[" + globalSession.getTransactionId() + "] is timeout and will be rolled back."); globalSession.addSessionLifecycleListener(SessionHolder.getRetryRollbackingSessionManager()); SessionHolder.getRetryRollbackingSessionManager().addGlobalSession(globalSession); @@ -282,129 +235,107 @@ protected void timeoutCheck() throws TransactionException { } - /** - * Handle retry rollbacking. - */ - protected void handleRetryRollbacking() { + private void handleRetryRollbacking() { Collection rollbackingSessions = SessionHolder.getRetryRollbackingSessionManager().allSessions(); - if(CollectionUtils.isEmpty(rollbackingSessions)){ - return; - } - long now = System.currentTimeMillis(); for (GlobalSession rollbackingSession : rollbackingSessions) { try { - if(isRetryTimeout(now, MAX_ROLLBACK_RETRY_TIMEOUT.toMillis(), rollbackingSession.getBeginTime())){ - /** - * Prevent thread safety issues - */ - SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(rollbackingSession); - LOGGER.error("GlobalSession rollback retry timeout [{}]", rollbackingSession.getTransactionId()); - continue; - } - rollbackingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); core.doGlobalRollback(rollbackingSession, true); } catch (TransactionException ex) { LOGGER.info("Failed to retry rollbacking [{}] {} {}", - rollbackingSession.getXid(), ex.getCode(), ex.getMessage()); + rollbackingSession.getTransactionId(), ex.getCode(), ex.getMessage()); } } } - /** - * Handle retry committing. - */ - protected void handleRetryCommitting() { + private void handleRetryCommitting() { Collection committingSessions = SessionHolder.getRetryCommittingSessionManager().allSessions(); - if(CollectionUtils.isEmpty(committingSessions)){ - return; - } - long now = System.currentTimeMillis(); for (GlobalSession committingSession : committingSessions) { try { - if(isRetryTimeout(now, MAX_COMMIT_RETRY_TIMEOUT.toMillis(), committingSession.getBeginTime())){ - /** - * Prevent thread safety issues - */ - SessionHolder.getRetryCommittingSessionManager().removeGlobalSession(committingSession); - LOGGER.error("GlobalSession commit retry timeout [{}]", committingSession.getTransactionId()); - continue; - } - committingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); core.doGlobalCommit(committingSession, true); } catch (TransactionException ex) { LOGGER.info("Failed to retry committing [{}] {} {}", - committingSession.getXid(), ex.getCode(), ex.getMessage()); + committingSession.getTransactionId(), ex.getCode(), ex.getMessage()); } } } - private boolean isRetryTimeout(long now, long timeout, long beginTime){ - /** - * Start timing when the session begin - */ - if(timeout >= ALWAYS_RETRY_BOUNDARY && - now - beginTime > timeout){ - return true; - } - return false; - } - - /** - * Handle async committing. - */ - protected void handleAsyncCommitting() { + private void handleAsyncCommitting() { Collection asyncCommittingSessions = SessionHolder.getAsyncCommittingSessionManager() .allSessions(); - if(CollectionUtils.isEmpty(asyncCommittingSessions)){ - return; - } for (GlobalSession asyncCommittingSession : asyncCommittingSessions) { try { - asyncCommittingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); core.doGlobalCommit(asyncCommittingSession, true); } catch (TransactionException ex) { LOGGER.info("Failed to async committing [{}] {} {}", - asyncCommittingSession.getXid(), ex.getCode(), ex.getMessage()); + asyncCommittingSession.getTransactionId(), ex.getCode(), ex.getMessage()); } } } + private ScheduledThreadPoolExecutor retryRollbacking = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("RetryRollbacking", 1)); + + private ScheduledThreadPoolExecutor retryCommitting = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("RetryCommitting", 1)); + + private ScheduledThreadPoolExecutor asyncCommitting = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("AsyncCommitting", 1)); + + private ScheduledThreadPoolExecutor timeoutCheck = new ScheduledThreadPoolExecutor(1, + new NamedThreadFactory("TxTimeoutCheck", 1)); /** * Init. */ public void init() { - retryRollbacking.scheduleAtFixedRate(() -> { - try { - handleRetryRollbacking(); - } catch (Exception e) { - LOGGER.info("Exception retry rollbacking ... ", e); + retryRollbacking.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + handleRetryRollbacking(); + } catch (Exception e) { + LOGGER.info("Exception retry rollbacking ... ", e); + } + } - }, 0, rollbackingRetryDelay, TimeUnit.SECONDS); + }, 0, 5, TimeUnit.MILLISECONDS); + + retryCommitting.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + handleRetryCommitting(); + } catch (Exception e) { + LOGGER.info("Exception retry committing ... ", e); + } - retryCommitting.scheduleAtFixedRate(() -> { - try { - handleRetryCommitting(); - } catch (Exception e) { - LOGGER.info("Exception retry committing ... ", e); } - }, 0, committingRetryDelay, TimeUnit.SECONDS); + }, 0, 5, TimeUnit.MILLISECONDS); + + asyncCommitting.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + handleAsyncCommitting(); + } catch (Exception e) { + LOGGER.info("Exception async committing ... ", e); + } - asyncCommitting.scheduleAtFixedRate(() -> { - try { - handleAsyncCommitting(); - } catch (Exception e) { - LOGGER.info("Exception async committing ... ", e); } - }, 0, asynCommittingRetryDelay, TimeUnit.SECONDS); + }, 0, 10, TimeUnit.MILLISECONDS); + + timeoutCheck.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + timeoutCheck(); + } catch (Exception e) { + LOGGER.info("Exception timeout checking ... ", e); + } - timeoutCheck.scheduleAtFixedRate(() -> { - try { - timeoutCheck(); - } catch (Exception e) { - LOGGER.info("Exception timeout checking ... ", e); } - }, 0, timeoutRetryDelay, TimeUnit.SECONDS); + }, 0, 2, TimeUnit.MILLISECONDS); } @Override @@ -438,14 +369,14 @@ public void destroy() { retryCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); asyncCommitting.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); timeoutCheck.awaitTermination(TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS, TimeUnit.MILLISECONDS); - } catch (InterruptedException ignore) { + } catch (InterruptedException ingore) { } - // 2. second close netty flow + // 2. sencond close netty flow if (messageSender instanceof RpcServer){ ((RpcServer) messageSender).destroy(); } - // 3. last destroy SessionHolder + // 3. last destory SessionHolder SessionHolder.destory(); } } diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCore.java b/server/src/main/java/io/seata/server/coordinator/DefaultCore.java index cd10d4281ba..1ba36763f1f 100644 --- a/server/src/main/java/io/seata/server/coordinator/DefaultCore.java +++ b/server/src/main/java/io/seata/server/coordinator/DefaultCore.java @@ -23,7 +23,7 @@ import io.seata.core.model.GlobalStatus; import io.seata.core.model.ResourceManagerInbound; import io.seata.server.lock.LockManager; -import io.seata.server.lock.LockerFactory; +import io.seata.server.lock.LockManagerFactory; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionHelper; @@ -46,7 +46,7 @@ public class DefaultCore implements Core { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCore.class); - private LockManager lockManager = LockerFactory.getLockManager(); + private LockManager lockManager = LockManagerFactory.get(); private ResourceManagerInbound resourceManagerInbound; @@ -58,7 +58,7 @@ public void setResourceManagerInbound(ResourceManagerInbound resourceManagerInbo @Override public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(xid); + GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid)); return globalSession.lockAndExcute(() -> { if (!globalSession.isActive()) { throw new TransactionException(GlobalTransactionNotActive, "Current Status: " + globalSession.getStatus()); @@ -67,7 +67,6 @@ public Long branchRegister(BranchType branchType, String resourceId, String clie throw new TransactionException(GlobalTransactionStatusInvalid, globalSession.getStatus() + " while expecting " + GlobalStatus.Begin); } - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId, applicationData, lockKeys, clientId); if (!branchSession.lock()) { @@ -82,10 +81,10 @@ public Long branchRegister(BranchType branchType, String resourceId, String clie }); } - private GlobalSession assertGlobalSessionNotNull(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + private GlobalSession assertGlobalSessionNotNull(long transactionId) throws TransactionException { + GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); if (globalSession == null) { - throw new TransactionException(TransactionExceptionCode.GlobalTransactionNotExist, "" + xid + ""); + throw new TransactionException(TransactionExceptionCode.GlobalTransactionNotExist, "" + transactionId + ""); } return globalSession; } @@ -94,12 +93,11 @@ private GlobalSession assertGlobalSessionNotNull(String xid) throws TransactionE @Override public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, String applicationData) throws TransactionException { - GlobalSession globalSession = assertGlobalSessionNotNull(xid); + GlobalSession globalSession = assertGlobalSessionNotNull(XID.getTransactionId(xid)); BranchSession branchSession = globalSession.getBranch(branchId); if (branchSession == null) { throw new TransactionException(BranchTransactionNotExist); } - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.changeBranchStatus(branchSession, status); } @@ -107,7 +105,7 @@ public void branchReport(BranchType branchType, String xid, long branchId, Branc public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) throws TransactionException { if (branchType == BranchType.AT) { - return lockManager.isLockable(xid, resourceId, lockKeys); + return lockManager.isLockable(XID.getTransactionId(xid), resourceId, lockKeys); } else { return true; } @@ -123,19 +121,17 @@ public String begin(String applicationId, String transactionServiceGroup, String session.begin(); - return session.getXid(); + return XID.generateXID(session.getTransactionId()); } @Override public GlobalStatus commit(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); if (globalSession == null) { return GlobalStatus.Finished; } - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); // just lock changeStatus boolean shouldCommit = globalSession.lockAndExcute(() -> { - //the lock should release after branch commit globalSession.closeAndClean(); // Highlight: Firstly, close the session, then no more branch can be registered. if (globalSession.getStatus() == GlobalStatus.Begin) { globalSession.changeStatus(GlobalStatus.Committing); @@ -179,7 +175,7 @@ public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws } else { SessionHelper.endCommitFailed(globalSession); LOGGER.error("Finally, failed to commit global[{}] since branch[{}] commit failed", - globalSession.getXid(), branchSession.getBranchId()); + globalSession.getTransactionId(), branchSession.getBranchId()); return; } default: @@ -193,7 +189,7 @@ public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws } else { LOGGER.error( "Failed to commit global[{}] since branch[{}] commit failed, will retry later.", - globalSession.getXid(), branchSession.getBranchId()); + globalSession.getTransactionId(), branchSession.getBranchId()); return; } @@ -210,11 +206,11 @@ public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws } if (globalSession.hasBranch()) { - LOGGER.info("Global[{}] committing is NOT done.", globalSession.getXid()); + LOGGER.info("Global[{}] committing is NOT done.", globalSession.getTransactionId()); return; } SessionHelper.endCommitted(globalSession); - LOGGER.info("Global[{}] committing is successfully done.", globalSession.getXid()); + LOGGER.info("Global[{}] committing is successfully done.", globalSession.getTransactionId()); } private void asyncCommit(GlobalSession globalSession) throws TransactionException { @@ -242,11 +238,10 @@ private void queueToRetryRollback(GlobalSession globalSession) throws Transactio @Override public GlobalStatus rollback(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); if (globalSession == null) { return GlobalStatus.Finished; } - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); // just lock changeStatus boolean shouldRollBack = globalSession.lockAndExcute(() -> { globalSession.close(); // Highlight: Firstly, close the session, then no more branch can be registered. @@ -284,7 +279,7 @@ public void doGlobalRollback(GlobalSession globalSession, boolean retrying) thro continue; case PhaseTwo_RollbackFailed_Unretryable: SessionHelper.endRollbackFailed(globalSession); - LOGGER.error("Failed to rollback global[" + globalSession.getXid() + "] since branch[" + LOGGER.error("Failed to rollback global[" + globalSession.getTransactionId() + "] since branch[" + branchSession.getBranchId() + "] rollback failed"); return; default: @@ -309,7 +304,7 @@ public void doGlobalRollback(GlobalSession globalSession, boolean retrying) thro @Override public GlobalStatus getStatus(String xid) throws TransactionException { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); return globalSession.getStatus(); } } diff --git a/server/src/main/java/io/seata/server/lock/AbstractLockManager.java b/server/src/main/java/io/seata/server/lock/AbstractLockManager.java deleted file mode 100644 index a8db3a54d92..00000000000 --- a/server/src/main/java/io/seata/server/lock/AbstractLockManager.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import io.seata.common.XID; -import io.seata.common.util.StringUtils; -import io.seata.core.lock.RowLock; -import io.seata.server.session.BranchSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -/** - * The type Abstract lock manager. - * - * @author zhangsen - * @data 2019 /4/25 - */ -public abstract class AbstractLockManager implements LockManager { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractLockManager.class); - - /** - * Collect row locks list.` - * - * @param branchSession the branch session - * @return the list - */ - protected List collectRowLocks(BranchSession branchSession){ - List locks = new ArrayList<>(); - if(branchSession == null || StringUtils.isBlank(branchSession.getLockKey())){ - return locks; - } - String xid = branchSession.getXid(); - String resourceId = branchSession.getResourceId(); - long transactionId = branchSession.getTransactionId(); - - String lockKey = branchSession.getLockKey(); - - return collectRowLocks(lockKey, resourceId, xid, transactionId, branchSession.getBranchId()); - } - - /** - * Collect row locks list. - * - * @param lockKey the lock key - * @param resourceId the resource id - * @param xid the xid - * @return the list - */ - protected List collectRowLocks(String lockKey, String resourceId, String xid) { - return collectRowLocks(lockKey, resourceId, xid, XID.getTransactionId(xid), null); - } - - /** - * Collect row locks list. - * - * @param lockKey the lock key - * @param resourceId the resource id - * @param xid the xid - * @param transactionId the transaction id - * @param branchID the branch id - * @return the list - */ - protected List collectRowLocks(String lockKey, String resourceId, String xid, Long transactionId, Long branchID){ - List locks = new ArrayList(); - - String[] tableGroupedLockKeys = lockKey.split(";"); - for (String tableGroupedLockKey : tableGroupedLockKeys) { - int idx = tableGroupedLockKey.indexOf(":"); - if (idx < 0) { - return locks; - } - String tableName = tableGroupedLockKey.substring(0, idx); - String mergedPKs = tableGroupedLockKey.substring(idx + 1); - if(StringUtils.isBlank(mergedPKs)){ - return locks; - } - String[] pks = mergedPKs.split(","); - if(pks == null || pks.length == 0){ - return locks; - } - for(String pk : pks){ - if(StringUtils.isNotBlank(pk)){ - RowLock rowLock = new RowLock(); - rowLock.setXid(xid); - rowLock.setTransactionId(transactionId); - rowLock.setBranchId(branchID); - rowLock.setTableName(tableName); - rowLock.setPk(pk); - rowLock.setResourceId(resourceId); - locks.add(rowLock); - } - } - } - return locks; - } - -} diff --git a/server/src/main/java/io/seata/server/lock/DefaultLockManager.java b/server/src/main/java/io/seata/server/lock/DefaultLockManager.java deleted file mode 100644 index dd66e979987..00000000000 --- a/server/src/main/java/io/seata/server/lock/DefaultLockManager.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.Locker; -import io.seata.core.lock.RowLock; -import io.seata.server.session.BranchSession; - -import java.util.List; - -/** - * The type Default lock manager. - * - * @author zhangsen - * @data 2019 -05-15 - */ -public class DefaultLockManager extends AbstractLockManager { - - private static Locker locker = null; - - @Override - public boolean acquireLock(BranchSession branchSession) throws TransactionException { - String lockKey = branchSession.getLockKey(); - if (StringUtils.isNullOrEmpty(lockKey)) { - //no lock - return true; - } - //get locks of branch - List locks = collectRowLocks(branchSession); - if(CollectionUtils.isEmpty(locks)){ - //no lock - return true; - } - return getLocker(branchSession).acquireLock(locks); - } - - @Override - public boolean releaseLock(BranchSession branchSession) throws TransactionException { - List locks = collectRowLocks(branchSession); - if(CollectionUtils.isEmpty(locks)){ - //no lock - return true; - } - try{ - return getLocker(branchSession).releaseLock(locks); - }catch(Exception t){ - LOGGER.error("unLock error, branchSession:" + branchSession, t); - return false; - } - } - - @Override - public boolean isLockable(String xid, String resourceId, String lockKey) throws TransactionException { - List locks = collectRowLocks(lockKey, resourceId, xid); - try{ - return getLocker().isLockable(locks); - }catch(Exception t){ - LOGGER.error("isLockable error, xid:" + xid + ", resourceId:"+resourceId + ", lockKey:"+lockKey, t); - return false; - } - } - - @Override - public void cleanAllLocks() throws TransactionException { - getLocker().cleanAllLocks(); - } - - /** - * Gets locker. - * - * @return the locker - */ - protected Locker getLocker() { - return getLocker(null); - } - - /** - * Gets locker. - * - * @param branchSession the branch session - * @return the locker - */ - protected Locker getLocker(BranchSession branchSession) { - return LockerFactory.get(branchSession); - } - -} diff --git a/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java b/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java new file mode 100644 index 00000000000..14a68549987 --- /dev/null +++ b/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java @@ -0,0 +1,186 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.server.lock; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import io.netty.util.internal.ConcurrentSet; +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.util.StringUtils; +import io.seata.core.exception.TransactionException; +import io.seata.server.session.BranchSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The type Default lock manager. + * + * @author sharajava + */ +public class DefaultLockManagerImpl implements LockManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLockManagerImpl.class); + + private static final int BUCKET_PER_TABLE = 128; + + private static final + ConcurrentHashMap>>> + LOCK_MAP = new ConcurrentHashMap>>>(); + + @Override + public boolean acquireLock(BranchSession branchSession) throws TransactionException { + String resourceId = branchSession.getResourceId(); + long transactionId = branchSession.getTransactionId(); + ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); + if (dbLockMap == null) { + LOCK_MAP.putIfAbsent(resourceId, + new ConcurrentHashMap>>()); + dbLockMap = LOCK_MAP.get(resourceId); + } + ConcurrentHashMap, Set> bucketHolder = branchSession.getLockHolder(); + + String lockKey = branchSession.getLockKey(); + if (StringUtils.isNullOrEmpty(lockKey)) { + return true; + } + + String[] tableGroupedLockKeys = lockKey.split(";"); + for (String tableGroupedLockKey : tableGroupedLockKeys) { + int idx = tableGroupedLockKey.indexOf(":"); + if (idx < 0) { + branchSession.unlock(); + throw new ShouldNeverHappenException("Wrong format of LOCK KEYS: " + branchSession.getLockKey()); + } + String tableName = tableGroupedLockKey.substring(0, idx); + String mergedPKs = tableGroupedLockKey.substring(idx + 1); + ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); + if (tableLockMap == null) { + dbLockMap.putIfAbsent(tableName, new ConcurrentHashMap>()); + tableLockMap = dbLockMap.get(tableName); + } + String[] pks = mergedPKs.split(","); + for (String pk : pks) { + int bucketId = pk.hashCode() % BUCKET_PER_TABLE; + Map bucketLockMap = tableLockMap.get(bucketId); + if (bucketLockMap == null) { + tableLockMap.putIfAbsent(bucketId, new HashMap()); + bucketLockMap = tableLockMap.get(bucketId); + } + synchronized (bucketLockMap) { + Long lockingTransactionId = bucketLockMap.get(pk); + if (lockingTransactionId == null) { + // No existing lock + bucketLockMap.put(pk, transactionId); + Set keysInHolder = bucketHolder.get(bucketLockMap); + if (keysInHolder == null) { + bucketHolder.putIfAbsent(bucketLockMap, new ConcurrentSet()); + keysInHolder = bucketHolder.get(bucketLockMap); + } + keysInHolder.add(pk); + + } else if (lockingTransactionId.longValue() == transactionId) { + // Locked by me + continue; + } else { + LOGGER.info( + "Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); + branchSession.unlock(); // Release all acquired locks. + return false; + } + } + } + } + return true; + } + + @Override + public boolean isLockable(long transactionId, String resourceId, String lockKey) throws TransactionException { + ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); + if (dbLockMap == null) { + return true; + } + String[] tableGroupedLockKeys = lockKey.split(";"); + for (String tableGroupedLockKey : tableGroupedLockKeys) { + int idx = tableGroupedLockKey.indexOf(":"); + if (idx < 0) { + throw new ShouldNeverHappenException("Wrong format of LOCK KEYS: " + lockKey); + } + String tableName = tableGroupedLockKey.substring(0, idx); + String mergedPKs = tableGroupedLockKey.substring(idx + 1); + ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); + if (tableLockMap == null) { + continue; + } + String[] pks = mergedPKs.split(","); + for (String pk : pks) { + int bucketId = pk.hashCode() % BUCKET_PER_TABLE; + Map bucketLockMap = tableLockMap.get(bucketId); + if (bucketLockMap == null) { + continue; + } + Long lockingTransactionId = bucketLockMap.get(pk); + if (lockingTransactionId == null || lockingTransactionId.longValue() == transactionId) { + // Locked by me + continue; + } else { + LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); + return false; + } + } + } + return true; + } + + @Override + public void cleanAllLocks() throws TransactionException { + LOCK_MAP.clear(); + } + + @Override + public boolean releaseLock(BranchSession branchSession) throws TransactionException { + ConcurrentHashMap, Set> lockHolder = branchSession.getLockHolder(); + if (lockHolder.size() == 0) { + return true; + } + Iterator, Set>> it = lockHolder.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry, Set> entry = it.next(); + Map bucket = entry.getKey(); + Set keys = entry.getValue(); + synchronized (bucket) { + for (String key : keys) { + Long v = bucket.get(key); + if (v == null) { + continue; + } + if (v.longValue() == branchSession.getTransactionId()) { + bucket.remove(key); + } + } + } + } + lockHolder.clear(); + return true; + } +} diff --git a/server/src/main/java/io/seata/server/lock/LockManager.java b/server/src/main/java/io/seata/server/lock/LockManager.java index 64e7bd7317e..54bcef3c0b4 100644 --- a/server/src/main/java/io/seata/server/lock/LockManager.java +++ b/server/src/main/java/io/seata/server/lock/LockManager.java @@ -35,30 +35,29 @@ public interface LockManager { boolean acquireLock(BranchSession branchSession) throws TransactionException; /** - * Un lock boolean. + * Is lockable boolean. * - * @param branchSession the branch session + * @param transactionId the transaction id + * @param resourceId the resource id + * @param lockKey the lock key * @return the boolean * @throws TransactionException the transaction exception */ - boolean releaseLock(BranchSession branchSession) throws TransactionException; + boolean isLockable(long transactionId, String resourceId, String lockKey) throws TransactionException; /** - * Is lockable boolean. + * Clean all locks. * - * @param xid the xid - * @param resourceId the resource id - * @param lockKey the lock key - * @return the boolean * @throws TransactionException the transaction exception */ - boolean isLockable(String xid, String resourceId, String lockKey) throws TransactionException; + void cleanAllLocks() throws TransactionException; /** - * Clean all locks. + * Release lock boolean. * + * @param branchSession the branch session + * @return the boolean * @throws TransactionException the transaction exception */ - void cleanAllLocks() throws TransactionException; - + boolean releaseLock(BranchSession branchSession) throws TransactionException; } diff --git a/server/src/main/java/io/seata/server/store/ReloadableStore.java b/server/src/main/java/io/seata/server/lock/LockManagerFactory.java similarity index 54% rename from server/src/main/java/io/seata/server/store/ReloadableStore.java rename to server/src/main/java/io/seata/server/lock/LockManagerFactory.java index d7b705c65a8..3468cc89449 100644 --- a/server/src/main/java/io/seata/server/store/ReloadableStore.java +++ b/server/src/main/java/io/seata/server/lock/LockManagerFactory.java @@ -13,34 +13,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.store; - -import java.util.List; +package io.seata.server.lock; /** - * The interface Reloadable store. + * The type Lock manager factory. * - * @author zhangsen - * @data 2019 /4/24 + * @author sharajava */ -public interface ReloadableStore { +public class LockManagerFactory { + + private static class SingletonHolder { + private static LockManager INSTANCE = new DefaultLockManagerImpl(); + } /** - * Read write store. + * Get lock manager. * - * @param readSize the read size - * @param isHistory the is history - * @return the list + * @return the lock manager */ - List readWriteStore(int readSize, boolean isHistory); + public static final LockManager get() { + return SingletonHolder.INSTANCE; + } /** - * Has remaining boolean. + * Just for test mocking * - * @param isHistory the is history - * @return the boolean + * @param lockManager the lock manager */ - boolean hasRemaining(boolean isHistory); - - + public static void set(LockManager lockManager) { + SingletonHolder.INSTANCE = lockManager; + } } diff --git a/server/src/main/java/io/seata/server/lock/LockerFactory.java b/server/src/main/java/io/seata/server/lock/LockerFactory.java deleted file mode 100644 index 6a402f0a447..00000000000 --- a/server/src/main/java/io/seata/server/lock/LockerFactory.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock; - -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.lock.LockMode; -import io.seata.core.lock.Locker; -import io.seata.core.store.db.DataSourceGenerator; -import io.seata.server.session.BranchSession; - -import javax.sql.DataSource; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * The type Lock manager factory. - * - * @author sharajava - */ -public class LockerFactory { - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The constant locker. - */ - protected static Locker locker = null; - - /** - * The constant lockerMap. - */ - protected static Map lockerMap = new ConcurrentHashMap<>(); - - /** - * The constant lockManager. - */ - protected static LockManager lockManager = new DefaultLockManager(); - - /** - * Get lock manager. - * - * @return the lock manager - */ - public static synchronized final LockManager getLockManager() { - return lockManager; - } - - /** - * Get lock manager. - * - * @param branchSession the branch session - * @return the lock manager - */ - public static synchronized final Locker get(BranchSession branchSession) { - String lockMode = CONFIG.getConfig(ConfigurationKeys.LOCK_MODE); - if(LockMode.DB.name().equalsIgnoreCase(lockMode)){ - if(lockerMap.get(lockMode) != null){ - return lockerMap.get(lockMode); - } - //init dataSource - String datasourceType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, datasourceType); - DataSource logStoreDataSource = dataSourceGenerator.generateDataSource(); - locker = EnhancedServiceLoader.load(Locker.class, lockMode, new Class[]{DataSource.class}, new Object[]{logStoreDataSource}); - lockerMap.put(lockMode, locker); - }else if(LockMode.MEMORY.name().equalsIgnoreCase(lockMode)){ - if(branchSession == null){ - throw new IllegalArgumentException("branchSession can be null for memory lockMode."); - } - locker = EnhancedServiceLoader.load(Locker.class, lockMode, - new Class[]{BranchSession.class}, new Object[]{branchSession} ); - }else { - //other locker - locker = EnhancedServiceLoader.load(Locker.class, lockMode); - } - return locker; - } - - -} diff --git a/server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java b/server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java deleted file mode 100644 index 5721727fdc8..00000000000 --- a/server/src/main/java/io/seata/server/lock/db/DataBaseLocker.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock.db; - -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.LoadLevel; -import io.seata.common.util.CollectionUtils; -import io.seata.core.lock.AbstractLocker; -import io.seata.core.lock.LockMode; -import io.seata.core.lock.RowLock; -import io.seata.core.store.LockStore; - -import javax.sql.DataSource; -import java.util.List; - -/** - * The type Data base locker. - * - * @author zhangsen - * @data 2019 -05-15 - */ -@LoadLevel(name = "db") -public class DataBaseLocker extends AbstractLocker { - - private LockStore lockStore; - - /** - * Instantiates a new Data base locker. - */ - public DataBaseLocker(){ - } - - /** - * Instantiates a new Data base locker. - * - * @param logStoreDataSource the log store data source - */ - public DataBaseLocker(DataSource logStoreDataSource){ - lockStore = EnhancedServiceLoader.load(LockStore.class, LockMode.DB.name(), new Class[]{DataSource.class}, new Object[]{logStoreDataSource}); - } - - @Override - public boolean acquireLock(List locks) { - if(CollectionUtils.isEmpty(locks)){ - //no lock - return true; - } - try{ - return lockStore.acquireLock(convertToLockDO(locks)); - }catch(Exception t){ - LOGGER.error("AcquireLock error, locks:" + CollectionUtils.toString(locks), t); - return false; - } - } - - @Override - public boolean releaseLock(List locks) { - if(CollectionUtils.isEmpty(locks)){ - //no lock - return true; - } - try{ - return lockStore.unLock(convertToLockDO(locks)); - }catch(Exception t){ - LOGGER.error("unLock error, locks:" + CollectionUtils.toString(locks), t); - return false; - } - } - - @Override - public boolean isLockable(List locks) { - try{ - return lockStore.isLockable(convertToLockDO(locks)); - }catch(Exception t){ - LOGGER.error("isLockable error, locks:" + CollectionUtils.toString(locks), t); - return false; - } - } - - /** - * Sets lock store. - * - * @param lockStore the lock store - */ - public void setLockStore(LockStore lockStore) { - this.lockStore = lockStore; - } -} diff --git a/server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java b/server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java deleted file mode 100644 index f4dbb9423e6..00000000000 --- a/server/src/main/java/io/seata/server/lock/memory/MemoryLocker.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock.memory; - -import io.netty.util.internal.ConcurrentSet; -import io.seata.common.exception.FrameworkException; -import io.seata.common.loader.LoadLevel; -import io.seata.common.util.CollectionUtils; -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.AbstractLocker; -import io.seata.core.lock.RowLock; -import io.seata.server.session.BranchSession; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * The type Memory locker. - * - * @author zhangsen - * @data 2019 -05-15 - */ -@LoadLevel(name="memory") -public class MemoryLocker extends AbstractLocker { - - private static final int BUCKET_PER_TABLE = 128; - - private static final ConcurrentHashMap>>> - LOCK_MAP = new ConcurrentHashMap>>>(); - - /** - * The Branch session. - */ - protected BranchSession branchSession = null; - - /** - * Instantiates a new Memory locker. - * - * @param branchSession the branch session - */ - public MemoryLocker(BranchSession branchSession){ - this.branchSession = branchSession; - } - - @Override - public boolean acquireLock(List rowLocks) { - if(CollectionUtils.isEmpty(rowLocks)){ - //no lock - return true; - } - String resourceId = branchSession.getResourceId(); - long transactionId = branchSession.getTransactionId(); - - ConcurrentHashMap, Set> bucketHolder = branchSession.getLockHolder(); - ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); - if (dbLockMap == null) { - LOCK_MAP.putIfAbsent(resourceId, new ConcurrentHashMap>>()); - dbLockMap = LOCK_MAP.get(resourceId); - } - - for(RowLock lock : rowLocks){ - String tableName = lock.getTableName(); - String pk = lock.getPk(); - ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); - if (tableLockMap == null) { - dbLockMap.putIfAbsent(tableName, new ConcurrentHashMap>()); - tableLockMap = dbLockMap.get(tableName); - } - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - Map bucketLockMap = tableLockMap.get(bucketId); - if (bucketLockMap == null) { - tableLockMap.putIfAbsent(bucketId, new ConcurrentHashMap()); - bucketLockMap = tableLockMap.get(bucketId); - } - synchronized (bucketLockMap) { - Long lockingTransactionId = bucketLockMap.get(pk); - if (lockingTransactionId == null) { - //No existing lock - bucketLockMap.put(pk, transactionId); - Set keysInHolder = bucketHolder.get(bucketLockMap); - if (keysInHolder == null) { - bucketHolder.putIfAbsent(bucketLockMap, new ConcurrentSet()); - keysInHolder = bucketHolder.get(bucketLockMap); - } - keysInHolder.add(pk); - - } else if (lockingTransactionId.longValue() == transactionId) { - // Locked by me - continue; - } else { - LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); - try { - // Release all acquired locks. - branchSession.unlock(); - } catch (TransactionException e) { - throw new FrameworkException(e); - } - return false; - } - } - } - return true; - } - - @Override - public boolean releaseLock(List rowLock) { - ConcurrentHashMap, Set> lockHolder = branchSession.getLockHolder(); - if (lockHolder == null || lockHolder.size() == 0) { - return true; - } - Iterator, Set>> it = lockHolder.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry, Set> entry = it.next(); - Map bucket = entry.getKey(); - Set keys = entry.getValue(); - synchronized (bucket) { - for (String key : keys) { - Long v = bucket.get(key); - if (v == null) { - continue; - } - if (v.longValue() == branchSession.getTransactionId()) { - bucket.remove(key); - } - } - } - } - lockHolder.clear(); - return true; - } - - @Override - public boolean isLockable(List rowLocks) { - if(CollectionUtils.isEmpty(rowLocks)){ - //no lock - return true; - } - Long transactionId = rowLocks.get(0).getTransactionId(); - String resourceId = rowLocks.get(0).getResourceId(); - ConcurrentHashMap>> dbLockMap = LOCK_MAP.get(resourceId); - if (dbLockMap == null) { - return true; - } - for(RowLock rowLock : rowLocks){ - String xid = rowLock.getXid(); - String tableName = rowLock.getTableName(); - String pk = rowLock.getPk(); - - ConcurrentHashMap> tableLockMap = dbLockMap.get(tableName); - if (tableLockMap == null) { - continue; - } - int bucketId = pk.hashCode() % BUCKET_PER_TABLE; - Map bucketLockMap = tableLockMap.get(bucketId); - if (bucketLockMap == null) { - continue; - } - Long lockingTransactionId = bucketLockMap.get(pk); - if (lockingTransactionId == null || lockingTransactionId.longValue() == transactionId) { - // Locked by me - continue; - } else { - LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + lockingTransactionId); - return false; - } - } - return true; - } - - @Override - public void cleanAllLocks() { - LOCK_MAP.clear(); - } -} diff --git a/server/src/main/java/io/seata/server/session/AbstractSessionManager.java b/server/src/main/java/io/seata/server/session/AbstractSessionManager.java index 8cce5790b8f..d58f8b71d5a 100644 --- a/server/src/main/java/io/seata/server/session/AbstractSessionManager.java +++ b/server/src/main/java/io/seata/server/session/AbstractSessionManager.java @@ -25,8 +25,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * The type Abstract session manager. + * + * @author sharajava */ public abstract class AbstractSessionManager implements SessionManager, SessionLifecycleListener { @@ -35,6 +43,11 @@ public abstract class AbstractSessionManager implements SessionManager, SessionL */ protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractSessionManager.class); + /** + * The Session map. + */ + protected Map sessionMap = new ConcurrentHashMap<>(); + /** * The Transaction store manager. */ @@ -45,12 +58,6 @@ public abstract class AbstractSessionManager implements SessionManager, SessionL */ protected String name; - /** - * Instantiates a new Abstract session manager. - */ - public AbstractSessionManager() { - } - /** * Instantiates a new Abstract session manager. * @@ -66,6 +73,15 @@ public void addGlobalSession(GlobalSession session) throws TransactionException LOGGER.debug("MANAGER[" + name + "] SESSION[" + session + "] " + LogOperation.GLOBAL_ADD); } writeSession(LogOperation.GLOBAL_ADD, session); + sessionMap.put(session.getTransactionId(), session); + + } + + + + @Override + public GlobalSession findGlobalSession(Long transactionId) { + return sessionMap.get(transactionId); } @Override @@ -82,6 +98,8 @@ public void removeGlobalSession(GlobalSession session) throws TransactionExcepti LOGGER.debug("MANAGER[" + name + "] SESSION[" + session + "] " + LogOperation.GLOBAL_REMOVE); } writeSession(LogOperation.GLOBAL_REMOVE, session); + sessionMap.remove(session.getTransactionId()); + } @Override @@ -108,6 +126,23 @@ public void removeBranchSession(GlobalSession globalSession, BranchSession branc LOGGER.debug("MANAGER[" + name + "] SESSION[" + branchSession + "] " + LogOperation.GLOBAL_ADD); } writeSession(LogOperation.BRANCH_REMOVE, branchSession); + + } + + @Override + public Collection allSessions() { + return sessionMap.values(); + } + + @Override + public List findGlobalSessions(SessionCondition condition) { + List found = new ArrayList<>(); + for (GlobalSession globalSession : sessionMap.values()) { + if (System.currentTimeMillis() - globalSession.getBeginTime() > condition.getOverTimeAliveMills()) { + found.add(globalSession); + } + } + return found; } @Override @@ -139,29 +174,18 @@ public void onRemoveBranch(GlobalSession globalSession, BranchSession branchSess @Override public void onClose(GlobalSession globalSession) throws TransactionException { globalSession.setActive(false); + } @Override public void onEnd(GlobalSession globalSession) throws TransactionException { removeGlobalSession(globalSession); + } - private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException { + private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException{ if (!transactionStoreManager.writeSession(logOperation, sessionStorable)) { throw new TransactionException(TransactionExceptionCode.FailedWriteSession); } } - - @Override - public void destroy() { - } - - /** - * Sets transaction store manager. - * - * @param transactionStoreManager the transaction store manager - */ - public void setTransactionStoreManager(TransactionStoreManager transactionStoreManager) { - this.transactionStoreManager = transactionStoreManager; - } } diff --git a/server/src/main/java/io/seata/server/session/BranchSession.java b/server/src/main/java/io/seata/server/session/BranchSession.java index 7354a88ab07..31e51961235 100644 --- a/server/src/main/java/io/seata/server/session/BranchSession.java +++ b/server/src/main/java/io/seata/server/session/BranchSession.java @@ -15,22 +15,22 @@ */ package io.seata.server.session; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + import io.seata.common.util.CompressUtil; import io.seata.core.exception.TransactionException; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; -import io.seata.server.lock.LockerFactory; +import io.seata.server.lock.LockManagerFactory; import io.seata.server.store.SessionStorable; import io.seata.server.store.StoreConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - /** * The type Branch session. * @@ -45,8 +45,6 @@ public class BranchSession implements Lockable, Comparable, Sessi private static ThreadLocal byteBufferThreadLocal = ThreadLocal.withInitial(() -> ByteBuffer.allocate( MAX_BRANCH_SESSION_SIZE)); - private String xid; - private long transactionId; private long branchId; @@ -66,7 +64,7 @@ public class BranchSession implements Lockable, Comparable, Sessi private String applicationData; private ConcurrentHashMap, Set> lockHolder - = new ConcurrentHashMap<>(); + = new ConcurrentHashMap, Set>(); /** * Gets application data. @@ -190,7 +188,7 @@ public BranchStatus getStatus() { * * @param status the status */ - public void setStatus(BranchStatus status) { + void setStatus(BranchStatus status) { this.status = status; } @@ -230,24 +228,6 @@ public void setBranchId(long branchId) { this.branchId = branchId; } - /** - * Gets xid. - * - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - @Override public String toString() { return "BR:" + branchId + "/" + transactionId; @@ -269,12 +249,12 @@ public ConcurrentHashMap, Set> getLockHolder() { @Override public boolean lock() throws TransactionException { - return LockerFactory.getLockManager().acquireLock(this); + return LockManagerFactory.get().acquireLock(this); } @Override public boolean unlock() throws TransactionException { - return LockerFactory.getLockManager().releaseLock(this); + return LockManagerFactory.get().releaseLock(this); } @Override @@ -288,9 +268,7 @@ public byte[] encode() { byte[] applicationDataBytes = applicationData != null ? applicationData.getBytes() : null; - byte[] xidBytes = xid != null ? xid.getBytes() : null; - - int size = calBranchSessionSize(resourceIdBytes, lockKeyBytes, clientIdBytes, applicationDataBytes, xidBytes); + int size = calBranchSessionSize(resourceIdBytes, lockKeyBytes, clientIdBytes, applicationDataBytes); if (size > MAX_BRANCH_SESSION_SIZE) { if (lockKeyBytes == null) { @@ -349,13 +327,6 @@ public byte[] encode() { byteBuffer.putInt(0); } - if(xidBytes != null){ - byteBuffer.putInt(xidBytes.length); - byteBuffer.put(xidBytes); - }else { - byteBuffer.putInt(0); - } - byteBuffer.put((byte)status.getCode()); byteBuffer.flip(); byte[] result = new byte[byteBuffer.limit()]; @@ -364,19 +335,18 @@ public byte[] encode() { } private int calBranchSessionSize(byte[] resourceIdBytes, byte[] lockKeyBytes, byte[] clientIdBytes, - byte[] applicationDataBytes, byte[] xidBytes) { + byte[] applicationDataBytes) { final int size = 8 // trascationId - + 8 // branchId - + 4 // resourceIdBytes.length - + 4 // lockKeyBytes.length - + 2 // clientIdBytes.length - + 4 // applicationDataBytes.length - + 1 // statusCode - + (resourceIdBytes == null ? 0 : resourceIdBytes.length) - + (lockKeyBytes == null ? 0 : lockKeyBytes.length) - + (clientIdBytes == null ? 0 : clientIdBytes.length) - + (applicationDataBytes == null ? 0 : applicationDataBytes.length) - + (xidBytes == null ? 0 : xidBytes.length); + + 8 // branchId + + 4 // resourceIdBytes.length + + 4 // lockKeyBytes.length + + 2 // clientIdBytes.length + + 4 // applicationDataBytes.length + + 1 // statusCode + + (resourceIdBytes == null ? 0 : resourceIdBytes.length) + + (lockKeyBytes == null ? 0 : lockKeyBytes.length) + + (clientIdBytes == null ? 0 : clientIdBytes.length) + + (applicationDataBytes == null ? 0 : applicationDataBytes.length); return size; } @@ -399,7 +369,7 @@ public void decode(byte[] a) { try { this.lockKey = new String(CompressUtil.uncompress(byLockKey)); } catch (IOException e) { - throw new RuntimeException("decompress lockKey error", e); + throw new RuntimeException("uncompress lockKey error", e); } } else { this.lockKey = new String(byLockKey); @@ -418,12 +388,6 @@ public void decode(byte[] a) { byteBuffer.get(byApplicationData); this.applicationData = new String(byApplicationData); } - int xidLen = byteBuffer.getInt(); - if (xidLen > 0) { - byte[] xidBytes = new byte[xidLen]; - byteBuffer.get(xidBytes); - this.xid = new String(xidBytes); - } this.status = BranchStatus.get(byteBuffer.get()); } diff --git a/server/src/main/java/io/seata/server/session/DefaultSessionManager.java b/server/src/main/java/io/seata/server/session/DefaultSessionManager.java index a9fcf0cae66..ff24f7f6bba 100644 --- a/server/src/main/java/io/seata/server/session/DefaultSessionManager.java +++ b/server/src/main/java/io/seata/server/session/DefaultSessionManager.java @@ -15,30 +15,19 @@ */ package io.seata.server.session; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import io.seata.common.loader.LoadLevel; -import io.seata.core.exception.TransactionException; -import io.seata.server.store.AbstractTransactionStoreManager; import io.seata.server.store.SessionStorable; +import io.seata.server.store.TransactionStoreManager; +import io.seata.server.store.TransactionWriteStore; /** - * The type Default session manager, store session data in memory. + * The type Default session manager. * * @author sharajava */ -@LoadLevel(name = "default") public class DefaultSessionManager extends AbstractSessionManager { - /** - * The Session map. - */ - protected Map sessionMap = new ConcurrentHashMap(); - /** * Instantiates a new Default session manager. * @@ -46,45 +35,27 @@ public class DefaultSessionManager extends AbstractSessionManager { */ public DefaultSessionManager(String name) { super(name); - transactionStoreManager = new AbstractTransactionStoreManager() { + transactionStoreManager = new TransactionStoreManager() { @Override public boolean writeSession(LogOperation logOperation, SessionStorable session) { return true; } - }; - } - @Override - public void addGlobalSession(GlobalSession session) throws TransactionException { - super.addGlobalSession(session); - sessionMap.put(session.getXid(), session); - } - - @Override - public GlobalSession findGlobalSession(String xid) { - return sessionMap.get(xid); - } + @Override + public void shutdown() { - @Override - public void removeGlobalSession(GlobalSession session) throws TransactionException { - super.removeGlobalSession(session); - sessionMap.remove(session.getXid()); - } + } - @Override - public Collection allSessions() { - return sessionMap.values(); - } + @Override + public List readWriteStoreFromFile(int readSize, boolean isHistory) { + return null; + } - @Override - public List findGlobalSessions(SessionCondition condition) { - List found = new ArrayList<>(); - for (GlobalSession globalSession : sessionMap.values()) { - if (System.currentTimeMillis() - globalSession.getBeginTime() > condition.getOverTimeAliveMills()) { - found.add(globalSession); + @Override + public boolean hasRemaining(boolean isHistory) { + return false; } - } - return found; + }; } @Override diff --git a/server/src/main/java/io/seata/server/session/file/FileBasedSessionManager.java b/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java similarity index 71% rename from server/src/main/java/io/seata/server/session/file/FileBasedSessionManager.java rename to server/src/main/java/io/seata/server/session/FileBasedSessionManager.java index 02ade24cefb..1684cccdfac 100644 --- a/server/src/main/java/io/seata/server/session/file/FileBasedSessionManager.java +++ b/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.session.file; +package io.seata.server.session; import java.io.File; import java.io.IOException; @@ -23,31 +23,21 @@ import java.util.Map; import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.LoadLevel; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.model.GlobalStatus; -import io.seata.core.store.StoreMode; -import io.seata.server.session.BranchSession; -import io.seata.server.session.DefaultSessionManager; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.Reloadable; -import io.seata.server.session.SessionManager; -import io.seata.server.store.ReloadableStore; import io.seata.server.UUIDGenerator; +import io.seata.server.store.FileTransactionStoreManager; import io.seata.server.store.SessionStorable; import io.seata.server.store.TransactionStoreManager; import io.seata.server.store.TransactionWriteStore; - /** * The type File based session manager. * * @author jimin.jm @alibaba-inc.com */ -@LoadLevel(name = "file") -public class FileBasedSessionManager extends DefaultSessionManager implements Reloadable { +public class FileBasedSessionManager extends AbstractSessionManager implements Reloadable { private static final int READ_SIZE = ConfigurationFactory.getInstance().getInt( ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE, 100); @@ -61,9 +51,7 @@ public class FileBasedSessionManager extends DefaultSessionManager implements Re */ public FileBasedSessionManager(String name, String sessionStoreFilePath) throws IOException { super(name); - transactionStoreManager = EnhancedServiceLoader.load(TransactionStoreManager.class, StoreMode.FILE.name(), - new Class[]{String.class, SessionManager.class}, - new Object[]{sessionStoreFilePath + File.separator + name, this}); + transactionStoreManager = new FileTransactionStoreManager(sessionStoreFilePath + File.separator + name, this); } @Override @@ -80,13 +68,13 @@ private void restoreSessions() { if (!unhandledBranchBuffer.isEmpty()) { unhandledBranchBuffer.values().forEach(branchSession -> { - String xid = branchSession.getXid(); + long tid = branchSession.getTransactionId(); long bid = branchSession.getBranchId(); - GlobalSession found = sessionMap.get(xid); + GlobalSession found = sessionMap.get(tid); if (found == null) { // Ignore if (LOGGER.isInfoEnabled()) { - LOGGER.info("GlobalSession Does Not Exists For BranchSession [" + bid + "/" + xid + "]"); + LOGGER.info("GlobalSession Does Not Exists For BranchSession [" + bid + "/" + tid + "]"); } } else { BranchSession existingBranch = found.getBranch(branchSession.getBranchId()); @@ -103,7 +91,7 @@ private void restoreSessions() { private void washSessions() { if (sessionMap.size() > 0) { - Iterator> iterator = sessionMap.entrySet().iterator(); + Iterator> iterator = sessionMap.entrySet().iterator(); while (iterator.hasNext()) { GlobalSession globalSession = iterator.next().getValue(); @@ -128,11 +116,8 @@ private void washSessions() { } private void restoreSessions(boolean isHistory, Map unhandledBranchBuffer) { - if(!(transactionStoreManager instanceof ReloadableStore)){ - return; - } - while (((ReloadableStore)transactionStoreManager).hasRemaining(isHistory)) { - List stores = ((ReloadableStore)transactionStoreManager).readWriteStore(READ_SIZE, isHistory); + while (transactionStoreManager.hasRemaining(isHistory)) { + List stores = transactionStoreManager.readWriteStoreFromFile(READ_SIZE, isHistory); restore(stores, unhandledBranchBuffer); } } @@ -146,40 +131,31 @@ private void restore(List stores, Map stores, Map byteBufferThreadLocal = ThreadLocal.withInitial(() -> ByteBuffer.allocate( MAX_GLOBAL_SESSION_SIZE)); - private String xid; - private long transactionId; private volatile GlobalStatus status; @@ -64,9 +61,7 @@ public class GlobalSession implements SessionLifecycle, SessionStorable { private long beginTime; - private String applicationData; - - private boolean active = true; + private boolean active; private ArrayList branchSessions = new ArrayList<>(); @@ -170,7 +165,7 @@ public void end() throws TransactionException { } - public void clean() throws TransactionException { + private void clean() throws TransactionException { for (BranchSession branchSession : branchSessions) { branchSession.unlock(); } @@ -287,7 +282,6 @@ public GlobalSession(String applicationId, String transactionServiceGroup, Strin this.transactionServiceGroup = transactionServiceGroup; this.transactionName = transactionName; this.timeout = timeout; - this.xid = XID.generateXID(transactionId); } /** @@ -299,15 +293,6 @@ public long getTransactionId() { return transactionId; } - /** - * Sets transaction id. - * - * @param transactionId the transaction id - */ - public void setTransactionId(long transactionId) { - this.transactionId = transactionId; - } - /** * Gets status. * @@ -322,28 +307,10 @@ public GlobalStatus getStatus() { * * @param status the status */ - public void setStatus(GlobalStatus status) { + void setStatus(GlobalStatus status) { this.status = status; } - /** - * Gets xid. - * - * @return the xid - */ - public String getXid() { - return xid; - } - - /** - * Sets xid. - * - * @param xid the xid - */ - public void setXid(String xid) { - this.xid = xid; - } - /** * Gets application id. * @@ -389,32 +356,6 @@ public long getBeginTime() { return beginTime; } - /** - * Sets begin time. - * - * @param beginTime the begin time - */ - public void setBeginTime(long beginTime) { - this.beginTime = beginTime; - } - - /** - * Gets application data. - * - * @return the application data - */ - public String getApplicationData() { - return applicationData; - } - - /** - * Sets application data. - * - * @param applicationData the application data - */ - public void setApplicationData(String applicationData) { - this.applicationData = applicationData; - } /** * Create global session global session. @@ -449,11 +390,7 @@ public byte[] encode() { byte[] byTxNameBytes = transactionName != null ? transactionName.getBytes() : null; - byte[] xidBytes = xid != null ? xid.getBytes():null; - - byte[] applicationDataBytes = applicationData != null ? applicationData.getBytes():null; - - int size = calGlobalSessionSize(byApplicationIdBytes, byServiceGroupBytes, byTxNameBytes, xidBytes, applicationDataBytes); + int size = calGlobalSessionSize(byApplicationIdBytes, byServiceGroupBytes, byTxNameBytes); if (size > MAX_GLOBAL_SESSION_SIZE) { throw new RuntimeException("global session size exceeded, size : " + size + " maxBranchSessionSize : " + @@ -483,19 +420,6 @@ public byte[] encode() { } else { byteBuffer.putShort((short)0); } - if(xidBytes != null){ - byteBuffer.putInt(xidBytes.length); - byteBuffer.put(xidBytes); - }else { - byteBuffer.putInt(0); - } - if(applicationDataBytes != null){ - byteBuffer.putInt(applicationDataBytes.length); - byteBuffer.put(applicationDataBytes); - }else { - byteBuffer.putInt(0); - } - byteBuffer.putLong(beginTime); byteBuffer.put((byte)status.getCode()); byteBuffer.flip(); @@ -504,20 +428,17 @@ public byte[] encode() { return result; } - private int calGlobalSessionSize(byte[] byApplicationIdBytes, byte[] byServiceGroupBytes, byte[] byTxNameBytes, - byte[] xidBytes, byte[] applicationDataBytes) { + private int calGlobalSessionSize(byte[] byApplicationIdBytes, byte[] byServiceGroupBytes, byte[] byTxNameBytes) { final int size = 8 // trascationId - + 4 // timeout - + 2 // byApplicationIdBytes.length - + 2 // byServiceGroupBytes.length - + 2 // byTxNameBytes.length - + 8 // beginTime - + 1 // statusCode - + (byApplicationIdBytes == null ? 0 : byApplicationIdBytes.length) - + (byServiceGroupBytes == null ? 0 : byServiceGroupBytes.length) - + (byTxNameBytes == null ? 0 : byTxNameBytes.length) - + (xidBytes ==null ? 0 : xidBytes.length) - + (applicationDataBytes == null ? 0 : applicationDataBytes.length); + + 4 // timeout + + 2 // byApplicationIdBytes.length + + 2 // byServiceGroupBytes.length + + 2 // byTxNameBytes.length + + 8 // beginTime + + 1 // statusCode + + (byApplicationIdBytes == null ? 0 : byApplicationIdBytes.length) + + (byServiceGroupBytes == null ? 0 : byServiceGroupBytes.length) + + (byTxNameBytes == null ? 0 : byTxNameBytes.length); return size; } @@ -544,19 +465,6 @@ public void decode(byte[] a) { byteBuffer.get(byTxName); this.transactionName = new String(byTxName); } - int xidLen = byteBuffer.getInt(); - if(xidLen > 0 ){ - byte[] xidBytes = new byte[xidLen]; - byteBuffer.get(xidBytes); - this.xid = new String(xidBytes); - } - int applicationDataLen = byteBuffer.getInt(); - if(applicationDataLen > 0){ - byte[] applicationDataLenBytes = new byte[applicationDataLen]; - byteBuffer.get(applicationDataLenBytes); - this.applicationData = new String(applicationDataLenBytes); - } - this.beginTime = byteBuffer.getLong(); this.status = GlobalStatus.get(byteBuffer.get()); } diff --git a/server/src/main/java/io/seata/server/session/SessionCondition.java b/server/src/main/java/io/seata/server/session/SessionCondition.java index 1b192bb0c85..4063d7aa378 100644 --- a/server/src/main/java/io/seata/server/session/SessionCondition.java +++ b/server/src/main/java/io/seata/server/session/SessionCondition.java @@ -15,8 +15,6 @@ */ package io.seata.server.session; -import io.seata.core.model.GlobalStatus; - /** * The type Session condition. * @@ -24,45 +22,8 @@ * @date 2018 /12/13 */ public class SessionCondition { - private Long transactionId; - private String xid; - private GlobalStatus status; - private GlobalStatus[] statuses; - private long overTimeAliveMills; - - /** - * Instantiates a new Session condition. - */ - public SessionCondition() { - } - /** - * Instantiates a new Session condition. - * - * @param xid the xid - */ - public SessionCondition(String xid) { - this.xid = xid; - } - - /** - * Instantiates a new Session condition. - * - * @param status the status - */ - public SessionCondition(GlobalStatus status) { - this.status = status; - statuses = new GlobalStatus[]{status}; - } - - /** - * Instantiates a new Session condition. - * - * @param statuses the statuses - */ - public SessionCondition(GlobalStatus[] statuses) { - this.statuses = statuses; - } + private long overTimeAliveMills; /** * Instantiates a new Session condition. @@ -73,23 +34,6 @@ public SessionCondition( long overTimeAliveMills) { this.overTimeAliveMills = overTimeAliveMills; } - /** - * Gets status. - * - * @return the status - */ - public GlobalStatus getStatus() { - return status; - } - - /** - * Sets status. - * - * @param status the status - */ - public void setStatus(GlobalStatus status) { - this.status = status; - } /** * Gets over time alive mills. @@ -108,28 +52,4 @@ public long getOverTimeAliveMills() { public void setOverTimeAliveMills(long overTimeAliveMills) { this.overTimeAliveMills = overTimeAliveMills; } - - public Long getTransactionId() { - return transactionId; - } - - public void setTransactionId(Long transactionId) { - this.transactionId = transactionId; - } - - public String getXid() { - return xid; - } - - public void setXid(String xid) { - this.xid = xid; - } - - public GlobalStatus[] getStatuses() { - return statuses; - } - - public void setStatuses(GlobalStatus[] statuses) { - this.statuses = statuses; - } } diff --git a/server/src/main/java/io/seata/server/session/SessionHelper.java b/server/src/main/java/io/seata/server/session/SessionHelper.java index fec302b1535..b3295d24e8f 100644 --- a/server/src/main/java/io/seata/server/session/SessionHelper.java +++ b/server/src/main/java/io/seata/server/session/SessionHelper.java @@ -47,7 +47,6 @@ public static BranchSession newBranchByGlobal(GlobalSession globalSession, Branc String applicationData, String lockKeys, String clientId) { BranchSession branchSession = new BranchSession(); - branchSession.setXid(globalSession.getXid()); branchSession.setTransactionId(globalSession.getTransactionId()); branchSession.setBranchId(UUIDGenerator.generateUUID()); branchSession.setBranchType(branchType); diff --git a/server/src/main/java/io/seata/server/session/SessionHolder.java b/server/src/main/java/io/seata/server/session/SessionHolder.java index 316b6e11d99..30f4b4d00b3 100644 --- a/server/src/main/java/io/seata/server/session/SessionHolder.java +++ b/server/src/main/java/io/seata/server/session/SessionHolder.java @@ -21,7 +21,6 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.exception.StoreException; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; @@ -47,11 +46,6 @@ public class SessionHolder { */ protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - /** - * The constant DEFAULT. - */ - public static final String DEFAULT = "default"; - /** * The constant ROOT_SESSION_MANAGER_NAME. */ @@ -88,33 +82,23 @@ public static void init(String mode) throws IOException { //the store mode StoreMode storeMode = StoreMode.valueof(mode); if (StoreMode.DB.equals(storeMode)) { - //database store - ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name()); - ASYNC_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name(), new Object[]{ASYNC_COMMITTING_SESSION_MANAGER_NAME});; - RETRY_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name(), new Object[]{RETRY_COMMITTING_SESSION_MANAGER_NAME});; - RETRY_ROLLBACKING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.DB.name(), new Object[]{RETRY_ROLLBACKING_SESSION_MANAGER_NAME});; + //TODO database store + } else if (StoreMode.FILE.equals(storeMode)) { //file store String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR); if (sessionStorePath == null) { throw new StoreException("the {store.file.dir} is empty."); } - ROOT_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, StoreMode.FILE.name(), new Object[]{ROOT_SESSION_MANAGER_NAME, sessionStorePath}); - ASYNC_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, DEFAULT, new Object[]{ASYNC_COMMITTING_SESSION_MANAGER_NAME});; - RETRY_COMMITTING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, DEFAULT, new Object[]{RETRY_COMMITTING_SESSION_MANAGER_NAME});; - RETRY_ROLLBACKING_SESSION_MANAGER = EnhancedServiceLoader.load(SessionManager.class, DEFAULT, new Object[]{RETRY_ROLLBACKING_SESSION_MANAGER_NAME});; + ROOT_SESSION_MANAGER = new FileBasedSessionManager(ROOT_SESSION_MANAGER_NAME, sessionStorePath); + ASYNC_COMMITTING_SESSION_MANAGER = new DefaultSessionManager(ASYNC_COMMITTING_SESSION_MANAGER_NAME); + RETRY_COMMITTING_SESSION_MANAGER = new DefaultSessionManager(RETRY_COMMITTING_SESSION_MANAGER_NAME); + RETRY_ROLLBACKING_SESSION_MANAGER = new DefaultSessionManager(RETRY_ROLLBACKING_SESSION_MANAGER_NAME); } else { //unknown store throw new IllegalArgumentException("unknown store mode:" + mode); } - //relaod - reload(); - } - /** - * Reload. - */ - protected static void reload(){ if (ROOT_SESSION_MANAGER instanceof Reloadable) { ((Reloadable) ROOT_SESSION_MANAGER).reload(); @@ -189,6 +173,7 @@ protected static void reload(){ }); } } + } /** @@ -242,11 +227,11 @@ public static final SessionManager getRetryRollbackingSessionManager() { /** * Find global session. * - * @param xid the xid + * @param transactionId the transaction id * @return the global session */ - public static GlobalSession findGlobalSession(String xid) { - return getRootSessionManager().findGlobalSession(xid); + public static GlobalSession findGlobalSession(Long transactionId) { + return getRootSessionManager().findGlobalSession(transactionId); } public static void destory() { diff --git a/server/src/main/java/io/seata/server/session/SessionManager.java b/server/src/main/java/io/seata/server/session/SessionManager.java index e7e94017191..2883d440482 100644 --- a/server/src/main/java/io/seata/server/session/SessionManager.java +++ b/server/src/main/java/io/seata/server/session/SessionManager.java @@ -41,10 +41,11 @@ public interface SessionManager extends SessionLifecycleListener, Disposable { /** * Find global session global session. * - * @param xid the xid + * @param transactionId the transaction id * @return the global session + * @throws TransactionException the transaction exception */ - GlobalSession findGlobalSession(String xid) ; + GlobalSession findGlobalSession(Long transactionId); /** * Update global session status. diff --git a/server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java b/server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java deleted file mode 100644 index 333b78e3ba1..00000000000 --- a/server/src/main/java/io/seata/server/session/db/DataBaseSessionManager.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session.db; - -import io.seata.common.exception.StoreException; -import io.seata.common.executor.Initialize; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.LoadLevel; -import io.seata.common.util.StringUtils; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.StoreMode; -import io.seata.server.session.AbstractSessionManager; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.session.SessionHolder; -import io.seata.server.session.SessionLifecycleListener; -import io.seata.server.session.SessionManager; -import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.TransactionStoreManager.LogOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.List; - -/** - * The Data base session manager. - * - * @author zhangsen - * @data 2019 /4/4 - */ -@LoadLevel(name = "db") -public class DataBaseSessionManager extends AbstractSessionManager implements SessionManager, SessionLifecycleListener, Initialize { - - /** - * The constant LOGGER. - */ - protected static final Logger LOGGER = LoggerFactory.getLogger(DataBaseSessionManager.class); - - /** - * The Task name. - */ - protected String taskName; - - /** - * Instantiates a new Data base session manager. - */ - public DataBaseSessionManager() { - super(); - } - - /** - * Instantiates a new Data base session manager. - * - * @param name the name - */ - public DataBaseSessionManager(String name) { - super(); - this.taskName = name; - } - - @Override - public void init() { - transactionStoreManager = EnhancedServiceLoader.load(TransactionStoreManager.class, StoreMode.DB.name()); - } - - @Override - public void addGlobalSession(GlobalSession session) throws TransactionException { - if (StringUtils.isBlank(taskName)) { - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_ADD, session); - if (!ret) { - throw new StoreException("addGlobalSession failed."); - } - }else { - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); - if (!ret) { - throw new StoreException("addGlobalSession failed."); - } - } - } - - @Override - public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { - if (StringUtils.isNotBlank(taskName)) { - return; - } - session.setStatus(status); - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session); - if (!ret) { - throw new StoreException("updateGlobalSessionStatus failed."); - } - } - - @Override - public void removeGlobalSession(GlobalSession session) throws TransactionException { - if (StringUtils.isNotBlank(taskName)) { - return; - } - boolean ret = transactionStoreManager.writeSession(LogOperation.GLOBAL_REMOVE, session); - if (!ret) { - throw new StoreException("removeGlobalSession failed."); - } - } - - @Override - public void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { - if (StringUtils.isNotBlank(taskName)) { - return; - } - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_ADD, session); - if (!ret) { - throw new StoreException("addBranchSession failed."); - } - } - - @Override - public void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException { - if (StringUtils.isNotBlank(taskName)) { - return; - } - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_UPDATE, session); - if (!ret) { - throw new StoreException("updateBranchSessionStatus failed."); - } - } - - @Override - public void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException { - if (StringUtils.isNotBlank(taskName)) { - return; - } - boolean ret = transactionStoreManager.writeSession(LogOperation.BRANCH_REMOVE, session); - if (!ret) { - throw new StoreException("removeBranchSession failed."); - } - } - - @Override - public GlobalSession findGlobalSession(String xid) { - return transactionStoreManager.readSession(xid); - } - - @Override - public Collection allSessions() { - //get by taskName - if (SessionHolder.ASYNC_COMMITTING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { - return findGlobalSessions(new SessionCondition(GlobalStatus.AsyncCommitting)); - } else if (SessionHolder.RETRY_COMMITTING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { - return findGlobalSessions(new SessionCondition(new GlobalStatus[]{GlobalStatus.CommitRetrying})); - } else if (SessionHolder.RETRY_ROLLBACKING_SESSION_MANAGER_NAME.equalsIgnoreCase(taskName)) { - return findGlobalSessions(new SessionCondition(new GlobalStatus[]{GlobalStatus.RollbackRetrying, - GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying})); - } else { - //all data - return findGlobalSessions(new SessionCondition(new GlobalStatus[]{ - GlobalStatus.UnKnown, GlobalStatus.Begin, - GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Rollbacking, GlobalStatus.RollbackRetrying, - GlobalStatus.TimeoutRollbacking, GlobalStatus.TimeoutRollbackRetrying, GlobalStatus.AsyncCommitting})); - } - } - - @Override - public List findGlobalSessions(SessionCondition condition) { - //nothing need to do - return transactionStoreManager.readSession(condition); - } - - - -} \ No newline at end of file diff --git a/server/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java b/server/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java deleted file mode 100644 index f024bd772bf..00000000000 --- a/server/src/main/java/io/seata/server/store/AbstractTransactionStoreManager.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store; - -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; - -import java.util.List; - -/** - * The type Abstract transaction store manager. - * - * @author zhangsen - * @data 2019 /4/25 - */ -public abstract class AbstractTransactionStoreManager implements TransactionStoreManager { - - @Override - public GlobalSession readSession(String xid) { - return null; - } - - @Override - public List readSession(SessionCondition sessionCondition) { - return null; - } - - @Override - public void shutdown() { - } -} diff --git a/server/src/main/java/io/seata/server/store/file/FileTransactionStoreManager.java b/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java similarity index 92% rename from server/src/main/java/io/seata/server/store/file/FileTransactionStoreManager.java rename to server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java index 5f8e42d8a31..9b3a32229c5 100644 --- a/server/src/main/java/io/seata/server/store/file/FileTransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java @@ -13,7 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.store.file; +package io.seata.server.store; + +import io.seata.common.thread.NamedThreadFactory; +import io.seata.common.util.CollectionUtils; +import io.seata.server.session.BranchSession; +import io.seata.server.session.GlobalSession; +import io.seata.server.session.SessionCondition; +import io.seata.server.session.SessionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -24,39 +33,17 @@ import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; -import io.seata.common.exception.StoreException; -import io.seata.common.loader.LoadLevel; -import io.seata.common.thread.NamedThreadFactory; -import io.seata.common.util.CollectionUtils; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.session.SessionManager; -import io.seata.server.store.AbstractTransactionStoreManager; -import io.seata.server.store.FlushDiskMode; -import io.seata.server.store.ReloadableStore; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.StoreConfig; -import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.TransactionWriteStore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * The type File transaction store manager. * * @author jimin.jm @alibaba-inc.com */ -@LoadLevel(name = "file") -public class FileTransactionStoreManager extends AbstractTransactionStoreManager implements TransactionStoreManager, ReloadableStore { +public class FileTransactionStoreManager implements TransactionStoreManager { + private static final Logger LOGGER = LoggerFactory.getLogger(FileTransactionStoreManager.class); private static final int MAX_THREAD_WRITE = 1; @@ -132,7 +119,8 @@ public class FileTransactionStoreManager extends AbstractTransactionStoreManager */ public FileTransactionStoreManager(String fullFileName, SessionManager sessionManager) throws IOException { initFile(fullFileName); - fileWriteExecutor = new ThreadPoolExecutor(MAX_THREAD_WRITE, MAX_THREAD_WRITE, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, + fileWriteExecutor = + new ThreadPoolExecutor(MAX_THREAD_WRITE, MAX_THREAD_WRITE, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new NamedThreadFactory("fileTransactionStore", MAX_THREAD_WRITE, true)); writeDataFileRunnable = new WriteDataFileRunnable(); @@ -259,16 +247,6 @@ private boolean findTimeoutAndSave() throws IOException { return false; } - @Override - public GlobalSession readSession(String xid) { - throw new StoreException("unsupport for read from file, xid:" + xid); - } - - @Override - public List readSession(SessionCondition sessionCondition) { - throw new StoreException("unsupport for read from file"); - } - @Override public void shutdown() { if (null != fileWriteExecutor) { @@ -279,7 +257,7 @@ public void shutdown() { ++retry; try { Thread.sleep(SHUTDOWN_CHECK_INTERNAL); - } catch (InterruptedException ignore) { + } catch (InterruptedException exx) { } } if (retry >= MAX_SHUTDOWN_RETRY) { @@ -295,7 +273,7 @@ public void shutdown() { } @Override - public List readWriteStore(int readSize, boolean isHistory) { + public List readWriteStoreFromFile(int readSize, boolean isHistory) { File file = null; long currentOffset = 0; if (isHistory) { @@ -327,7 +305,7 @@ public boolean hasRemaining(boolean isHistory) { raf = new RandomAccessFile(file, "r"); return currentOffset < raf.length(); - } catch (IOException ignore) { + } catch (IOException exx) { } finally { closeFile(raf); } @@ -534,7 +512,7 @@ public void run() { StoreRequest storeRequest = storeRequests.poll(MAX_WAIT_TIME_MILLS, TimeUnit.MILLISECONDS); handleStoreRequest(storeRequest); } catch (Exception exx) { - LOGGER.error("write file error: {}", exx.getMessage(), exx); + LOGGER.error("write file error", exx.getMessage()); } } handleRestRequest(); diff --git a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java index 26dc122009c..da7d44a4ad9 100644 --- a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java @@ -15,9 +15,6 @@ */ package io.seata.server.store; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; - import java.util.List; /** @@ -36,28 +33,27 @@ public interface TransactionStoreManager { */ boolean writeSession(LogOperation logOperation, SessionStorable session); - /** - * Read global session global session. - * - * @param xid the xid - * @return the global session + * Shutdown. */ - GlobalSession readSession(String xid); + void shutdown(); /** - * Read session by status list. + * Read write store from file list. * - * @param sessionCondition the session condition + * @param readSize the read size + * @param isHistory the is history * @return the list */ - List readSession(SessionCondition sessionCondition); + List readWriteStoreFromFile(int readSize, boolean isHistory); /** - * Shutdown. + * Has remaining boolean. + * + * @param isHistory the is history + * @return the boolean */ - void shutdown(); - + boolean hasRemaining(boolean isHistory); /** * The enum Log operation. diff --git a/server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java b/server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java deleted file mode 100644 index 1cce734f8ea..00000000000 --- a/server/src/main/java/io/seata/server/store/db/DatabaseTransactionStoreManager.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store.db; - - -import io.seata.common.exception.StoreException; -import io.seata.common.executor.Initialize; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.LoadLevel; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; -import io.seata.core.constants.ConfigurationKeys; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.BranchTransactionDO; -import io.seata.core.store.GlobalTransactionDO; -import io.seata.core.store.LogStore; -import io.seata.core.store.StoreMode; -import io.seata.core.store.db.DataSourceGenerator; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.store.AbstractTransactionStoreManager; -import io.seata.server.store.SessionStorable; -import io.seata.server.store.TransactionStoreManager; - -import javax.sql.DataSource; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * The type Database transaction store manager. - * - * @author zhangsen - * @data 2019 /4/2 - */ -@LoadLevel(name = "db") -public class DatabaseTransactionStoreManager extends AbstractTransactionStoreManager implements TransactionStoreManager, Initialize { - - /** - * The constant CONFIG. - */ - protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - - /** - * The constant DEFAULT_LOG_QUERY_LIMIT. - */ - protected static final int DEFAULT_LOG_QUERY_LIMIT = 100; - - /** - * is inited - */ - protected AtomicBoolean inited = new AtomicBoolean(false); - - /** - * The Log store. - */ - protected LogStore logStore ; - - - /** - * The Log query limit. - */ - protected int logQueryLimit ; - - /** - * Instantiates a new Database transaction store manager. - */ - public DatabaseTransactionStoreManager(){ - } - - @Override - public synchronized void init(){ - if(inited.get()){ - return ; - } - logQueryLimit = CONFIG.getInt(ConfigurationKeys.STORE_DB_LOG_QUERY_LIMIT, DEFAULT_LOG_QUERY_LIMIT); - String datasourceType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); - //init dataSource - DataSourceGenerator dataSourceGenerator = EnhancedServiceLoader.load(DataSourceGenerator.class, datasourceType); - DataSource logStoreDataSource = dataSourceGenerator.generateDataSource(); - logStore = EnhancedServiceLoader.load(LogStore.class, StoreMode.DB.name(), new Class[]{DataSource.class}, new Object[]{logStoreDataSource}); - inited.set(true); - } - - @Override - public boolean writeSession(LogOperation logOperation, SessionStorable session) { - if (LogOperation.GLOBAL_ADD.equals(logOperation)){ - logStore.insertGlobalTransactionDO(convertGlobalTransactionDO(session)); - }else if(LogOperation.GLOBAL_UPDATE.equals(logOperation)){ - logStore.updateGlobalTransactionDO(convertGlobalTransactionDO(session)); - }else if(LogOperation.GLOBAL_REMOVE.equals(logOperation)){ - logStore.deleteGlobalTransactionDO(convertGlobalTransactionDO(session)); - }else if(LogOperation.BRANCH_ADD.equals(logOperation)){ - logStore.insertBranchTransactionDO(convertBranchTransactionDO(session)); - }else if(LogOperation.BRANCH_UPDATE.equals(logOperation)){ - logStore.updateBranchTransactionDO(convertBranchTransactionDO(session)); - }else if(LogOperation.BRANCH_REMOVE.equals(logOperation)){ - logStore.deleteBranchTransactionDO(convertBranchTransactionDO(session)); - }else { - throw new StoreException("Unknown LogOperation:" + logOperation.name()); - } - return true; - } - - /** - * Read session global session. - * - * @param transactionId the transaction id - * @return the global session - */ - public GlobalSession readSession(Long transactionId) { - //global transaction - GlobalTransactionDO globalTransactionDO = logStore.queryGlobalTransactionDO(transactionId); - if(globalTransactionDO == null){ - return null; - } - //branch transactions - List branchTransactionDOs = logStore.queryBranchTransactionDO(globalTransactionDO.getXid()); - return getGlobalSession(globalTransactionDO, branchTransactionDOs); - } - - /** - * Read session global session. - * - * @param xid the xid - * @return the global session - */ - @Override - public GlobalSession readSession(String xid) { - //global transaction - GlobalTransactionDO globalTransactionDO = logStore.queryGlobalTransactionDO(xid); - if(globalTransactionDO == null){ - return null; - } - //branch transactions - List branchTransactionDOs = logStore.queryBranchTransactionDO(globalTransactionDO.getXid()); - return getGlobalSession(globalTransactionDO, branchTransactionDOs); - } - - /** - * Read session list. - * - * @param statuses the statuses - * @return the list - */ - public List readSession(GlobalStatus[] statuses) { - int[] states = new int[statuses.length]; - for(int i = 0; i < statuses.length; i++){ - states[i] = statuses[i].getCode(); - } - List globalSessions = new ArrayList(); - //global transaction - List globalTransactionDOs = logStore.queryGlobalTransactionDO(states, logQueryLimit); - if(CollectionUtils.isEmpty(globalTransactionDOs)){ - return null; - } - for(GlobalTransactionDO globalTransactionDO : globalTransactionDOs){ - List branchTransactionDOs = logStore.queryBranchTransactionDO(globalTransactionDO.getXid()); - globalSessions.add(getGlobalSession(globalTransactionDO, branchTransactionDOs)); - } - return globalSessions; - } - - @Override - public List readSession(SessionCondition sessionCondition) { - if(StringUtils.isNotBlank(sessionCondition.getXid())){ - GlobalSession globalSession = readSession(sessionCondition.getXid()); - if(globalSession != null){ - List globalSessions = new ArrayList(); - globalSessions.add(globalSession); - return globalSessions; - } - }else if(sessionCondition.getTransactionId() != null){ - GlobalSession globalSession = readSession(sessionCondition.getTransactionId()); - if(globalSession != null){ - List globalSessions = new ArrayList(); - globalSessions.add(globalSession); - return globalSessions; - } - }else if(CollectionUtils.isNotEmpty(sessionCondition.getStatuses())){ - return readSession(sessionCondition.getStatuses()); - } - return null; - } - - private GlobalSession getGlobalSession(GlobalTransactionDO globalTransactionDO, List branchTransactionDOs){ - GlobalSession globalSession = convertGlobalSession(globalTransactionDO); - //branch transactions - if(branchTransactionDOs != null && branchTransactionDOs.size() > 0){ - for(BranchTransactionDO branchTransactionDO : branchTransactionDOs){ - globalSession.add(convertBranchSession(branchTransactionDO)); - } - } - return globalSession; - } - - private GlobalSession convertGlobalSession(GlobalTransactionDO globalTransactionDO){ - GlobalSession session = new GlobalSession(globalTransactionDO.getApplicationId(), - globalTransactionDO.getTransactionServiceGroup(), - globalTransactionDO.getTransactionName(), - globalTransactionDO.getTimeout()); - session.setTransactionId(globalTransactionDO.getTransactionId()); - session.setXid(globalTransactionDO.getXid()); - session.setStatus(GlobalStatus.get(globalTransactionDO.getStatus())); - session.setApplicationData(globalTransactionDO.getApplicationData()); - session.setBeginTime(globalTransactionDO.getBeginTime()); - return session; - } - - private BranchSession convertBranchSession(BranchTransactionDO branchTransactionDO){ - BranchSession branchSession = new BranchSession(); - branchSession.setXid(branchTransactionDO.getXid()); - branchSession.setTransactionId(branchTransactionDO.getTransactionId()); - branchSession.setApplicationData(branchTransactionDO.getApplicationData()); - branchSession.setBranchId(branchTransactionDO.getBranchId()); - branchSession.setBranchType(BranchType.valueOf(branchTransactionDO.getBranchType())); - branchSession.setResourceId(branchTransactionDO.getResourceId()); - branchSession.setClientId(branchTransactionDO.getClientId()); - branchSession.setLockKey(branchTransactionDO.getLockKey()); - branchSession.setResourceGroupId(branchTransactionDO.getResourceGroupId()); - branchSession.setStatus(BranchStatus.get(branchTransactionDO.getStatus())); - return branchSession; - } - - private GlobalTransactionDO convertGlobalTransactionDO(SessionStorable session){ - if(session == null || !(session instanceof GlobalSession)){ - throw new IllegalArgumentException("the parameter of SessionStorable is not available, SessionStorable:" + StringUtils.toString(session)); - } - GlobalSession globalSession = (GlobalSession) session; - - GlobalTransactionDO globalTransactionDO = new GlobalTransactionDO(); - globalTransactionDO.setXid(globalSession.getXid()); - globalTransactionDO.setStatus(globalSession.getStatus().getCode()); - globalTransactionDO.setApplicationId(globalSession.getApplicationId()); - globalTransactionDO.setBeginTime(globalSession.getBeginTime()); - globalTransactionDO.setTimeout(globalSession.getTimeout()); - globalTransactionDO.setTransactionId(globalSession.getTransactionId()); - globalTransactionDO.setTransactionName(globalSession.getTransactionName()); - globalTransactionDO.setTransactionServiceGroup(globalSession.getTransactionServiceGroup()); - globalTransactionDO.setApplicationData(globalSession.getApplicationData()); - return globalTransactionDO; - } - - private BranchTransactionDO convertBranchTransactionDO(SessionStorable session){ - if(session == null || !(session instanceof BranchSession)){ - throw new IllegalArgumentException("the parameter of SessionStorable is not available, SessionStorable:" + StringUtils.toString(session)); - } - BranchSession branchSession = (BranchSession) session; - - BranchTransactionDO branchTransactionDO = new BranchTransactionDO(); - branchTransactionDO.setXid(branchSession.getXid()); - branchTransactionDO.setBranchId(branchSession.getBranchId()); - branchTransactionDO.setBranchType(branchSession.getBranchType().name()); - branchTransactionDO.setClientId(branchSession.getClientId()); - branchTransactionDO.setLockKey(branchSession.getLockKey()); - branchTransactionDO.setResourceGroupId(branchSession.getResourceGroupId()); - branchTransactionDO.setTransactionId(branchSession.getTransactionId()); - branchTransactionDO.setApplicationData(branchSession.getApplicationData()); - branchTransactionDO.setResourceId(branchSession.getResourceId()); - branchTransactionDO.setStatus(branchSession.getStatus().getCode()); - return branchTransactionDO; - } - - /** - * Sets log store. - * - * @param logStore the log store - */ - public void setLogStore(LogStore logStore) { - this.logStore = logStore; - } - - /** - * Sets log query limit. - * - * @param logQueryLimit the log query limit - */ - public void setLogQueryLimit(int logQueryLimit) { - this.logQueryLimit = logQueryLimit; - } -} \ No newline at end of file diff --git a/server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java b/server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java deleted file mode 100644 index 2cc8e14929e..00000000000 --- a/server/src/main/java/io/seata/server/store/db/DbcpDataSourceGenerator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store.db; - -import io.seata.common.loader.LoadLevel; -import io.seata.core.store.db.AbstractDataSourceGenerator; -import org.apache.commons.dbcp.BasicDataSource; - -import javax.sql.DataSource; - -/** - * The type Dbcp data source generator. - * - * @author zhangsen - * @data 2019 /4/24 - */ -@LoadLevel(name = "dbcp") -public class DbcpDataSourceGenerator extends AbstractDataSourceGenerator { - - @Override - public DataSource generateDataSource() { - BasicDataSource ds = new BasicDataSource(); - ds.setDriverClassName(getDriverName(getDBType())); - ds.setUrl(getUrl()); - ds.setUsername(getUser()); - ds.setPassword(getPassword()); - ds.setInitialSize(getMinConn()); - ds.setMaxActive(getMaxConn()); - ds.setMinIdle(getMinConn()); - ds.setMaxIdle(getMinConn()); - ds.setMaxWait(5000); - ds.setTimeBetweenEvictionRunsMillis(120000); - ds.setNumTestsPerEvictionRun(1); - ds.setTestWhileIdle(true); - ds.setValidationQuery(getValidationQuery(getDBType())); - ds.setConnectionProperties("useUnicode=yes;characterEncoding=utf8;socketTimeout=5000;connectTimeout=500"); - return ds; - } - - -} diff --git a/server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java b/server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java deleted file mode 100644 index 04ddfe77b63..00000000000 --- a/server/src/main/java/io/seata/server/store/db/DruidDataSourceGenerator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.store.db; - -import com.alibaba.druid.pool.DruidDataSource; -import io.seata.common.loader.LoadLevel; -import io.seata.core.store.db.AbstractDataSourceGenerator; - -import javax.sql.DataSource; - -/** - * The type Druid data source generator. - * - * @author zhangsen - * @data 2019 /4/28 - */ -@LoadLevel(name = "druid") -public class DruidDataSourceGenerator extends AbstractDataSourceGenerator { - - @Override - public DataSource generateDataSource() { - DruidDataSource ds = new DruidDataSource(); - ds.setDriverClassName(getDriverName(getDBType())); - ds.setUrl(getUrl()); - ds.setUsername(getUser()); - ds.setPassword(getPassword()); - ds.setInitialSize(getMinConn()); - ds.setMaxActive(getMaxConn()); - ds.setMinIdle(getMinConn()); - ds.setMaxWait(5000); - ds.setTimeBetweenEvictionRunsMillis(120000); - ds.setMinEvictableIdleTimeMillis(300000); - ds.setTestWhileIdle(true); - ds.setTestOnBorrow(true); - ds.setPoolPreparedStatements(true); - ds.setMaxPoolPreparedStatementPerConnectionSize(20); - ds.setValidationQuery(getValidationQuery(getDBType())); - ds.setDefaultAutoCommit(true); - return ds; - } -} diff --git a/server/src/main/resources/META-INF/services/io.seata.core.lock.Locker b/server/src/main/resources/META-INF/services/io.seata.core.lock.Locker deleted file mode 100644 index d8b311d6e93..00000000000 --- a/server/src/main/resources/META-INF/services/io.seata.core.lock.Locker +++ /dev/null @@ -1,2 +0,0 @@ -io.seata.server.lock.memory.MemoryLocker -io.seata.server.lock.db.DataBaseLocker \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator b/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator deleted file mode 100644 index 68b9548e561..00000000000 --- a/server/src/main/resources/META-INF/services/io.seata.core.store.db.DataSourceGenerator +++ /dev/null @@ -1,2 +0,0 @@ -io.seata.server.store.db.DbcpDataSourceGenerator -io.seata.server.store.db.DruidDataSourceGenerator \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager b/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager deleted file mode 100644 index 9d3f0808a60..00000000000 --- a/server/src/main/resources/META-INF/services/io.seata.server.session.SessionManager +++ /dev/null @@ -1,3 +0,0 @@ -io.seata.server.session.file.FileBasedSessionManager -io.seata.server.session.db.DataBaseSessionManager -io.seata.server.session.DefaultSessionManager \ No newline at end of file diff --git a/server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager b/server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager deleted file mode 100644 index 948d6c079dd..00000000000 --- a/server/src/main/resources/META-INF/services/io.seata.server.store.TransactionStoreManager +++ /dev/null @@ -1,2 +0,0 @@ -io.seata.server.store.db.DatabaseTransactionStoreManager -io.seata.server.store.file.FileTransactionStoreManager \ No newline at end of file diff --git a/server/src/main/resources/db_store.sql b/server/src/main/resources/db_store.sql deleted file mode 100644 index 78b4fa01871..00000000000 --- a/server/src/main/resources/db_store.sql +++ /dev/null @@ -1,52 +0,0 @@ --- the table to store GlobalSession data -drop table `global_table`; -create table `global_table` ( - `xid` varchar(128) not null, - `transaction_id` bigint, - `status` tinyint not null, - `application_id` varchar(32), - `transaction_service_group` varchar(32), - `transaction_name` varchar(64), - `timeout` int, - `begin_time` bigint, - `application_data` varchar(2000), - `gmt_create` datetime, - `gmt_modified` datetime, - primary key (`xid`), - key `idx_gmt_modified_status` (`gmt_modified`, `status`), - key `idx_transaction_id` (`transaction_id`) -); - --- the table to store BranchSession data -drop table `branch_table`; -create table `branch_table` ( - `branch_id` bigint not null, - `xid` varchar(128) not null, - `transaction_id` bigint , - `resource_group_id` varchar(32), - `resource_id` varchar(256) , - `lock_key` varchar(128) , - `branch_type` varchar(8) , - `status` tinyint, - `client_id` varchar(64), - `application_data` varchar(2000), - `gmt_create` datetime, - `gmt_modified` datetime, - primary key (`branch_id`), - key `idx_xid` (`xid`) -); - --- the table to store lock data -drop table `lock_table`; -create table `lock_table` ( - `row_key` varchar(128) not null, - `xid` varchar(96), - `transaction_id` long , - `branch_id` long, - `resource_id` varchar(256) , - `table_name` varchar(32) , - `pk` varchar(32) , - `gmt_create` datetime , - `gmt_modified` datetime, - primary key(`row_key`) -); diff --git a/server/src/main/resources/file.conf b/server/src/main/resources/file.conf index 59e21433299..dc908a344ef 100644 --- a/server/src/main/resources/file.conf +++ b/server/src/main/resources/file.conf @@ -29,9 +29,6 @@ service { enableDegrade = false #disable disable = false - #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent - max.commit.retry.timeout = "-1" - max.rollback.retry.timeout = "-1" } client { @@ -66,44 +63,10 @@ store { ## database store db { - ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. - datasource = "dbcp" - ## mysql/oracle/h2/oceanbase etc. - db-type = "mysql" - url = "jdbc:mysql://127.0.0.1:3306/seata" - user = "mysql" - password = "mysql" - min-conn = 1 - max-conn = 3 - global.table = "global_table" - branch.table = "branch_table" - query-limit = 100 - } -} -lock { - ## the data row lock store mode: local_db、memory or db - mode = "memory" - - memory{ - ## store lock in memory of server - } - - db{ - ## use db of server to store lock, the db is ${store.db.url} - lock-table= "lock_table" - } + driver_class = "" + url = "" + user = "" + password = "" + } - local_db { - ## store lock in local db - } -} -recovery{ - committing-retry-delay = 5 - asyn-committing-retry-delay = 5 - rollbacking-retry-delay = 5 - timeout-retry-delay = 5 } - -transaction { - undo.data.validation = true -} \ No newline at end of file diff --git a/server/src/main/resources/logback.xml b/server/src/main/resources/logback.xml index 4f2b1d02edc..62d9e1acd56 100644 --- a/server/src/main/resources/logback.xml +++ b/server/src/main/resources/logback.xml @@ -41,7 +41,7 @@ - + diff --git a/server/src/main/resources/nacos-config.txt b/server/src/main/resources/nacos-config.txt index b80827982df..254a8db09d4 100644 --- a/server/src/main/resources/nacos-config.txt +++ b/server/src/main/resources/nacos-config.txt @@ -13,8 +13,6 @@ transport.thread-factory.worker-thread-size=8 service.vgroup_mapping.my_test_tx_group=default service.enableDegrade=false service.disable=false -service.max.commit.retry.timeout=-1 -service.max.rollback.retry.timeout=-1 client.async.commit.buffer.limit=10000 client.lock.retry.internal=10 client.lock.retry.times=30 @@ -25,21 +23,7 @@ store.file.max-global-session-size=512 store.file.file-write-buffer-cache-size=16384 store.file.flush-disk-mode=async store.file.session.reload.read_size=100 -store.db.datasource=dbcp -store.db.db-type=mysql -store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true -store.db.user=mysql -store.db.password=mysql -store.db.min-conn=1 -store.db.max-conn=3 -store.db.global.table=global_table -store.db.branch.table=branch_table -store.db.query-limit=100 -lock.mode=memory -lock.db.lock-table=lock_table -recovery.committing-retry-delay = 5 -recovery.asyn-committing-retry-delay = 5 -recovery.rollbacking-retry-delay = 5 -recovery.timeout-retry-delay = 5 -transaction.undo.data.validation=true - +store.db.driver_class=com.mysql.jdbc.Driver +store.db.url=jdbc:mysql://localhost:3306/seata_demo +store.db.user=user +store.db.password=password \ No newline at end of file diff --git a/server/src/main/resources/registry.conf b/server/src/main/resources/registry.conf index 66b963d139a..1cddea72194 100644 --- a/server/src/main/resources/registry.conf +++ b/server/src/main/resources/registry.conf @@ -45,7 +45,7 @@ registry { } config { - # file、nacos 、apollo、zk、consul、etcd3 + # file、nacos 、apollo、zk、consul type = "file" nacos { @@ -65,9 +65,6 @@ config { session.timeout = 6000 connect.timeout = 2000 } - etcd3 { - serverAddr = "http://localhost:2379" - } file { name = "file.conf" } diff --git a/server/src/test/java/WriteStoreMultithreadTest.java b/server/src/test/java/WriteStoreMultithreadTest.java index 360759f5b69..94eb5c88770 100644 --- a/server/src/test/java/WriteStoreMultithreadTest.java +++ b/server/src/test/java/WriteStoreMultithreadTest.java @@ -20,8 +20,8 @@ import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionCondition; import io.seata.server.session.SessionManager; +import io.seata.server.store.FileTransactionStoreManager; import io.seata.server.store.TransactionStoreManager; -import io.seata.server.store.file.FileTransactionStoreManager; import java.util.ArrayList; import java.util.Collection; @@ -55,11 +55,10 @@ public void addGlobalSession(GlobalSession session) throws TransactionException } @Override - public GlobalSession findGlobalSession(String xid) { + public GlobalSession findGlobalSession(Long transactionId) { return null; } - @Override public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException { diff --git a/server/src/test/java/WriteStoreTest.java b/server/src/test/java/WriteStoreTest.java index d2056f75f63..9f9964d1b86 100644 --- a/server/src/test/java/WriteStoreTest.java +++ b/server/src/test/java/WriteStoreTest.java @@ -27,13 +27,11 @@ import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionCondition; import io.seata.server.session.SessionManager; -import io.seata.server.store.ReloadableStore; +import io.seata.server.store.FileTransactionStoreManager; import io.seata.server.store.SessionStorable; import io.seata.server.store.TransactionStoreManager; import io.seata.server.store.TransactionStoreManager.LogOperation; import io.seata.server.store.TransactionWriteStore; -import io.seata.server.store.file.FileTransactionStoreManager; - /** * The type Write store test. @@ -73,7 +71,7 @@ public void addGlobalSession(GlobalSession session) throws TransactionException } @Override - public GlobalSession findGlobalSession(String xid) { + public GlobalSession findGlobalSession(Long transactionId) { return null; } @@ -222,8 +220,8 @@ private static void write(TransactionStoreManager transactionStoreManager) { private static Map readAll(TransactionStoreManager transactionStoreManager) { Map resultMap = new HashMap<>(65535 * 5 * 9); - while (((ReloadableStore)transactionStoreManager).hasRemaining(true)) { - List transactionWriteStores = ((ReloadableStore)transactionStoreManager).readWriteStore(2000, + while (transactionStoreManager.hasRemaining(true)) { + List transactionWriteStores = transactionStoreManager.readWriteStoreFromFile(2000, true); if (null != transactionWriteStores) { for (TransactionWriteStore transactionWriteStore : transactionWriteStores) { @@ -232,8 +230,8 @@ private static Map readAll(TransactionStoreManage } } } - while (((ReloadableStore)transactionStoreManager).hasRemaining(false)) { - List transactionWriteStores = ((ReloadableStore)transactionStoreManager).readWriteStore(2000, + while (transactionStoreManager.hasRemaining(false)) { + List transactionWriteStores = transactionStoreManager.readWriteStoreFromFile(2000, false); if (null != transactionWriteStores) { for (TransactionWriteStore transactionWriteStore : transactionWriteStores) { diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java index d5a03ece983..d68dcf16bb5 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java @@ -31,8 +31,6 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -78,7 +76,7 @@ public static void beforeClass() throws Exception { SessionHolder.init(null); serverMessageSender = new MockServerMessageSender(); defaultCoordinator = new DefaultCoordinator(serverMessageSender); -// defaultCoordinator.init(); + defaultCoordinator.init(); } @ParameterizedTest @@ -107,23 +105,6 @@ public void branchRollback(String xid, Long branchId) { Assertions.assertEquals(result, BranchStatus.PhaseTwo_Rollbacked); } - - @Test - public void test_handleRetryRollbacking() throws TransactionException, InterruptedException { - - String xid = core.begin(applicationId, txServiceGroup, txName, 10); - Long branchId = core.branchRegister(BranchType.AT, "abcd", clientId, xid, applicationData, lockKeys_2); - - Thread.sleep(100); - - defaultCoordinator.timeoutCheck(); - defaultCoordinator.handleRetryRollbacking(); - - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - Assertions.assertNull(globalSession); - - } - @AfterAll public static void afterClass() throws Exception { @@ -183,4 +164,4 @@ public Object sendSyncRequest(String resourceId, String clientId, Object message } } -} \ No newline at end of file +} diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java index 8569001e89a..42b33e4ff5a 100644 --- a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java +++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java @@ -23,7 +23,6 @@ import io.seata.core.model.ResourceManagerInbound; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionHelper; import io.seata.server.session.SessionHolder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -85,7 +84,7 @@ public void initSessionManager() throws Exception { public void branchRegisterTest(String xid) throws Exception { core.branchRegister(BranchType.AT, resourceId, clientId, xid, "abc", lockKeys_1); long transactionId = XID.getTransactionId(xid); - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); Assertions.assertEquals(globalSession.getSortedBranches().size(), 1); //clear @@ -104,7 +103,7 @@ public void branchRegisterTest(String xid) throws Exception { public void branchReportTest(String xid, Long branchId) throws Exception { core.branchReport(BranchType.AT, xid, branchId, BranchStatus.PhaseOne_Done, applicationData); long transactionId = XID.getTransactionId(xid); - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); BranchSession branchSession = globalSession.getBranch(branchId); Assertions.assertEquals(branchSession.getStatus(), BranchStatus.PhaseOne_Done); @@ -121,12 +120,8 @@ public void branchReportTest(String xid, Long branchId) throws Exception { public void beginTest() throws Exception { String xid = core.begin(applicationId, txServiceGroup, txName, timeout); long transactionId = XID.getTransactionId(xid); - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); + GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId); Assertions.assertNotNull(globalSession); - - //clear - globalSession.end(); - } /** @@ -151,9 +146,8 @@ public void commitTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalCommitCommitTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, - applicationData, "t1:1", clientId); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + BranchSession branchSession = new BranchSession(); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseOne_Done)); @@ -174,9 +168,8 @@ public void doGlobalCommitCommitTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalCommitUnretryableTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, - applicationData, "t1:1", clientId); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + BranchSession branchSession = new BranchSession(); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_CommitFailed_Unretryable, BranchStatus.PhaseOne_Done)); @@ -196,9 +189,8 @@ public void doGlobalCommitUnretryableTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalCommitExpTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, - applicationData, "t1:1", clientId); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + BranchSession branchSession = new BranchSession(); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseOne_Timeout, BranchStatus.PhaseOne_Done)); @@ -231,9 +223,8 @@ public void rollBackTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalRollBackRollbackedTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, - applicationData, "t1:1", clientId); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + BranchSession branchSession = new BranchSession(); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_Rollbacked)); @@ -254,9 +245,8 @@ public void doGlobalRollBackRollbackedTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalRollBackUnretryableTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, - applicationData, "t1:1", clientId); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + BranchSession branchSession = new BranchSession(); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_RollbackFailed_Unretryable)); @@ -276,16 +266,14 @@ public void doGlobalRollBackUnretryableTest(String xid) throws Exception { @ParameterizedTest @MethodSource("xidProvider") public void doGlobalRollBackRetryableExpTest(String xid) throws Exception { - GlobalSession globalSession = SessionHolder.findGlobalSession(xid); - BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, resourceId, - applicationData, "t1:1", clientId); + GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid)); + BranchSession branchSession = new BranchSession(); globalSession.addBranch(branchSession); globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done); core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_RollbackFailed_Retryable)); core.doGlobalRollback(globalSession, false); Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.RollbackRetrying); - //clear globalSession.end(); } diff --git a/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerImplTest.java b/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java similarity index 87% rename from server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerImplTest.java rename to server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java index 7bf4148174e..fbe0c216b42 100644 --- a/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerImplTest.java +++ b/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.server.lock.memory; +package io.seata.server.lock; -import io.seata.common.XID; import io.seata.core.model.BranchType; import io.seata.server.UUIDGenerator; -import io.seata.server.lock.LockManager; import io.seata.server.session.BranchSession; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -27,16 +25,15 @@ import java.util.stream.Stream; - /** * The type Default lock manager impl test. * * @author zhimo.xiao @gmail.com * @since 2019 /1/23 */ -public class MemoryLockManagerImplTest { +public class DefaultLockManagerImplTest { - private LockManager lockManager = new MemoryLockManagerForTest();; + private LockManager lockManager = new DefaultLockManagerImpl(); private static final long transactionId = UUIDGenerator.generateUUID(); @@ -53,7 +50,6 @@ public class MemoryLockManagerImplTest { @ParameterizedTest @MethodSource("branchSessionProvider") public void acquireLockTest(BranchSession branchSession) throws Exception { - boolean result = lockManager.acquireLock(branchSession); Assertions.assertTrue(result); branchSession.unlock(); @@ -66,8 +62,7 @@ public void acquireLockTest(BranchSession branchSession) throws Exception { */ @Test public void isLockableTest() throws Exception { - boolean resultOne = lockManager.isLockable(XID.generateXID(transactionId), resourceId, lockKey); - + boolean resultOne = lockManager.isLockable(transactionId, resourceId, lockKey); Assertions.assertTrue(resultOne); } @@ -78,7 +73,6 @@ public void isLockableTest() throws Exception { */ static Stream branchSessionProvider() { BranchSession branchSession = new BranchSession(); - branchSession.setXid(XID.generateXID(transactionId)); branchSession.setBranchId(1L); branchSession.setTransactionId(transactionId); branchSession.setClientId("c1"); diff --git a/server/src/test/java/io/seata/server/lock/LockManagerTest.java b/server/src/test/java/io/seata/server/lock/LockManagerTest.java index f420ebe7635..31084b1358a 100644 --- a/server/src/test/java/io/seata/server/lock/LockManagerTest.java +++ b/server/src/test/java/io/seata/server/lock/LockManagerTest.java @@ -17,7 +17,6 @@ import io.seata.core.model.BranchType; import io.seata.server.UUIDGenerator; -import io.seata.server.lock.memory.MemoryLockManagerForTest; import io.seata.server.session.BranchSession; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; @@ -43,7 +42,7 @@ public class LockManagerTest { @ParameterizedTest @MethodSource("branchSessionProvider") public void acquireLock_success(BranchSession branchSession) throws Exception { - LockManager lockManager = new MemoryLockManagerForTest(); + LockManager lockManager = LockManagerFactory.get(); Assertions.assertTrue(lockManager.acquireLock(branchSession)); } @@ -57,7 +56,7 @@ public void acquireLock_success(BranchSession branchSession) throws Exception { @ParameterizedTest @MethodSource("branchSessionsProvider") public void acquireLock_failed(BranchSession branchSession1, BranchSession branchSession2) throws Exception { - LockManager lockManager = new MemoryLockManagerForTest(); + LockManager lockManager = LockManagerFactory.get(); Assertions.assertTrue(lockManager.acquireLock(branchSession1)); Assertions.assertFalse(lockManager.acquireLock(branchSession2)); } @@ -72,13 +71,13 @@ public void acquireLock_failed(BranchSession branchSession1, BranchSession branc @MethodSource("branchSessionProvider") public void isLockableTest(BranchSession branchSession) throws Exception { branchSession.setLockKey("t:4"); - LockManager lockManager = new MemoryLockManagerForTest(); + LockManager lockManager = LockManagerFactory.get(); Assertions.assertTrue(lockManager - .isLockable(branchSession.getXid(), branchSession.getResourceId(), branchSession.getLockKey())); + .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey())); lockManager.acquireLock(branchSession); branchSession.setTransactionId(UUIDGenerator.generateUUID()); Assertions.assertFalse(lockManager - .isLockable(branchSession.getXid(), branchSession.getResourceId(), branchSession.getLockKey())); + .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey())); } /** diff --git a/server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java b/server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java deleted file mode 100644 index f11485d6408..00000000000 --- a/server/src/test/java/io/seata/server/lock/db/DataBaseLockManagerImplTest.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock.db; - -import io.seata.core.exception.TransactionException; -import io.seata.core.lock.Locker; -import io.seata.core.store.db.LockStoreDataBaseDAO; -import io.seata.server.lock.DefaultLockManager; -import io.seata.server.lock.LockManager; -import io.seata.server.session.BranchSession; -import org.apache.commons.dbcp.BasicDataSource; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - - - -/** - * @author zhangsen - * @data 2019/4/28 - */ -public class DataBaseLockManagerImplTest { - - static LockManager lockManager = null; - - static BasicDataSource dataSource = null; - - static LockStoreDataBaseDAO dataBaseLockStoreDAO = null; - - @BeforeAll - public static void start(){ - dataSource = new BasicDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setUrl("jdbc:h2:./db_store/db_lock"); - dataSource.setUsername("sa"); - dataSource.setPassword(""); - - dataBaseLockStoreDAO = new LockStoreDataBaseDAO(dataSource); - dataBaseLockStoreDAO.setDbType("h2"); - dataBaseLockStoreDAO.setLockTable("lock_table"); - - lockManager = new DBLockManagerForTest(dataBaseLockStoreDAO); - - prepareTable(dataSource); - } - - private static void prepareTable(BasicDataSource dataSource) { - Connection conn = null; - try { - conn = dataSource.getConnection(); - Statement s = conn.createStatement(); - try { - s.execute("drop table lock_table"); - } catch (Exception e) { - } - s.execute("CREATE TABLE lock_table ( xid varchar(96), transaction_id long , branch_id long, resource_id varchar(32) ,table_name varchar(32) ,pk varchar(32) , row_key varchar(128) primary key not null, gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6)) "); - System.out.println("create table lock_table success."); - - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - } - } - - @Test - public void acquireLock() throws TransactionException, SQLException { - BranchSession branchSession = new BranchSession(); - branchSession.setXid("abc-123:786756"); - branchSession.setTransactionId(123543465); - branchSession.setBranchId(5756678); - branchSession.setResourceId("abcss"); - branchSession.setLockKey("t1:13,14;t2:11,12"); - - Assertions.assertTrue(lockManager.acquireLock(branchSession)); - - String sql = "select * from lock_table where xid = 'abc-123:786756'" ; - String sql2 = "select count(*) from lock_table where xid = 'abc-123:786756' " + - "and row_key in ('abcss^^^t1^^^13', 'abcss^^^t1^^^14', 'abcss^^^t2^^^11', 'abcss^^^t2^^^12')" ; - String delSql = "delete from lock_table where xid = 'abc-123:786756'" ; - Connection conn = null; - try { - conn = dataSource.getConnection(); - - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - rs.close(); - - rs = conn.createStatement().executeQuery(sql2); - if(rs.next()){ - Assertions.assertTrue(true); - Assertions.assertEquals(4, rs.getInt(1)); - }else { - Assertions.assertTrue(false); - } - rs.close(); - - conn.createStatement().execute(delSql); - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Test - public void re_acquireLock() throws TransactionException, SQLException { - BranchSession branchSession = new BranchSession(); - branchSession.setXid("abc-123:65867978"); - branchSession.setTransactionId(123543465); - branchSession.setBranchId(5756678); - branchSession.setResourceId("abcss"); - branchSession.setLockKey("t1:53,54;t2:21,32"); - - Assertions.assertTrue(lockManager.acquireLock(branchSession)); - - BranchSession branchSession2 = new BranchSession(); - branchSession2.setXid("abc-123:65867978"); - branchSession2.setTransactionId(123543465); - branchSession2.setBranchId(575667854); - branchSession2.setResourceId("abcss"); - branchSession2.setLockKey("t1:13,14;t2:21,45"); - - Assertions.assertTrue(lockManager.acquireLock(branchSession2)); - - BranchSession branchSession3 = new BranchSession(); - branchSession3.setXid("abc-123:5678789"); - branchSession3.setTransactionId(334123); - branchSession3.setBranchId(5657); - branchSession3.setResourceId("abcss"); - branchSession3.setLockKey("t1:53,14;t2:21,45"); - - Assertions.assertTrue(!lockManager.acquireLock(branchSession3)); - - String delSql = "delete from lock_table where xid in( 'abc-123:65867978' , 'abc-123:65867978' , 'abc-123:5678789' )" ; - Connection conn = null; - try { - conn = dataSource.getConnection(); - - conn.createStatement().execute(delSql); - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - @Test - public void unLock() throws TransactionException, SQLException { - BranchSession branchSession = new BranchSession(); - branchSession.setXid("abc-123:56867"); - branchSession.setTransactionId(1236765); - branchSession.setBranchId(204565); - branchSession.setResourceId("abcss"); - branchSession.setLockKey("t1:3,4;t2:4,5"); - - Assertions.assertTrue(lockManager.acquireLock(branchSession)); - - String sql = "select * from lock_table where xid = 'abc-123:56867'" ; - String sql2 = "select count(*) from lock_table where xid = 'abc-123:56867' " + - "and row_key in ('abcss^^^t1^^^3', 'abcss^^^t1^^^4', 'abcss^^^t2^^^4', 'abcss^^^t2^^^5')" ; - Connection conn = null; - try { - conn = dataSource.getConnection(); - - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else { - Assertions.assertTrue(false); - } - rs.close(); - - rs = conn.createStatement().executeQuery(sql2); - if(rs.next()){ - Assertions.assertTrue(true); - Assertions.assertEquals(4, rs.getInt(1)); - }else { - Assertions.assertTrue(false); - } - rs.close(); - - //un lock - Assertions.assertTrue(lockManager.releaseLock(branchSession)); - - rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(false); - }else { - Assertions.assertTrue(true); - } - rs.close(); - - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - - - - } - - @Test - public void isLockable() throws TransactionException, SQLException { - BranchSession branchSession = new BranchSession(); - branchSession.setXid("abc-123:56877898"); - branchSession.setTransactionId(245686786); - branchSession.setBranchId(467568); - branchSession.setResourceId("abcss"); - branchSession.setLockKey("t1:8,7;t2:1,2"); - - Assertions.assertTrue(lockManager.acquireLock(branchSession)); - - BranchSession branchSession2 = new BranchSession(); - branchSession2.setXid("abc-123:56877898"); - branchSession2.setTransactionId(245686786); - branchSession2.setBranchId(1242354576); - branchSession2.setResourceId("abcss"); - branchSession2.setLockKey("t1:8"); - - Assertions.assertTrue(lockManager.isLockable(branchSession2.getXid(), branchSession2.getResourceId(), branchSession2.getLockKey())); - - BranchSession branchSession3 = new BranchSession(); - branchSession3.setXid("abc-123:4575614354"); - branchSession3.setTransactionId(65867867); - branchSession3.setBranchId(123123); - branchSession3.setResourceId("abcss"); - branchSession3.setLockKey("t2:1,12"); - - Assertions.assertTrue(!lockManager.isLockable(branchSession3.getXid(), branchSession3.getResourceId(), branchSession3.getLockKey())); - - String delSql = "delete from lock_table where xid in( 'abc-123:56877898' , 'abc-123:56877898' , 'abc-123:4575614354' )" ; - Connection conn = null; - try { - conn = dataSource.getConnection(); - - conn.createStatement().execute(delSql); - } finally { - if(conn != null){ - try { - conn.close(); - } catch (SQLException e) { - } - } - } - } - - public static class DBLockManagerForTest extends DefaultLockManager { - - protected LockStoreDataBaseDAO lockStore; - - public DBLockManagerForTest(LockStoreDataBaseDAO db){ - lockStore = db; - } - - @Override - protected Locker getLocker(BranchSession branchSession) { - DataBaseLocker locker = new DataBaseLocker(); - locker.setLockStore(lockStore); - return locker; - } - } -} \ No newline at end of file diff --git a/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java b/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java deleted file mode 100644 index 1bdd7c0c0b7..00000000000 --- a/server/src/test/java/io/seata/server/lock/memory/MemoryLockManagerForTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.lock.memory; - -import io.seata.core.lock.Locker; -import io.seata.server.lock.DefaultLockManager; -import io.seata.server.session.BranchSession; - -/** - * @author zhangsen - * @data 2019-05-16 - */ -public class MemoryLockManagerForTest extends DefaultLockManager { - - @Override - protected Locker getLocker(BranchSession branchSession) { - return new MemoryLocker(branchSession); - } -} diff --git a/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java b/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java index 69b12a0c247..33544245aa5 100644 --- a/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java +++ b/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java @@ -15,7 +15,6 @@ */ package io.seata.server.session; -import io.seata.common.XID; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; @@ -62,7 +61,7 @@ public void addGlobalSessionTest(GlobalSession globalSession) throws Exception { @MethodSource("globalSessionProvider") public void findGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); Assertions.assertNotNull(expected); Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId()); Assertions.assertEquals(expected.getApplicationId(), globalSession.getApplicationId()); @@ -85,7 +84,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex sessionManager.addGlobalSession(globalSession); globalSession.setStatus(GlobalStatus.Finished); sessionManager.updateGlobalSessionStatus(globalSession, GlobalStatus.Finished); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); Assertions.assertNotNull(expected); Assertions.assertEquals(GlobalStatus.Finished, expected.getStatus()); sessionManager.removeGlobalSession(globalSession); @@ -102,7 +101,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex public void removeGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); sessionManager.removeGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); Assertions.assertNull(expected); } @@ -302,10 +301,6 @@ public void onEndTest(GlobalSession globalSession) throws Exception { */ static Stream globalSessionProvider() { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - return Stream.of( Arguments.of(globalSession) ); diff --git a/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java b/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java index 7c58a309b89..803f1200c47 100644 --- a/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java +++ b/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java @@ -15,11 +15,6 @@ */ package io.seata.server.session; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import io.seata.common.XID; import io.seata.core.model.BranchStatus; import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; @@ -29,10 +24,11 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import io.seata.server.session.file.FileBasedSessionManager; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; import java.util.stream.Stream; - /** * The type File based session manager test. * @@ -76,7 +72,7 @@ public void addGlobalSessionTest(GlobalSession globalSession) throws Exception { @MethodSource("globalSessionProvider") public void findGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); Assertions.assertNotNull(expected); Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId()); Assertions.assertEquals(expected.getApplicationId(), globalSession.getApplicationId()); @@ -99,7 +95,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex sessionManager.addGlobalSession(globalSession); globalSession.setStatus(GlobalStatus.Finished); sessionManager.updateGlobalSessionStatus(globalSession, GlobalStatus.Finished); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); Assertions.assertNotNull(expected); Assertions.assertEquals(GlobalStatus.Finished, expected.getStatus()); sessionManager.removeGlobalSession(globalSession); @@ -116,7 +112,7 @@ public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Ex public void removeGlobalSessionTest(GlobalSession globalSession) throws Exception { sessionManager.addGlobalSession(globalSession); sessionManager.removeGlobalSession(globalSession); - GlobalSession expected = sessionManager.findGlobalSession(globalSession.getXid()); + GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId()); Assertions.assertNull(expected); } @@ -316,10 +312,6 @@ public void onEndTest(GlobalSession globalSession) throws Exception { */ static Stream globalSessionProvider() { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - return Stream.of( Arguments.of(globalSession) ); @@ -345,7 +337,6 @@ static Stream globalSessionsProvider() { */ static Stream branchSessionProvider() { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - globalSession.setXid(XID.generateXID(globalSession.getTransactionId())); BranchSession branchSession = new BranchSession(); branchSession.setTransactionId(globalSession.getTransactionId()); branchSession.setBranchId(1L); diff --git a/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java b/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java deleted file mode 100644 index 14b04c30b20..00000000000 --- a/server/src/test/java/io/seata/server/session/db/DataBaseSessionManagerTest.java +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.seata.server.session.db; - -import io.seata.common.XID; -import io.seata.core.exception.TransactionException; -import io.seata.core.model.BranchStatus; -import io.seata.core.model.BranchType; -import io.seata.core.model.GlobalStatus; -import io.seata.core.store.db.LogStoreDataBaseDAO; -import io.seata.server.UUIDGenerator; -import io.seata.server.session.BranchSession; -import io.seata.server.session.GlobalSession; -import io.seata.server.session.SessionCondition; -import io.seata.server.session.SessionManager; -import io.seata.server.store.db.DatabaseTransactionStoreManager; -import org.apache.commons.dbcp.BasicDataSource; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; - -/** - * The type Data base session manager test. - * - * @author zhangsen - * @data 2019 /4/28 - */ -public class DataBaseSessionManagerTest { - - static SessionManager sessionManager = null; - - static LogStoreDataBaseDAO logStoreDataBaseDAO = null; - - static BasicDataSource dataSource = null; - - @BeforeAll - public static void start() throws Exception { - DataBaseSessionManager tempSessionManager = new DataBaseSessionManager(); - DatabaseTransactionStoreManager transactionStoreManager = new DatabaseTransactionStoreManager(); - - dataSource = new BasicDataSource(); - dataSource.setDriverClassName("org.h2.Driver"); - dataSource.setUrl("jdbc:h2:./db_store/db_session"); - dataSource.setUsername("sa"); - dataSource.setPassword(""); - - logStoreDataBaseDAO = new LogStoreDataBaseDAO(dataSource); - logStoreDataBaseDAO.setDbType("h2"); - logStoreDataBaseDAO.setGlobalTable("global_table"); - logStoreDataBaseDAO.setBrachTable("branch_table"); - - transactionStoreManager.setLogQueryLimit(100); - transactionStoreManager.setLogStore(logStoreDataBaseDAO); - - tempSessionManager.setTransactionStoreManager(transactionStoreManager); - sessionManager = tempSessionManager; - - prepareTable(dataSource); - } - - private static void prepareTable(BasicDataSource dataSource) { - Connection conn = null; - try { - conn = dataSource.getConnection(); - Statement s = conn.createStatement(); - try { - s.execute("drop table global_table"); - } catch (Exception e) { - } - s.execute("CREATE TABLE global_table ( xid varchar(96), transaction_id long , STATUS int, application_id varchar(32), transaction_service_group varchar(32) ,transaction_name varchar(32) ,timeout int, begin_time long, application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); - System.out.println("create table global_table success."); - - try { - s.execute("drop table branch_table"); - } catch (Exception e) { - } - s.execute("CREATE TABLE branch_table ( xid varchar(96), transaction_id long , branch_id long, resource_group_id varchar(32), resource_id varchar(32) ,lock_key varchar(64) ,branch_type varchar(32) , status int , client_id varchar(128), application_data varchar(500), gmt_create TIMESTAMP(6) ,gmt_modified TIMESTAMP(6) ) "); - System.out.println("create table branch_table success."); - - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - } - } - - - @Test - public void test_addGlobalSession() throws TransactionException, SQLException { - GlobalSession session = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(session.getTransactionId()); - session.setXid(xid); - session.setTransactionId(146757978); - session.setBeginTime(System.currentTimeMillis()); - session.setApplicationData("abc=878s"); - session.setStatus(GlobalStatus.Begin); - - sessionManager.addGlobalSession(session); - - String sql = "select * from global_table where xid= '"+xid+"'"; - String delSql = "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else{ - Assertions.assertTrue(false); - } - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - - @Test - public void test_updateGlobalSessionStatus() throws TransactionException, SQLException { - GlobalSession session = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(session.getTransactionId()); - session.setXid(xid); - session.setTransactionId(146757978); - session.setBeginTime(System.currentTimeMillis()); - session.setApplicationData("abc=878s"); - session.setStatus(GlobalStatus.Begin); - - sessionManager.addGlobalSession(session); - - session.setStatus(GlobalStatus.Committing); - sessionManager.updateGlobalSessionStatus(session, GlobalStatus.Committing); - - String sql = "select * from global_table where xid= '"+xid+"'"; - String delSql = "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - Assertions.assertEquals(rs.getInt("status"), GlobalStatus.Committing.getCode()); - }else{ - Assertions.assertTrue(false); - } - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void test_removeGlobalSession() throws Exception { - GlobalSession session = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(session.getTransactionId()); - session.setXid(xid); - session.setTransactionId(146757978); - session.setBeginTime(System.currentTimeMillis()); - session.setApplicationData("abc=878s"); - session.setStatus(GlobalStatus.Begin); - - sessionManager.addGlobalSession(session); - - String sql = "select * from global_table where xid= '"+xid+"'"; - String delSql = "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else{ - Assertions.assertTrue(false); - } - rs.close(); - - //delete - sessionManager.removeGlobalSession(session); - - rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(false); - }else{ - Assertions.assertTrue(true); - } - rs.close(); - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void test_findGlobalSession() throws Exception { - GlobalSession session = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(session.getTransactionId()); - session.setXid(xid); - session.setTransactionId(146757978); - session.setBeginTime(System.currentTimeMillis()); - session.setApplicationData("abc=878s"); - session.setStatus(GlobalStatus.Begin); - - sessionManager.addGlobalSession(session); - - GlobalSession globalSession_db = sessionManager.findGlobalSession(session.getXid()); - Assertions.assertNotNull(globalSession_db); - - Assertions.assertEquals(globalSession_db.getTransactionId(), session.getTransactionId()); - Assertions.assertEquals(globalSession_db.getXid(), session.getXid()); - Assertions.assertEquals(globalSession_db.getApplicationData(), session.getApplicationData()); - Assertions.assertEquals(globalSession_db.getApplicationId(), session.getApplicationId()); - Assertions.assertEquals(globalSession_db.getTransactionName(), session.getTransactionName()); - Assertions.assertEquals(globalSession_db.getTransactionServiceGroup(), session.getTransactionServiceGroup()); - Assertions.assertEquals(globalSession_db.getBeginTime(), session.getBeginTime()); - Assertions.assertEquals(globalSession_db.getTimeout(), session.getTimeout()); - Assertions.assertEquals(globalSession_db.getStatus(), session.getStatus()); - - String delSql = "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - - @Test - public void test_addBranchSession() throws Exception { - GlobalSession globalSession = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.setTransactionId(146757978); - globalSession.setBeginTime(System.currentTimeMillis()); - globalSession.setApplicationData("abc=878s"); - globalSession.setStatus(GlobalStatus.Begin); - - BranchSession branchSession = new BranchSession(); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setXid(xid); - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(1L); - branchSession.setResourceGroupId("my_test_tx_group"); - branchSession.setResourceId("tb_1"); - branchSession.setLockKey("t_1"); - branchSession.setBranchType(BranchType.AT); - branchSession.setApplicationData("{\"data\":\"test\"}"); - - sessionManager.addBranchSession(globalSession, branchSession); - - String sql = "select * from branch_table where xid= '"+xid+"'"; - String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - }else{ - Assertions.assertTrue(false); - } - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - - @Test - public void test_updateBranchSessionStatus() throws Exception { - GlobalSession globalSession = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.setTransactionId(146757978); - globalSession.setBeginTime(System.currentTimeMillis()); - globalSession.setApplicationData("abc=878s"); - globalSession.setStatus(GlobalStatus.Begin); - - BranchSession branchSession = new BranchSession(); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setXid(xid); - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(1L); - branchSession.setResourceGroupId("my_test_tx_group"); - branchSession.setResourceId("tb_1"); - branchSession.setLockKey("t_1"); - branchSession.setBranchType(BranchType.AT); - branchSession.setApplicationData("{\"data\":\"test\"}"); - branchSession.setStatus(BranchStatus.PhaseOne_Done); - - sessionManager.addBranchSession(globalSession, branchSession); - - branchSession.setStatus(BranchStatus.PhaseOne_Timeout); - sessionManager.updateBranchSessionStatus(branchSession, BranchStatus.PhaseOne_Timeout); - - String sql = "select * from branch_table where xid= '"+xid+"'"; - String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(true); - Assertions.assertEquals(rs.getInt("status"), BranchStatus.PhaseOne_Timeout.getCode()); - }else{ - Assertions.assertTrue(false); - } - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void test_removeBranchSession() throws Exception { - GlobalSession globalSession = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.setTransactionId(146757978); - globalSession.setBeginTime(System.currentTimeMillis()); - globalSession.setApplicationData("abc=878s"); - globalSession.setStatus(GlobalStatus.Begin); - - BranchSession branchSession = new BranchSession(); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setXid(xid); - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(1L); - branchSession.setResourceGroupId("my_test_tx_group"); - branchSession.setResourceId("tb_1"); - branchSession.setLockKey("t_1"); - branchSession.setBranchType(BranchType.AT); - branchSession.setApplicationData("{\"data\":\"test\"}"); - branchSession.setStatus(BranchStatus.PhaseOne_Done); - - sessionManager.addBranchSession(globalSession, branchSession); - - sessionManager.removeBranchSession(globalSession, branchSession); - - String sql = "select * from branch_table where xid= '"+xid+"'"; - String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - ResultSet rs = conn.createStatement().executeQuery(sql); - if(rs.next()){ - Assertions.assertTrue(false); - }else{ - Assertions.assertTrue(true); - } - - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - - @Test - public void test_allSessions() throws Exception { - GlobalSession globalSession = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.setTransactionId(146757978); - globalSession.setBeginTime(System.currentTimeMillis()); - globalSession.setApplicationData("abc=878s"); - globalSession.setStatus(GlobalStatus.Begin); - - sessionManager.addGlobalSession(globalSession); - - BranchSession branchSession = new BranchSession(); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setXid(xid); - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(1L); - branchSession.setResourceGroupId("my_test_tx_group"); - branchSession.setResourceId("tb_1"); - branchSession.setLockKey("t_1"); - branchSession.setBranchType(BranchType.AT); - branchSession.setClientId("abc-123"); - branchSession.setApplicationData("{\"data\":\"test\"}"); - branchSession.setStatus(BranchStatus.PhaseOne_Done); - - sessionManager.addBranchSession(globalSession, branchSession); - - - BranchSession branchSession2 = new BranchSession(); - branchSession2.setBranchId(UUIDGenerator.generateUUID()); - branchSession2.setXid(xid); - branchSession2.setTransactionId(globalSession.getTransactionId()); - branchSession2.setBranchId(2L); - branchSession2.setResourceGroupId("my_test_tx_group"); - branchSession2.setResourceId("tb_1"); - branchSession2.setLockKey("t_1"); - branchSession2.setBranchType(BranchType.TCC); - branchSession2.setClientId("abc-123"); - branchSession2.setApplicationData("{\"data\":\"test\"}"); - branchSession2.setStatus(BranchStatus.PhaseOne_Done); - - sessionManager.addBranchSession(globalSession, branchSession2); - - Collection rets = sessionManager.allSessions(); - Assertions.assertNotNull(rets); - Assertions.assertEquals(1, rets.size()); - - GlobalSession globalSession_db = (io.seata.server.session.GlobalSession) new ArrayList(rets).get(0); - - Assertions.assertNotNull(globalSession_db.getReverseSortedBranches()); - Assertions.assertEquals(2, globalSession_db.getReverseSortedBranches().size()); - - Assertions.assertNotNull(globalSession_db.getBranch(1L)); - Assertions.assertNotNull(globalSession_db.getBranch(2L)); - - String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - conn.createStatement().execute(delSql); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - @Test - public void test_findGlobalSessions() throws TransactionException, SQLException { - String xid = null; - { - GlobalSession globalSession = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.setTransactionId(146757978); - globalSession.setBeginTime(System.currentTimeMillis()); - globalSession.setApplicationData("abc=878s"); - globalSession.setStatus(GlobalStatus.Begin); - - sessionManager.addGlobalSession(globalSession); - - BranchSession branchSession = new BranchSession(); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setXid(xid); - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(1L); - branchSession.setResourceGroupId("my_test_tx_group"); - branchSession.setResourceId("tb_1"); - branchSession.setLockKey("t_1"); - branchSession.setBranchType(BranchType.AT); - branchSession.setClientId("abc-123"); - branchSession.setApplicationData("{\"data\":\"test\"}"); - branchSession.setStatus(BranchStatus.PhaseOne_Done); - sessionManager.addBranchSession(globalSession, branchSession); - } - String xid2 = null; - { - GlobalSession globalSession = GlobalSession.createGlobalSession("test", - "test", "test123", 100); - xid2 = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.setTransactionId(146757978); - globalSession.setBeginTime(System.currentTimeMillis()); - globalSession.setApplicationData("abc=878s"); - globalSession.setStatus(GlobalStatus.CommitRetrying); - - sessionManager.addGlobalSession(globalSession); - - BranchSession branchSession = new BranchSession(); - branchSession.setBranchId(UUIDGenerator.generateUUID()); - branchSession.setXid(xid2); - branchSession.setTransactionId(globalSession.getTransactionId()); - branchSession.setBranchId(1L); - branchSession.setResourceGroupId("my_test_tx_group"); - branchSession.setResourceId("tb_1"); - branchSession.setLockKey("t_1"); - branchSession.setBranchType(BranchType.AT); - branchSession.setClientId("abc-123"); - branchSession.setApplicationData("{\"data\":\"test\"}"); - branchSession.setStatus(BranchStatus.PhaseOne_Done); - sessionManager.addBranchSession(globalSession, branchSession); - } - - - Collection rets = sessionManager.findGlobalSessions(new SessionCondition( GlobalStatus.Begin)); - Assertions.assertNotNull(rets); - Assertions.assertEquals(1, rets.size()); - - GlobalSession globalSession_db = (io.seata.server.session.GlobalSession) new ArrayList(rets).get(0); - - Assertions.assertNotNull(globalSession_db.getReverseSortedBranches()); - Assertions.assertEquals(1, globalSession_db.getReverseSortedBranches().size()); - - Assertions.assertNotNull(globalSession_db.getBranch(1L)); - - String delSql = "delete from branch_table where xid= '"+xid+"'" + ";" + "delete from global_table where xid= '"+xid+"'"; - String delSql2 = "delete from branch_table where xid= '"+xid2+"'" + ";" + "delete from global_table where xid= '"+xid2+"'"; - Connection conn = null; - try{ - conn = dataSource.getConnection(); - conn.createStatement().execute(delSql); - conn.createStatement().execute(delSql2); - }finally { - if(conn != null){ - conn.close(); - } - } - } - - - - -} \ No newline at end of file diff --git a/server/src/test/java/io/seata/server/store/SessionStoreTest.java b/server/src/test/java/io/seata/server/store/SessionStoreTest.java index 37fecd0d6c4..45048d7f63d 100644 --- a/server/src/test/java/io/seata/server/store/SessionStoreTest.java +++ b/server/src/test/java/io/seata/server/store/SessionStoreTest.java @@ -15,9 +15,6 @@ */ package io.seata.server.store; -import java.io.File; - -import io.seata.common.XID; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; @@ -25,7 +22,7 @@ import io.seata.core.model.BranchType; import io.seata.core.model.GlobalStatus; import io.seata.server.lock.LockManager; -import io.seata.server.lock.memory.MemoryLockManagerForTest; +import io.seata.server.lock.LockManagerFactory; import io.seata.server.session.BranchSession; import io.seata.server.session.GlobalSession; import io.seata.server.session.SessionHelper; @@ -34,6 +31,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.io.File; /** * The type Session store test. @@ -65,8 +63,7 @@ public void clean() throws Exception { if (rootDataFileHis.exists()) { rootDataFileHis.delete(); } - LockManager lockManager = new MemoryLockManagerForTest(); - lockManager.cleanAllLocks(); + LockManagerFactory.get().cleanAllLocks(); } /** @@ -78,48 +75,43 @@ public void clean() throws Exception { public void testRestoredFromFile() throws Exception { SessionHolder.init("file"); GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID, "ta:1,2;tb:3", "xxx"); - branchSession1.setXid(xid); branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = new MemoryLockManagerForTest(); + LockManager lockManager = LockManagerFactory.get(); - String otherXID = XID.generateXID(0L); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3")); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:2")); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:3")); - - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:4")); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:5")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:4")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:5")); lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:2")); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:3")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:2")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:3")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); + GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); Assertions.assertNotNull(reloadSession); Assertions.assertFalse(globalSession == reloadSession); Assertions.assertEquals(globalSession.getApplicationId(), reloadSession.getApplicationId()); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:2")); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "tb:3")); - Assertions.assertTrue(lockManager.isLockable(xid, RESOURCE_ID, "tb:3")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3")); + Assertions.assertTrue(lockManager.isLockable(globalSession.getTransactionId(), RESOURCE_ID, "tb:3")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -153,9 +145,6 @@ public void testRestoredFromFileAsyncCommitting() throws Exception { SessionHolder.init("file"); GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -164,31 +153,29 @@ public void testRestoredFromFileAsyncCommitting() throws Exception { Assertions.assertTrue(branchSession1.lock()); globalSession.addBranch(branchSession1); - LockManager lockManager = new MemoryLockManagerForTest(); - - String otherXID = XID.generateXID(0L); + LockManager lockManager = LockManagerFactory.get(); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.AsyncCommitting); lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); + GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.AsyncCommitting); GlobalSession sessionInAsyncCommittingQueue = SessionHolder.getAsyncCommittingSessionManager() - .findGlobalSession(globalSession.getXid()); + .findGlobalSession(tid); Assertions.assertTrue(reloadSession == sessionInAsyncCommittingQueue); // No locking for session in AsyncCommitting status - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -205,9 +192,6 @@ public void testRestoredFromFileCommitRetry() throws Exception { SessionHolder.init("file"); GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -216,11 +200,9 @@ public void testRestoredFromFileCommitRetry() throws Exception { branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = new MemoryLockManagerForTest(); - - String otherXID = XID.generateXID(0L); + LockManager lockManager = LockManagerFactory.get(); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.Committing); globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Retryable); @@ -228,23 +210,23 @@ public void testRestoredFromFileCommitRetry() throws Exception { lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); + GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.CommitRetrying); GlobalSession sessionInRetryCommittingQueue = SessionHolder.getRetryCommittingSessionManager() - .findGlobalSession(globalSession.getXid()); + .findGlobalSession(tid); Assertions.assertTrue(reloadSession == sessionInRetryCommittingQueue); BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId()); Assertions.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_CommitFailed_Retryable); // Lock is held by session in CommitRetrying status - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -262,9 +244,6 @@ public void testRestoredFromFileRollbackRetry() throws Exception { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -273,11 +252,9 @@ public void testRestoredFromFileRollbackRetry() throws Exception { branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = new MemoryLockManagerForTest(); + LockManager lockManager = LockManagerFactory.get(); - String otherXID = XID.generateXID(0L); - - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.Rollbacking); globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_RollbackFailed_Retryable); @@ -285,23 +262,23 @@ public void testRestoredFromFileRollbackRetry() throws Exception { lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); + GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.RollbackRetrying); GlobalSession sessionInRetryRollbackingQueue = SessionHolder.getRetryRollbackingSessionManager() - .findGlobalSession(globalSession.getXid()); + .findGlobalSession(tid); Assertions.assertTrue(reloadSession == sessionInRetryRollbackingQueue); BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId()); Assertions.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_RollbackFailed_Retryable); // Lock is held by session in RollbackRetrying status - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); //clear reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); @@ -319,9 +296,6 @@ public void testRestoredFromFileRollbackFailed() throws Exception { GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000); - String xid = XID.generateXID(globalSession.getTransactionId()); - globalSession.setXid(xid); - globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager()); globalSession.begin(); @@ -330,28 +304,26 @@ public void testRestoredFromFileRollbackFailed() throws Exception { branchSession1.lock(); globalSession.addBranch(branchSession1); - LockManager lockManager = new MemoryLockManagerForTest(); - - String otherXID = XID.generateXID(0L); + LockManager lockManager = LockManagerFactory.get(); - Assertions.assertFalse(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); globalSession.changeStatus(GlobalStatus.Rollbacking); globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Unretryable); SessionHelper.endRollbackFailed(globalSession); // Lock is released. - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); lockManager.cleanAllLocks(); - Assertions.assertTrue(lockManager.isLockable(otherXID, RESOURCE_ID, "ta:1")); + Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1")); // Re-init SessionHolder: restore sessions from file SessionHolder.init("file"); long tid = globalSession.getTransactionId(); - GlobalSession reloadSession = SessionHolder.findGlobalSession(globalSession.getXid()); + GlobalSession reloadSession = SessionHolder.findGlobalSession(tid); Assertions.assertNull(reloadSession); } } diff --git a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java b/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java index 0fe6860eb5a..dddd5e83c29 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java +++ b/tcc/src/main/java/io/seata/rm/tcc/TwoPhaseResult.java @@ -17,6 +17,9 @@ import io.seata.common.util.StringUtils; +import java.util.HashMap; +import java.util.Map; + /** * the TCC method result * diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java b/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java index 2ff32ca4980..a4cda53d59a 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/remoting/RemotingParser.java @@ -17,6 +17,8 @@ import io.seata.common.exception.FrameworkException; +import java.lang.reflect.InvocationTargetException; + /** * extract remoting bean info * diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java index c4764df599c..d07050c5f34 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParser.java @@ -20,6 +20,7 @@ import io.seata.rm.tcc.api.LocalTCC; import io.seata.rm.tcc.remoting.Protocols; import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.rm.tcc.remoting.RemotingDesc; import java.util.Set; diff --git a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java index 8af247f16f1..ff1cc8349cf 100644 --- a/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java +++ b/tcc/src/main/java/io/seata/rm/tcc/remoting/parser/SofaRpcRemotingParser.java @@ -19,6 +19,8 @@ import io.seata.common.util.ReflectionUtil; import io.seata.rm.tcc.remoting.Protocols; import io.seata.rm.tcc.remoting.RemotingDesc; +import io.seata.rm.tcc.remoting.Protocols; +import io.seata.rm.tcc.remoting.RemotingDesc; /** * sofa-rpc remoting bean parsing diff --git a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java b/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java index 9f3a192b98f..dc5682b9b10 100644 --- a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java +++ b/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java @@ -20,6 +20,9 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import io.seata.core.protocol.ResultCode; +import io.seata.core.protocol.transaction.BranchRegisterRequest; +import io.seata.core.protocol.transaction.BranchRegisterResponse; import io.seata.server.UUIDGenerator; import io.seata.server.coordinator.DefaultCoordinator; diff --git a/test/src/test/resources/file.conf b/test/src/test/resources/file.conf index 65573b25b31..30801f29901 100644 --- a/test/src/test/resources/file.conf +++ b/test/src/test/resources/file.conf @@ -70,7 +70,3 @@ client { } report.retry.count = 5 } - -transaction { - undo.data.validation = true -} \ No newline at end of file diff --git a/test/src/test/resources/registry.conf b/test/src/test/resources/registry.conf index 5115876d916..1cddea72194 100644 --- a/test/src/test/resources/registry.conf +++ b/test/src/test/resources/registry.conf @@ -45,7 +45,7 @@ registry { } config { - # file、nacos 、apollo、zk、consul、etcd3 + # file、nacos 、apollo、zk、consul type = "file" nacos { @@ -65,10 +65,7 @@ config { session.timeout = 6000 connect.timeout = 2000 } - etcd3 { - serverAddr = "http://localhost:2379" - } file { name = "file.conf" } -} \ No newline at end of file +} diff --git a/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java b/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java index 9833634c61f..f4deba4aaf0 100644 --- a/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java +++ b/tm/src/main/java/io/seata/tm/TransactionManagerHolder.java @@ -17,10 +17,16 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.core.exception.TransactionException; +import io.seata.core.exception.TransactionExceptionCode; +import io.seata.core.model.GlobalStatus; import io.seata.core.model.TransactionManager; +import io.seata.core.protocol.transaction.*; +import io.seata.core.rpc.netty.TmRpcClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.TimeoutException; /** * The type Default transaction manager. diff --git a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java index 78e85d66e75..2736c79d282 100644 --- a/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java +++ b/tm/src/main/java/io/seata/tm/api/DefaultGlobalTransaction.java @@ -20,6 +20,7 @@ import io.seata.core.exception.TransactionException; import io.seata.core.model.GlobalStatus; import io.seata.core.model.TransactionManager; +import io.seata.tm.DefaultTransactionManager; import io.seata.tm.TransactionManagerHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From ce86bdce732f5cd0edd7f1e9fbe8dbd7f1cd32d8 Mon Sep 17 00:00:00 2001 From: slievrly Date: Wed, 9 Dec 2020 23:27:34 +0800 Subject: [PATCH 3/5] change version to 1.4.1 Signed-off-by: slievrly --- all/pom.xml | 2 +- bom/pom.xml | 2 +- core/src/main/java/io/seata/core/protocol/Version.java | 2 +- pom.xml | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index d7f7deef75e..038ec45bf14 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -21,7 +21,7 @@ io.seata seata-all - 1.5.0-SNAPSHOT + 1.4.1 Seata All-in-one ${project.version} http://seata.io diff --git a/bom/pom.xml b/bom/pom.xml index 9ab2df9d85e..2901e25f110 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -20,7 +20,7 @@ io.seata seata-bom - 1.5.0-SNAPSHOT + 1.4.1 4.0.0 pom diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java index ff9fa4bca3b..2a6c8cfef76 100644 --- a/core/src/main/java/io/seata/core/protocol/Version.java +++ b/core/src/main/java/io/seata/core/protocol/Version.java @@ -32,7 +32,7 @@ public class Version { /** * The constant CURRENT. */ - private static final String CURRENT = "1.5.0-SNAPSHOT"; + private static final String CURRENT = "1.4.1"; private static final String VERSION_0_7_1 = "0.7.1"; private static final int MAX_VERSION_DOT = 3; diff --git a/pom.xml b/pom.xml index a1f61bba28b..97484f443ba 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ config core discovery - distribution + integration/dubbo integration/dubbo-alibaba integration/sofa-rpc @@ -41,7 +41,7 @@ server spring tcc - test + tm metrics serializer @@ -89,7 +89,7 @@ - 1.5.0-SNAPSHOT + 1.4.1 1.8 @@ -245,7 +245,7 @@ - false + ${project.version},latest From 9569bed4127fa513ba7b27db0891ef9e67a2743f Mon Sep 17 00:00:00 2001 From: slievrly Date: Thu, 10 Dec 2020 13:57:38 +0800 Subject: [PATCH 4/5] release: release 1.4.1 Signed-off-by: slievrly --- all/pom.xml | 1 + bom/pom.xml | 1 + pom.xml | 7 ++++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index 8210ab18028..9a9082d0731 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -778,6 +778,7 @@ oss_seata https://oss.sonatype.org/ false + true diff --git a/bom/pom.xml b/bom/pom.xml index 2901e25f110..41deea42728 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -567,6 +567,7 @@ oss_seata https://oss.sonatype.org/ false + true diff --git a/pom.xml b/pom.xml index 97484f443ba..ccc84e5dff5 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ config core discovery - + distribution integration/dubbo integration/dubbo-alibaba integration/sofa-rpc @@ -41,7 +41,7 @@ server spring tcc - + test tm metrics serializer @@ -212,6 +212,7 @@ oss_seata https://oss.sonatype.org/ false + true @@ -245,7 +246,7 @@ - + false ${project.version},latest From 33eae0c83acaa4e0877066e227ad4277d192e00d Mon Sep 17 00:00:00 2001 From: slievrly Date: Sun, 15 May 2022 23:04:31 +0800 Subject: [PATCH 5/5] add description for release 1.5.0 Signed-off-by: slievrly --- build/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/pom.xml b/build/pom.xml index a2c63599ef3..c3c420bbe0e 100644 --- a/build/pom.xml +++ b/build/pom.xml @@ -25,6 +25,7 @@ ${revision} Seata Build ${project.version} + Seata Build Pom @@ -289,7 +290,7 @@ release - false + true ${project.version},latest