IGNITE-5786 .NET: Fix cache store session handling for cross-cache transactions
This closes #2331 Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c1a3b374 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c1a3b374 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c1a3b374 Branch: refs/heads/ignite-5757 Commit: c1a3b3744f89e27906621e62e9d73281791fcf30 Parents: 6de0571 Author: Pavel Tupitsyn <ptupit...@apache.org> Authored: Fri Jul 21 17:04:39 2017 +0300 Committer: Pavel Tupitsyn <ptupit...@apache.org> Committed: Fri Jul 21 17:04:39 2017 +0300 ---------------------------------------------------------------------- .../dotnet/PlatformDotNetCacheStore.java | 31 +++++++ .../Apache.Ignite.Core.Tests.csproj | 5 ++ .../Cache/Store/CacheStoreSessionTest.cs | 90 +++++++++++++------- .../Store/CacheStoreSessionTestCodeConfig.cs | 68 +++++++++++++++ .../Store/CacheStoreSessionTestSharedFactory.cs | 48 +++++++++++ .../Cache/Store/CacheStoreTest.cs | 10 ++- .../cache-store-session-shared-factory.xml | 76 +++++++++++++++++ .../Config/Cache/Store/cache-store-session.xml | 20 ++--- .../Impl/Cache/Store/CacheStoreInternal.cs | 14 ++- 9 files changed, 320 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetCacheStore.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetCacheStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetCacheStore.java index dd61a54..471eb01 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetCacheStore.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetCacheStore.java @@ -47,6 +47,7 @@ import javax.cache.integration.CacheLoaderException; import javax.cache.integration.CacheWriterException; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; /** @@ -90,6 +91,9 @@ public class PlatformDotNetCacheStore<K, V> implements CacheStore<K, V>, Platfor /** Key used to distinguish session deployment. */ private static final Object KEY_SES = new Object(); + /** Key to designate a set of stores that share current session. */ + private static final Object KEY_SES_STORES = new Object(); + /** */ @CacheStoreSessionResource private CacheStoreSession ses; @@ -337,6 +341,23 @@ public class PlatformDotNetCacheStore<K, V> implements CacheStore<K, V>, Platfor writer.writeLong(session()); writer.writeString(ses.cacheName()); writer.writeBoolean(commit); + + // When multiple stores (caches) participate in a single transaction, + // they share a single session, but sessionEnd is called on each store. + // Same thing happens on platform side: session is shared; each store must be notified, + // then session should be closed. + Collection<Long> stores = (Collection<Long>) ses.properties().get(KEY_SES_STORES); + assert stores != null; + + stores.remove(ptr); + boolean last = stores.isEmpty(); + + writer.writeBoolean(last); + + if (last) { + // Session object has been released on platform side, remove marker. + ses.properties().remove(KEY_SES); + } } }, null); } @@ -415,6 +436,16 @@ public class PlatformDotNetCacheStore<K, V> implements CacheStore<K, V>, Platfor ses.properties().put(KEY_SES, sesPtr); } + // Keep track of all stores that use current session (cross-cache tx uses single session for all caches). + Collection<Long> stores = (Collection<Long>) ses.properties().get(KEY_SES_STORES); + + if (stores == null) { + stores = new HashSet<>(); + ses.properties().put(KEY_SES_STORES, stores); + } + + stores.add(ptr); + return sesPtr; } http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index 90b7970..e4f65bc 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -89,6 +89,8 @@ <Compile Include="Cache\Query\Linq\CacheLinqTest.Misc.cs" /> <Compile Include="Cache\Query\Linq\CacheLinqTest.Custom.cs" /> <Compile Include="Cache\Query\Linq\CacheLinqTest.Contains.cs" /> + <Compile Include="Cache\Store\CacheStoreSessionTestCodeConfig.cs" /> + <Compile Include="Cache\Store\CacheStoreSessionTestSharedFactory.cs" /> <Compile Include="Deployment\CacheGetFunc.cs" /> <Compile Include="Deployment\GetAddressFunc.cs" /> <Compile Include="Deployment\PeerAssemblyLoadingAllApisTest.cs" /> @@ -314,6 +316,9 @@ <Content Include="Config\Cache\Affinity\affinity-function.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> + <Content Include="Config\Cache\Store\cache-store-session-shared-factory.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> <Content Include="Config\Cache\Store\cache-store-session.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTest.cs index 315e285..818948c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTest.cs @@ -28,16 +28,13 @@ namespace Apache.Ignite.Core.Tests.Cache.Store /// <summary> /// Tests for store session. /// </summary> - public sealed class CacheStoreSessionTest + public class CacheStoreSessionTest { - /** Grid name. */ - private const string IgniteName = "grid"; - /** Cache 1 name. */ - private const string Cache1 = "cache1"; + protected const string Cache1 = "cache1"; /** Cache 2 name. */ - private const string Cache2 = "cache2"; + protected const string Cache2 = "cache2"; /** Operations. */ private static ConcurrentBag<ICollection<Operation>> _dumps; @@ -48,11 +45,26 @@ namespace Apache.Ignite.Core.Tests.Cache.Store [TestFixtureSetUp] public void BeforeTests() { - Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration()) + Ignition.Start(GetIgniteConfiguration()); + } + + /// <summary> + /// Gets the ignite configuration. + /// </summary> + protected virtual IgniteConfiguration GetIgniteConfiguration() + { + return new IgniteConfiguration(TestUtils.GetTestConfiguration()) { - IgniteInstanceName = IgniteName, SpringConfigUrl = @"config\cache\store\cache-store-session.xml" - }); + }; + } + + /// <summary> + /// Gets the store count. + /// </summary> + protected virtual int StoreCount + { + get { return 2; } } /// <summary> @@ -61,21 +73,29 @@ namespace Apache.Ignite.Core.Tests.Cache.Store [TestFixtureTearDown] public void AfterTests() { - Ignition.StopAll(true); + try + { + TestUtils.AssertHandleRegistryHasItems(Ignition.GetIgnite(), 2, 1000); + } + finally + { + Ignition.StopAll(true); + } } /// <summary> /// Test basic session API. /// </summary> [Test] + [Timeout(30000)] public void TestSession() { _dumps = new ConcurrentBag<ICollection<Operation>>(); - var ignite = Ignition.GetIgnite(IgniteName); + var ignite = Ignition.GetIgnite(); - var cache1 = Ignition.GetIgnite(IgniteName).GetCache<int, int>(Cache1); - var cache2 = Ignition.GetIgnite(IgniteName).GetCache<int, int>(Cache2); + var cache1 = ignite.GetCache<int, int>(Cache1); + var cache2 = ignite.GetCache<int, int>(Cache2); // 1. Test rollback. using (var tx = ignite.GetTransactions().TxStart()) @@ -86,11 +106,15 @@ namespace Apache.Ignite.Core.Tests.Cache.Store tx.Rollback(); } - Assert.AreEqual(1, _dumps.Count); - var ops = _dumps.First(); - Assert.AreEqual(1, ops.Count); + // SessionEnd is called once per store instance. + Assert.AreEqual(StoreCount, _dumps.Count); - Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.SesEnd && !op.Commit)); + foreach (var ops in _dumps) + { + var op = ops.Single(); + Assert.AreEqual(OperationType.SesEnd, op.Type); + Assert.IsFalse(op.Commit); + } _dumps = new ConcurrentBag<ICollection<Operation>>(); @@ -103,13 +127,17 @@ namespace Apache.Ignite.Core.Tests.Cache.Store tx.Commit(); } - Assert.AreEqual(1, _dumps.Count); - ops = _dumps.First(); - Assert.AreEqual(3, ops.Count); + Assert.AreEqual(StoreCount, _dumps.Count); - Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write && Cache1.Equals(op.CacheName) && 1.Equals(op.Key) && 1.Equals(op.Value))); - Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write && Cache2.Equals(op.CacheName) && 2.Equals(op.Key) && 2.Equals(op.Value))); - Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit)); + foreach (var ops in _dumps) + { + Assert.AreEqual(2 + StoreCount, ops.Count); + Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write + && Cache1 == op.CacheName && 1 == op.Key && 1 == op.Value)); + Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write + && Cache2 == op.CacheName && 2 == op.Key && 2 == op.Value)); + Assert.AreEqual(StoreCount, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit)); + } _dumps = new ConcurrentBag<ICollection<Operation>>(); @@ -122,13 +150,17 @@ namespace Apache.Ignite.Core.Tests.Cache.Store tx.Commit(); } - Assert.AreEqual(1, _dumps.Count); - ops = _dumps.First(); - Assert.AreEqual(3, ops.Count); + Assert.AreEqual(StoreCount, _dumps.Count); + foreach (var ops in _dumps) + { + Assert.AreEqual(2 + StoreCount, ops.Count); - Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete && Cache1.Equals(op.CacheName) && 1.Equals(op.Key))); - Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete && Cache2.Equals(op.CacheName) && 2.Equals(op.Key))); - Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit)); + Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete + && Cache1 == op.CacheName && 1 == op.Key)); + Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete + && Cache2 == op.CacheName && 2 == op.Key)); + Assert.AreEqual(StoreCount, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit)); + } } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestCodeConfig.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestCodeConfig.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestCodeConfig.cs new file mode 100644 index 0000000..0b5f474 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestCodeConfig.cs @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +namespace Apache.Ignite.Core.Tests.Cache.Store +{ + using Apache.Ignite.Core.Cache.Configuration; + using Apache.Ignite.Core.Cache.Store; + using Apache.Ignite.Core.Common; + using NUnit.Framework; + + /// <summary> + /// Tests store session with programmatic configuration (uses different store factory on Java side). + /// </summary> + [TestFixture] + public class CacheStoreSessionTestCodeConfig : CacheStoreSessionTest + { + /** <inheritdoc /> */ + protected override IgniteConfiguration GetIgniteConfiguration() + { + return new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + CacheConfiguration = new[] + { + new CacheConfiguration(Cache1) + { + AtomicityMode = CacheAtomicityMode.Transactional, + ReadThrough = true, + WriteThrough = true, + CacheStoreFactory = new StoreFactory() + }, + new CacheConfiguration(Cache2) + { + AtomicityMode = CacheAtomicityMode.Transactional, + ReadThrough = true, + WriteThrough = true, + CacheStoreFactory = new StoreFactory() + } + } + }; + } + + /// <summary> + /// Store factory. + /// </summary> + private class StoreFactory : IFactory<ICacheStore> + { + /** <inheritdoc /> */ + public ICacheStore CreateInstance() + { + return new Store(); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestSharedFactory.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestSharedFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestSharedFactory.cs new file mode 100644 index 0000000..2af5915 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreSessionTestSharedFactory.cs @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +namespace Apache.Ignite.Core.Tests.Cache.Store +{ + using NUnit.Framework; + + /// <summary> + /// Session test with shared PlatformDotNetCacheStoreFactory, + /// which causes the same store insance to be used for both caches. + /// </summary> + [TestFixture] + public class CacheStoreSessionTestSharedFactory : CacheStoreSessionTest + { + /** <inheritdoc /> */ + protected override IgniteConfiguration GetIgniteConfiguration() + { + return new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + SpringConfigUrl = @"config\cache\store\cache-store-session-shared-factory.xml" + }; + } + + /** <inheritdoc /> */ + protected override int StoreCount + { + get + { + // Shared PlatformDotNetCacheStoreFactory results in a single store instance. + return 1; + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs index e05f4bd..d3e4ab6 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs @@ -64,7 +64,15 @@ namespace Apache.Ignite.Core.Tests.Cache.Store [TestFixtureTearDown] public void AfterTests() { - Ignition.StopAll(true); + try + { + // 3 stores are expected in HandleRegistry. + TestUtils.AssertHandleRegistryHasItems(Ignition.GetIgnite(), 3, 1000); + } + finally + { + Ignition.StopAll(true); + } } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session-shared-factory.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session-shared-factory.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session-shared-factory.xml new file mode 100644 index 0000000..05515c4 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session-shared-factory.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:util="http://www.springframework.org/schema/util" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util + http://www.springframework.org/schema/util/spring-util.xsd"> + <bean id="storeFactory" class="org.apache.ignite.platform.dotnet.PlatformDotNetCacheStoreFactory"> + <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Store.CacheStoreSessionTest+Store, Apache.Ignite.Core.Tests"/> + </bean> + + <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> + <property name="localHost" value="127.0.0.1"/> + <property name="connectorConfiguration"><null/></property> + + <property name="cacheConfiguration"> + <list> + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache1"/> + <property name="cacheMode" value="LOCAL"/> + <property name="atomicityMode" value="TRANSACTIONAL"/> + <property name="writeThrough" value="true"/> + <property name="readThrough" value="true"/> + + <property name="cacheStoreFactory" ref="storeFactory" /> + </bean> + + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache2"/> + <property name="cacheMode" value="LOCAL"/> + <property name="atomicityMode" value="TRANSACTIONAL"/> + <property name="writeThrough" value="true"/> + <property name="readThrough" value="true"/> + + <property name="cacheStoreFactory" ref="storeFactory" /> + </bean> + </list> + </property> + + <property name="discoverySpi"> + <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi"> + <property name="ipFinder"> + <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"> + <property name="addresses"> + <list> + <!-- In distributed environment, replace with actual host IP address. --> + <value>127.0.0.1:47500</value> + </list> + </property> + </bean> + </property> + <property name="socketTimeout" value="300" /> + </bean> + </property> + </bean> +</beans> http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session.xml index 3cc9efa..14dc78e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session.xml +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Store/cache-store-session.xml @@ -25,18 +25,10 @@ http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> - <bean id="storeFactory" class="org.apache.ignite.platform.dotnet.PlatformDotNetCacheStoreFactory"> - <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Store.CacheStoreSessionTest+Store, Apache.Ignite.Core.Tests"/> - </bean> - <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> <property name="localHost" value="127.0.0.1"/> <property name="connectorConfiguration"><null/></property> - <property name="includeEventTypes"> - <util:constant static-field="org.apache.ignite.events.EventType.EVTS_CACHE"/> - </property> - <property name="cacheConfiguration"> <list> <bean class="org.apache.ignite.configuration.CacheConfiguration"> @@ -46,7 +38,11 @@ <property name="writeThrough" value="true"/> <property name="readThrough" value="true"/> - <property name="cacheStoreFactory" ref="storeFactory" /> + <property name="cacheStoreFactory"> + <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetCacheStoreFactory"> + <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Store.CacheStoreSessionTest+Store, Apache.Ignite.Core.Tests"/> + </bean> + </property> </bean> <bean class="org.apache.ignite.configuration.CacheConfiguration"> @@ -56,7 +52,11 @@ <property name="writeThrough" value="true"/> <property name="readThrough" value="true"/> - <property name="cacheStoreFactory" ref="storeFactory" /> + <property name="cacheStoreFactory"> + <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetCacheStoreFactory"> + <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Store.CacheStoreSessionTest+Store, Apache.Ignite.Core.Tests"/> + </bean> + </property> </bean> </list> </property> http://git-wip-us.apache.org/repos/asf/ignite/blob/c1a3b374/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStoreInternal.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStoreInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStoreInternal.cs index f147579..df4c1ae 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStoreInternal.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStoreInternal.cs @@ -111,6 +111,8 @@ namespace Apache.Ignite.Core.Impl.Cache.Store CacheStoreSession ses = grid.HandleRegistry.Get<CacheStoreSession>(sesId, true); + // Session cache name may change in cross-cache transaction. + // Single session is used for all stores in cross-cache transactions. ses.CacheName = rawReader.ReadString(); _sesProxy.SetSession(ses); @@ -223,11 +225,19 @@ namespace Apache.Ignite.Core.Impl.Cache.Store break; case OpSesEnd: - grid.HandleRegistry.Release(sesId); + { + var commit = rawReader.ReadBoolean(); + var last = rawReader.ReadBoolean(); - _store.SessionEnd(rawReader.ReadBoolean()); + if (last) + { + grid.HandleRegistry.Release(sesId); + } + + _store.SessionEnd(commit); break; + } default: throw new IgniteException("Invalid operation type: " + opType);