diff --git a/CMakeLists.txt b/CMakeLists.txt index de64a068..726cfa68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,7 +167,7 @@ if (WIN32) add_custom_target( swig ALL - COMMAND cmake -G "${CMAKE_GENERATOR}" "-DHOTRODCPP_HOME=${NATIVE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/swig" + COMMAND cmake -G "${CMAKE_GENERATOR}" "-DHOTRODCPP_HOME=${NATIVE_DIR}" "-DSWIG_DIR=${SWIG_DIR}" "-DSWIG_EXECUTABLE=${SWIG_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/swig" COMMAND cmake --build . --config "${CMAKE_CFG_INTDIR}" WORKING_DIRECTORY "${SWIG_BUILD}" DEPENDS ${PROTO_SRCS} ${TEST_PROTO_SRCS} @@ -416,6 +416,7 @@ if (NOT DEFINED ENABLE_CSHARP_TESTING OR ENABLE_CSHARP_TESTING) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/resources/standalone-hotrod-ssl.xml DESTINATION "${JBOSS_HOME}/standalone/configuration") file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/resources/clustered-sasl-cs.xml DESTINATION "${JBOSS_HOME}/standalone/configuration") file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/resources/clustered.xml DESTINATION "${JBOSS_HOME}/standalone/configuration") + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/resources/standalone.xml DESTINATION "${JBOSS_HOME}/standalone/configuration") file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/resources/certificates/keystore.jks DESTINATION "${JBOSS_HOME}/standalone/configuration") file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/resources/certificates/truststore.jks DESTINATION "${JBOSS_HOME}/standalone/configuration") file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/resources/certificates/keystore_server_sni1_rsa.jks DESTINATION "${JBOSS_HOME}/standalone/configuration") diff --git a/Jenkinsfile b/Jenkinsfile index f9d734ce..fad39d43 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,7 +11,7 @@ pipeline { cppTag = '8.1.0.Final' CMAKE_HOME = 'C:\\\\PROGRA~2\\\\CMake\\\\bin' generator = '"Visual Studio 14 2015 Win64"' - INFINISPAN_VERSION = '9.2.3.Final' + INFINISPAN_VERSION = '9.3.1.Final' JAVA_HOME = 'C:\\\\PROGRA~1\\\\JAVA\\\\JDK18~1.0_7' M2_HOME = 'C:\\\\APACHE~1.9' MVN_PROGRAM = 'C:\\\\APACHE~1.9\\\\BIN\\\\MVN.BAT' @@ -19,15 +19,14 @@ pipeline { PROTOBUF_LIBRARY = 'C:\\\\protobuf-2.6.1-pack\\\\lib\\\\libprotobuf-static.lib' PROTOBUF_PROTOC_EXECUTABLE = 'C:\\\\protobuf-2.6.1-pack\\\\bin\\\\protoc.exe' PROTOBUF_PROTOC_LIBRARY = 'C:\\\\protobuf-2.6.1-pack\\\\lib\\\\libprotoc.lib' - SWIG_DIR = 'C:\\\\PROGRA~1\\\\SWIGWI~1.12' - SWIG_EXECUTABLE = 'C:\\\\PROGRA~1\\\\SWIGWI~1.12\\\\SWIG.EXE' + SWIG_DIR = 'C:\\\\PROGRA~1\\\\SWIGWI~2.12' + SWIG_EXECUTABLE = 'C:\\\\PROGRA~1\\\\SWIGWI~2.12\\\\SWIG.EXE' test32 = 'empty' test64 = 'empty' version_1major = '8' version_2minor = '1' version_3micro = '0' version_4qualifier = 'Final' - HOTROD_LOG_LEVEL = 'TRACE' } steps { dir('cpp-client') { @@ -57,8 +56,8 @@ pipeline { GOOGLE_PROTOBUF_NUPKG = 'C:\\\\Users\\\\Administrator' HOTROD_SNK = 'c:\\\\data\\\\hotrod_cs.key' IKVM_CUSTOM_BIN_PATH = 'C:\\\\Users\\\\Administrator\\\\ikvm-8.1.5717.0\\\\bin' - INFINISPAN_VERSION = '9.2.3.Final' - JBOSS_HOME = 'Y:\\\\cpp-client\\\\infinispan-server-9.2.3.Final' + INFINISPAN_VERSION = '9.3.1.Final' + JBOSS_HOME = 'Y:\\\\cpp-client\\\\infinispan-server-9.3.1.Final' JAVA_HOME = 'C:\\\\PROGRA~1\\\\JAVA\\\\JDK18~1.0_7' M2_HOME = 'C:\\\\APACHE~1.9' MAVEN_OPTS = '"-Dmaven.multiModuleProjectDirectory=C:\\\\APACHE~1.9"' @@ -72,7 +71,7 @@ pipeline { PROTOBUF_PROTOC_EXECUTABLE = 'C:\\\\protobuf-2.6.1-pack\\\\bin\\\\protoc.exe' PROTOBUF_PROTOC_EXECUTABLE_CS = 'C:\\\\Users\\\\Administrator\\\\Google.Protobuf.Tools.3.4.0\\\\tools\\\\windows_x64\\\\protoc.exe' PROTOBUF_PROTOC_LIBRARY = 'C:\\\\protobuf-2.6.1-pack\\\\lib\\\\libprotoc.lib' - SWIG_DIR = 'C:\\\\PROGRA~1\\\\SWIGWI~1.12' + SWIG_DIR = 'C:\\\\PROGRA~1\\\\SWIGWI~2.12' SWIG_EXECUTABLE = 'C:\\\\PROGRA~1\\\\SWIGWI~2.12\\\\SWIG.EXE' test32 = 'skip' test64 = 'run' diff --git a/build.bat b/build.bat index f413aad6..edcd12a4 100644 --- a/build.bat +++ b/build.bat @@ -16,7 +16,7 @@ cd build_windows set "buildTest=%~1" call :unquote u_generator %generator% -cmake -G "%u_generator%" -DHOTRODCPP_HOME=%HOTRODCPP_HOME% -DPROTOBUF_PROTOC_EXECUTABLE_CS="%PROTOBUF_PROTOC_EXECUTABLE_CS%" -DGOOGLE_PROTOBUF_NUPKG="%GOOGLE_PROTOBUF_NUPKG%" -DPROTOBUF_INCLUDE_DIR=%PROTOBUF_INCLUDE_DIR% -DJBOSS_HOME=%JBOSS_HOME% -DIKVM_CUSTOM_BIN_PATH=%IKVM_CUSTOM_BIN_PATH% -DOPENSSL_ROOT_DIR=%OPENSSL_ROOT_DIR% -DCONFIGURATION=RelWithDebInfo %~4 .. +cmake -G "%u_generator%" -DHOTRODCPP_HOME=%HOTRODCPP_HOME% -DSWIG_DIR=%SWIG_DIR% -DSWIG_EXECUTABLE=%SWIG_EXECUTABLE% -DPROTOBUF_PROTOC_EXECUTABLE_CS="%PROTOBUF_PROTOC_EXECUTABLE_CS%" -DGOOGLE_PROTOBUF_NUPKG="%GOOGLE_PROTOBUF_NUPKG%" -DPROTOBUF_INCLUDE_DIR=%PROTOBUF_INCLUDE_DIR% -DJBOSS_HOME=%JBOSS_HOME% -DIKVM_CUSTOM_BIN_PATH=%IKVM_CUSTOM_BIN_PATH% -DOPENSSL_ROOT_DIR=%OPENSSL_ROOT_DIR% -DCONFIGURATION=RelWithDebInfo %~4 .. if %errorlevel% neq 0 goto fail cmake --build . --config RelWithDebInfo diff --git a/src/Infinispan.HotRod/Config/Configuration.cs b/src/Infinispan.HotRod/Config/Configuration.cs index 82832ebc..a0d1245f 100644 --- a/src/Infinispan.HotRod/Config/Configuration.cs +++ b/src/Infinispan.HotRod/Config/Configuration.cs @@ -130,5 +130,23 @@ public IMarshaller Marshaller() { return marshaller; } + + /// + /// Check if this configuration enables transactional operation + /// + /// + public bool IsTransactional() + { + return config.isTransactional(); + } + + /// + /// Enable disable transactional operations + /// + /// true enables transactional operations + public void SetTransactional(bool t) + { + config.setTransactional(t); + } } } \ No newline at end of file diff --git a/src/Infinispan.HotRod/Config/ConfigurationBuilder.cs b/src/Infinispan.HotRod/Config/ConfigurationBuilder.cs index c057c144..763c4707 100644 --- a/src/Infinispan.HotRod/Config/ConfigurationBuilder.cs +++ b/src/Infinispan.HotRod/Config/ConfigurationBuilder.cs @@ -135,7 +135,12 @@ public ConfigurationBuilder Marshaller(IMarshaller marshaller) this.marshaller = marshaller; return this; } - + + public ConfigurationBuilder Transactional(bool t) + { + builder.SetTransactional(t); + return this; + } } #pragma warning restore 1591 } diff --git a/src/Infinispan.HotRod/Exceptions/HotRodClientRollbackException.cs b/src/Infinispan.HotRod/Exceptions/HotRodClientRollbackException.cs new file mode 100644 index 00000000..40606031 --- /dev/null +++ b/src/Infinispan.HotRod/Exceptions/HotRodClientRollbackException.cs @@ -0,0 +1,12 @@ +namespace Infinispan.HotRod.Exceptions +{ + /// + /// Used to indicated that a commit operation actually rolled back + /// + public class HotRodClientRollbackException : HotRodClientException + { + internal HotRodClientRollbackException(string message) : base(message) + { + } + } +} diff --git a/src/Infinispan.HotRod/RemoteCacheManager.cs b/src/Infinispan.HotRod/RemoteCacheManager.cs index 67562582..53d33a1c 100644 --- a/src/Infinispan.HotRod/RemoteCacheManager.cs +++ b/src/Infinispan.HotRod/RemoteCacheManager.cs @@ -256,5 +256,14 @@ public ISet GetCacheNames() { return manager.GetCacheNames(); } + + /// + /// Return the transaction manager + /// + /// + public Infinispan.HotRod.SWIG.TransactionManager GetTransactionManager() + { + return manager.GetTransactionManager(); + } } } diff --git a/src/Infinispan.HotRod/SWIG/Configuration.cs b/src/Infinispan.HotRod/SWIG/Configuration.cs index bd282c50..52d3a2c1 100644 --- a/src/Infinispan.HotRod/SWIG/Configuration.cs +++ b/src/Infinispan.HotRod/SWIG/Configuration.cs @@ -21,5 +21,7 @@ internal interface Configuration IList Servers(); Dictionary> GetServersMapConfiguration(); + bool isTransactional(); + void setTransactional(bool t); } } \ No newline at end of file diff --git a/src/Infinispan.HotRod/SWIG/ConfigurationBuilder.cs b/src/Infinispan.HotRod/SWIG/ConfigurationBuilder.cs index 60f99263..5fb4c0cd 100644 --- a/src/Infinispan.HotRod/SWIG/ConfigurationBuilder.cs +++ b/src/Infinispan.HotRod/SWIG/ConfigurationBuilder.cs @@ -28,5 +28,6 @@ internal interface ConfigurationBuilder ConfigurationBuilder ValueSizeEstimate(int valueSizeEstimate); ConfigurationBuilder MaxRetries(int maxRetries); ConfigurationBuilder BalancingStrategyProducer(Infinispan.HotRod.Config.FailOverRequestBalancingStrategyProducerDelegate bsp); + ConfigurationBuilder SetTransactional(bool t); } } diff --git a/src/Infinispan.HotRod/SWIG/RemoteCacheManager.cs b/src/Infinispan.HotRod/SWIG/RemoteCacheManager.cs index 8e46721b..d7176298 100644 --- a/src/Infinispan.HotRod/SWIG/RemoteCacheManager.cs +++ b/src/Infinispan.HotRod/SWIG/RemoteCacheManager.cs @@ -16,5 +16,6 @@ internal interface RemoteCacheManager RemoteCounterManager GetCounterManager(); Infinispan.HotRod.SWIGGen.RemoteCacheManagerAdmin administration(); System.Collections.Generic.ISet GetCacheNames(); + TransactionManager GetTransactionManager(); } } diff --git a/src/Infinispan.HotRod/SWIG/TransactionManager.cs b/src/Infinispan.HotRod/SWIG/TransactionManager.cs new file mode 100644 index 00000000..c1e535a3 --- /dev/null +++ b/src/Infinispan.HotRod/SWIG/TransactionManager.cs @@ -0,0 +1,23 @@ +using System; + +namespace Infinispan.HotRod.SWIG +{ + /// + /// This class contains method to start commit and rollback a transaction + /// + public interface TransactionManager + { + /// + /// Begin a transaction + /// + void Begin(); + /// + /// Commit a transaction + /// + void Commit(); + /// + /// Rollback a transaction + /// + void Rollback(); + } +} diff --git a/swig/hotrod_arch.i b/swig/hotrod_arch.i index f807ea99..ede832f5 100644 --- a/swig/hotrod_arch.i +++ b/swig/hotrod_arch.i @@ -74,6 +74,10 @@ return this; } + public Infinispan.HotRod.SWIG.ConfigurationBuilder SetTransactional(bool t) { + return setTransactional(t); + } + %} %typemap(csinterfaces_derived) infinispan::hotrod::ServerConfigurationBuilder "IDisposable, Infinispan.HotRod.SWIG.ServerConfigurationBuilder" @@ -351,12 +355,26 @@ public System.Collections.Generic.Dictionary "IDisposable, Infinispan.HotRod.SWIG.RemoteByteArrayCache" %typemap(csinterfaces) infinispan::hotrod::RemoteCacheManager "IDisposable, Infinispan.HotRod.SWIG.RemoteCacheManager" +%typemap(csinterfaces) infinispan::hotrod::TransactionManager "IDisposable, Infinispan.HotRod.SWIG.TransactionManager" %typemap(csinterfaces) infinispan::hotrod::RemoteCounterManager "IDisposable, Infinispan.HotRod.RemoteCounterManager" %typemap(csinterfaces) infinispan::hotrod::Counter "IDisposable, Infinispan.HotRod.Counter" %typemap(csinterfaces_derived) infinispan::hotrod::StrongCounter "IDisposable, Infinispan.HotRod.StrongCounter" %typemap(csinterfaces_derived) infinispan::hotrod::WeakCounter "IDisposable, Infinispan.HotRod.WeakCounter" %typemap(csinterfaces) infinispan::hotrod::CounterConfiguration "IDisposable, Infinispan.HotRod.ICounterConfiguration" +%typemap(cscode) infinispan::hotrod::TransactionManager %{ + public void Begin() { + begin(); + } + + public void Commit() { + commit(); + } + + public void Rollback() { + rollback(); + } +%} %typemap(cscode) infinispan::hotrod::RemoteCacheManager %{ public void Start() { start(); @@ -409,6 +427,11 @@ public System.Collections.Generic.Dictionary #include #include +#include +#include #include #include #include @@ -69,6 +73,7 @@ namespace org { namespace infinispan { namespace query { namespace remote { name %typemap(csclassmodifiers) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "internal class" %typemap(csclassmodifiers) enum SWIGTYPE "internal enum" + /* Force a common interface between the 32 and 64 bit wrapper code. */ %include "hotrod_arch.i" @@ -179,6 +184,11 @@ static int getpath(void *context, const char ** path) { %ignore infinispan::hotrod::event::ClientCacheEntryCustomEvent; %ignore infinispan::hotrod::event::DotNetClientListener::getFailoverFunction; %ignore getBalancingStrategy; +%ignore infinispan::hotrod::TransactionContext; +%ignore infinispan::hotrod::SynchronizationAdapter; +%ignore infinispan::hotrod::XID; +%ignore infinispan::hotrod::TransactionTable; + %include "infinispan/hotrod/ClientEvent.h" %include "infinispan/hotrod/ClientListener.h" @@ -202,6 +212,8 @@ static int getpath(void *context, const char ** path) { %include "infinispan/hotrod/RemoteCacheBase.h" %include "infinispan/hotrod/RemoteCache.h" +%include "infinispan/hotrod/TransactionManager.h" +%include "infinispan/hotrod/Transactions.h" %include "infinispan/hotrod/RemoteCacheManager.h" %include "infinispan/hotrod/CounterConfiguration.h" %include "infinispan/hotrod/CounterEvent.h" diff --git a/test/Infinispan.HotRod.Tests/RemoteEventTest.cs b/test/Infinispan.HotRod.Tests/RemoteEventTest.cs index e3e0e0b9..a533d18e 100644 --- a/test/Infinispan.HotRod.Tests/RemoteEventTest.cs +++ b/test/Infinispan.HotRod.Tests/RemoteEventTest.cs @@ -139,6 +139,7 @@ public void ConditionalEventsTest() } [Test] + [Ignore("ISPN-9409")] public void CustomEventsTest() { LoggingEventListener listener = new LoggingEventListener(); @@ -169,6 +170,7 @@ public void CustomEventsTest() } [Test] + [Ignore("ISPN-9409")] public void FilterEventsTest() { LoggingEventListener listener = new LoggingEventListener(); diff --git a/test/Infinispan.HotRod.Tests/TransactionTest.cs b/test/Infinispan.HotRod.Tests/TransactionTest.cs new file mode 100644 index 00000000..e5d87964 --- /dev/null +++ b/test/Infinispan.HotRod.Tests/TransactionTest.cs @@ -0,0 +1,355 @@ +using Infinispan.HotRod.Config; +using Infinispan.HotRod.Exceptions; +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using Infinispan.HotRod.Tests.Util; + + +namespace Infinispan.HotRod.Tests.StandaloneXml +{ + [TestFixture] + [Category("standalone_xml")] + [Category("DefaultTestSuite")] + public class TransactionTest + { + RemoteCacheManager remoteManager; + RemoteCacheManager nonTxRemoteManager; + + IMarshaller marshaller; + IMarshaller nonTxMarshaller; + + private void InitializeRemoteCacheManager(bool started) + { + ConfigurationBuilder conf = new ConfigurationBuilder(); + conf.AddServer().Host("127.0.0.1").Port(11222); + conf.ConnectionTimeout(90000).SocketTimeout(6000).Transactional(true); + conf.ProtocolVersion("2.7"); + marshaller = new JBasicMarshaller(); + conf.Marshaller(marshaller); + remoteManager = new RemoteCacheManager(conf.Build(), started); + } + + private void InitializeNonTxRemoteCacheManager(bool started) + { + ConfigurationBuilder conf = new ConfigurationBuilder(); + conf.AddServer().Host("127.0.0.1").Port(11222); + conf.ConnectionTimeout(90000).SocketTimeout(6000); + conf.ProtocolVersion("2.7"); + nonTxMarshaller = new JBasicMarshaller(); + conf.Marshaller(marshaller); + nonTxRemoteManager = new RemoteCacheManager(conf.Build(), started); + } + + [Test] + public void ReadCommitted() + { + InitializeRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v1 = "boron"; + string rv1; + + cache.Clear(); + try + { + txManager.Begin(); + cache.Put(k1, v1); + // Check the correct value from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + txManager.Commit(); + } + catch (Exception ex) + { + // try to release the tx resources + txManager.Rollback(); + throw ex; + } + // Check the correct value from remote cache + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + } + + [Test] + public void ReadRollbackOnNotExistent() + { + InitializeRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v1 = "boron"; + string rv1; + + cache.Clear(); + try + { + txManager.Begin(); + cache.Put(k1, v1); + // Check the correct value from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + } + finally { + txManager.Rollback(); + } + // Check the correct value from remote cache + rv1 = cache.Get(k1); + Assert.IsNull(rv1); + } + + // Client must read last value both during the tx (from the context) + // and after the commit (from the cache) + [Test] + public void ChangeExistentAndCommit() + { + InitializeRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v0 = "carbon"; + string v1 = "boron"; + string rv1; + + cache.Clear(); + cache.Put(k1, v0); + try + { + txManager.Begin(); + cache.Put(k1, v1); + // Check the correct value from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + txManager.Commit(); + } + catch (Exception ex) + { + // try to release the tx resources + txManager.Rollback(); + throw ex; + } + // Check the correct value from remote cache + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + } + + // Client must read last value during the tx (from the context) + // and the old value from the cache after the rollback + [Test] + public void ReadRollbackOnExistent() + { + InitializeRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string oldv = "oxygen"; + string v1 = "boron"; + string rv1; + + cache.Clear(); + string oldrv1 = cache.Put(k1, oldv); + Assert.IsNull(oldrv1); + try + { + txManager.Begin(); + oldrv1 = cache.Put(k1, v1); + Assert.AreEqual(oldrv1, oldv); + // Check the correct value from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + } finally { + txManager.Rollback(); + } + // Check the correct value from remote cache + rv1 = cache.Get(k1); + Assert.AreEqual(oldrv1, oldv); + } + + // Client must read last value during the tx (from the context) + [Test] + public void ReadInTransactionContext() + { + InitializeRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v1 = "boron"; + string rv1; + + cache.Clear(); + try + { + txManager.Begin(); + + string oldv1 = cache.Put(k1, v1); + // Check the correct value from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + cache.Remove(k1); + rv1 = cache.Get(k1); + Assert.IsNull(rv1); + } finally { + txManager.Rollback(); + } + } + + // TX Client must read last value during the tx (from the context) + // NONTX client must read old value from the cache + [Test] + public void ReadCommittedAndNonTxRead() + { + InitializeRemoteCacheManager(true); + InitializeNonTxRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + IRemoteCache nonTxCache = nonTxRemoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v1 = "boron"; + string rv1; + string nontxrv1; + + cache.Clear(); + try + { + txManager.Begin(); + + cache.Put(k1, v1); + // Check the correct value from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + nontxrv1 = nonTxCache.Get(k1); + Assert.IsNull(nontxrv1); + txManager.Commit(); + } + catch (Exception ex) + { + // try to release the tx resources + txManager.Rollback(); + throw ex; + } + // Check the correct value from remote cache + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + nontxrv1 = nonTxCache.Get(k1); + Assert.AreEqual(nontxrv1, v1); + } + + // NONTX client must put/get values from the cache + [Test] + public void PutAndReadWithNonTxCache() + { + InitializeRemoteCacheManager(true); + InitializeNonTxRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + IRemoteCache nonTxCache = nonTxRemoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v1 = "boron"; + string rv1; + + cache.Clear(); + try + { + txManager.Begin(); + string oldv1 = nonTxCache.Put(k1, v1); + // Check the correct value from the tx context + rv1 = nonTxCache.Get(k1); + Assert.AreEqual(rv1, v1); + rv1 = cache.Remove(k1); + rv1 = cache.Get(k1); + Assert.IsNull(rv1); + } finally { + txManager.Rollback(); + } + rv1 = nonTxCache.Get(k1); + Assert.AreEqual(rv1, v1); + } + + // NONTX client must put/get values from the cache + [Test] + public void RepeatableGetForTxClient() + { + InitializeRemoteCacheManager(true); + InitializeNonTxRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + IRemoteCache nonTxCache = nonTxRemoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v1 = "boron"; + string v2 = "helium"; + string rv1; + + cache.Clear(); + try + { + txManager.Begin(); + + string oldv1 = nonTxCache.Put(k1, v1); + // Check the correct value from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + // This goes to the server + oldv1 = nonTxCache.Put(k1, v2); + // But this values comes from the tx context + rv1 = cache.Get(k1); + Assert.AreEqual(rv1, v1); + cache.Remove(k1); + rv1 = cache.Get(k1); + Assert.IsNull(rv1); + } finally { + txManager.Rollback(); + } + rv1 = nonTxCache.Get(k1); + Assert.AreEqual(rv1, v2); + } + // NONTX client must put/get values from the cache + [Test] + public void ConflictsAndFail() + { + InitializeRemoteCacheManager(true); + InitializeNonTxRemoteCacheManager(true); + IRemoteCache cache = remoteManager.GetCache("non_xa", true); + IRemoteCache nonTxCache = nonTxRemoteManager.GetCache("non_xa", true); + var txManager = remoteManager.GetTransactionManager(); + + string k1 = "key13"; + string v1 = "boron"; + string k2 = "key14"; + string v2 = "helium"; + string vx = "calcium"; + + cache.Clear(); + try + { + txManager.Begin(); + + string oldv1 = cache.Put(k1, v1); + string oldv2 = cache.Put(k2, v2); + // Check the correct value from the tx context + string rv1 = nonTxCache.Put(k1, vx); + Assert.IsNull(rv1); + Assert.Throws(() => + { + txManager.Commit(); + }); + } + catch (Exception ex) + { + // try to release the tx resources + txManager.Rollback(); + throw ex; + } + Assert.AreEqual(cache.Get(k1), vx); + Assert.IsNull(cache.Get(k2)); + } + } +} diff --git a/test/resources/clustered-sasl-cs.xml b/test/resources/clustered-sasl-cs.xml index 43efa238..5597d17c 100644 --- a/test/resources/clustered-sasl-cs.xml +++ b/test/resources/clustered-sasl-cs.xml @@ -176,7 +176,7 @@ - + diff --git a/test/resources/standalone-hotrod-ssl.xml b/test/resources/standalone-hotrod-ssl.xml index adde4922..872a34e7 100644 --- a/test/resources/standalone-hotrod-ssl.xml +++ b/test/resources/standalone-hotrod-ssl.xml @@ -174,7 +174,7 @@ - + diff --git a/test/resources/standalone.xml b/test/resources/standalone.xml new file mode 100644 index 00000000..c8ebff96 --- /dev/null +++ b/test/resources/standalone.xml @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + h2 + + sa + sa + + + + + org.h2.jdbcx.JdbcDataSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +