You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/08/31 09:10:26 UTC
[4/9] ignite git commit: IGNITE-5931 .NET: Fix type registration race
condition
IGNITE-5931 .NET: Fix type registration race condition
This closes #2553
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/eae6e3b9
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/eae6e3b9
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/eae6e3b9
Branch: refs/heads/ignite-3478
Commit: eae6e3b9fd43b42fc9d74e61118800dc0f3f6f0c
Parents: d253c02
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Aug 30 18:35:05 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Aug 30 18:35:05 2017 +0300
----------------------------------------------------------------------
.../Binary/BinaryDynamicRegistrationTest.cs | 49 ++++++++++++++++++++
.../Binary/BinarySelfTest.cs | 12 -----
.../Cache/Affinity/AffinityFieldTest.cs | 10 +++-
.../Impl/Binary/Marshaller.cs | 43 ++++++++++-------
4 files changed, 84 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/eae6e3b9/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs
index 4f458f4..01804b7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs
@@ -25,6 +25,8 @@ namespace Apache.Ignite.Core.Tests.Binary
using System.Collections.Generic;
using System.IO;
using System.Linq;
+ using System.Threading;
+ using System.Threading.Tasks;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Cache.Store;
@@ -357,6 +359,53 @@ namespace Apache.Ignite.Core.Tests.Binary
}
/// <summary>
+ /// Tests registration in multiple threads.
+ /// </summary>
+ [Test]
+ public void TestRegistrationMultithreaded([Values(true, false)] bool useTypeName)
+ {
+ const int iterations = 50;
+ const int threads = 4;
+
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ var cache = ignite.CreateCache<int, int>("c").WithKeepBinary<int, IBinaryObject>();
+ var bin = ignite.GetBinary();
+ Func<Type, IBinaryObjectBuilder> getBuilder = x =>
+ useTypeName ? bin.GetBuilder(x.FullName) : bin.GetBuilder(x);
+
+ var types = new[] { typeof(Foo), typeof(Bar), typeof(Bin) };
+
+ foreach (var type in types)
+ {
+ var type0 = type; // Modified closure.
+
+ for (var i = 0; i < iterations; i++)
+ {
+ var countdown = new CountdownEvent(threads);
+
+ Action registerType = () =>
+ {
+ countdown.Signal();
+ Assert.IsTrue(countdown.Wait(5000));
+
+ var binObj = getBuilder(type0).SetIntField("x", 1).Build();
+ cache[1] = binObj;
+
+ Assert.AreEqual(binObj, cache[1]);
+ };
+
+ var tasks = Enumerable.Range(0, threads)
+ .Select(x => Task.Factory.StartNew(registerType))
+ .ToArray();
+
+ Task.WaitAll(tasks);
+ }
+ }
+ }
+ }
+
+ /// <summary>
/// Tests the type registration.
/// </summary>
private static void Test(IIgnite ignite1, IIgnite ignite2)
http://git-wip-us.apache.org/repos/asf/ignite/blob/eae6e3b9/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
index e24dca0..4237eda 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
@@ -1534,18 +1534,6 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(nDateArr, obj2.NDateArr);
}
- [Test]
- public void TestBinaryConfigurationValidation()
- {
- var cfg = new BinaryConfiguration(typeof (PropertyType))
- {
- Types = new[] {typeof(PropertyType).AssemblyQualifiedName}
- };
-
- // ReSharper disable once ObjectCreationAsStatement
- Assert.Throws<BinaryObjectException>(() => new Marshaller(cfg));
- }
-
/// <summary>
/// Tests the compact footer setting.
/// </summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/eae6e3b9/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFieldTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFieldTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFieldTest.cs
index 31326b7..c3482bb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFieldTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFieldTest.cs
@@ -76,7 +76,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
_cache1.Put(new CacheKeyAttrOverride(), string.Empty);
// Verify
- foreach (var type in new[] { typeof(CacheKey) , typeof(CacheKeyAttr), typeof(CacheKeyAttrOverride)})
+ foreach (var type in new[] { typeof(CacheKey), typeof(CacheKeyAttr),
+ typeof(CacheKeyAttrDynamicRegistration), typeof(CacheKeyAttrOverride)})
{
Assert.AreEqual("AffinityKey", _cache1.Ignite.GetBinary().GetBinaryType(type).AffinityKeyFieldName);
Assert.AreEqual("AffinityKey", _cache2.Ignite.GetBinary().GetBinaryType(type).AffinityKeyFieldName);
@@ -91,6 +92,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
{
TestKeyLocation0((key, affKey) => new CacheKey {Key = key, AffinityKey = affKey});
TestKeyLocation0((key, affKey) => new CacheKeyAttr {Key = key, AffinityKey = affKey});
+ TestKeyLocation0((key, affKey) => new CacheKeyAttrDynamicRegistration {Key = key, AffinityKey = affKey});
TestKeyLocation0((key, affKey) => new CacheKeyAttrOverride {Key = key, AffinityKey = affKey});
}
@@ -190,6 +192,12 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
[AffinityKeyMapped] public int AffinityKey { get; set; }
}
+ private class CacheKeyAttrDynamicRegistration
+ {
+ public int Key { get; set; }
+ [AffinityKeyMapped] public int AffinityKey { get; set; }
+ }
+
private class CacheKeyAttrOverride
{
[AffinityKeyMapped] public int Key { get; set; }
http://git-wip-us.apache.org/repos/asf/ignite/blob/eae6e3b9/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
index 5ede542..a6d5517 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -503,21 +503,28 @@ namespace Apache.Ignite.Core.Impl.Binary
desc = desc == null
? new BinaryFullTypeDescriptor(type, typeId, typeName, true, _cfg.NameMapper,
- _cfg.IdMapper, ser, false, null, BinaryUtils.IsIgniteEnum(type), registered)
+ _cfg.IdMapper, ser, false, GetAffinityKeyFieldNameFromAttribute(type),
+ BinaryUtils.IsIgniteEnum(type), registered)
: new BinaryFullTypeDescriptor(desc, type, ser, registered);
if (RegistrationDisabled)
+ {
return desc;
+ }
var typeKey = BinaryUtils.TypeKey(true, typeId);
var desc0 = _idToDesc.GetOrAdd(typeKey, x => desc);
- if (desc0.Type != null && desc0.Type.FullName != type.FullName)
+ if (desc0.Type != null && desc0.TypeName != typeName)
+ {
ThrowConflictingTypeError(type, desc0.Type, typeId);
+ }
desc0 = _typeNameToDesc.GetOrAdd(typeName, x => desc);
- if (desc0.Type != null && desc0.Type.FullName != type.FullName)
+ if (desc0.Type != null && desc0.TypeName != typeName)
+ {
ThrowConflictingTypeError(type, desc0.Type, typeId);
+ }
_typeToDesc.Set(type, desc);
@@ -652,34 +659,36 @@ namespace Apache.Ignite.Core.Impl.Binary
bool keepDeserialized, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper,
IBinarySerializerInternal serializer, string affKeyFieldName, bool isEnum)
{
+ Debug.Assert(!string.IsNullOrEmpty(typeName));
+
long typeKey = BinaryUtils.TypeKey(userType, typeId);
BinaryFullTypeDescriptor conflictingType;
- if (_idToDesc.TryGetValue(typeKey, out conflictingType))
+ if (_idToDesc.TryGetValue(typeKey, out conflictingType) && conflictingType.TypeName != typeName)
{
- var type1 = conflictingType.Type != null
- ? conflictingType.Type.AssemblyQualifiedName
- : conflictingType.TypeName;
-
- var type2 = type != null ? type.AssemblyQualifiedName : typeName;
-
- ThrowConflictingTypeError(type1, type2, typeId);
+ ThrowConflictingTypeError(typeName, conflictingType.TypeName, typeId);
}
- if (userType && _typeNameToDesc.ContainsKey(typeName))
- throw new BinaryObjectException("Conflicting type name: " + typeName);
-
var descriptor = new BinaryFullTypeDescriptor(type, typeId, typeName, userType, nameMapper, idMapper,
serializer, keepDeserialized, affKeyFieldName, isEnum);
+ if (RegistrationDisabled)
+ {
+ return descriptor;
+ }
+
if (type != null)
- _typeToDesc.GetOrAdd(type, x => descriptor);
+ {
+ _typeToDesc.Set(type, descriptor);
+ }
if (userType)
- _typeNameToDesc.GetOrAdd(typeName, x => descriptor);
+ {
+ _typeNameToDesc.Set(typeName, descriptor);
+ }
- _idToDesc.GetOrAdd(typeKey, _ => descriptor);
+ _idToDesc.Set(typeKey, descriptor);
return descriptor;
}