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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+