You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/03/09 15:17:47 UTC
[3/6] ignite git commit: IGNITE-2739 .NET: AffinityKey support. This
closes #533.
IGNITE-2739 .NET: AffinityKey support. This closes #533.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1f328e45
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1f328e45
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1f328e45
Branch: refs/heads/ignite-1786
Commit: 1f328e45acc4fdf490425bef0bd9af37cf45a720
Parents: e92aba4
Author: Pavel Tupitsyn <pt...@gridgain.com>
Authored: Wed Mar 9 13:20:20 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Mar 9 13:20:20 2016 +0300
----------------------------------------------------------------------
.../platform/PlatformComputeEchoTask.java | 11 +-
.../Apache.Ignite.Core.Tests.csproj | 1 +
.../Cache/CacheAffinityFieldTest.cs | 199 +++++++++++++++++++
.../Cache/CacheConfigurationTest.cs | 13 +-
.../Compute/ComputeApiTest.cs | 5 +-
.../Apache.Ignite.Core.csproj | 2 +
.../Cache/Affinity/AffinityKey.cs | 162 +++++++++++++++
.../Affinity/AffinityKeyMappedAttribute.cs | 46 +++++
.../Impl/Binary/Marshaller.cs | 33 ++-
.../Binary/EmployeeKey.cs | 2 +
10 files changed, 457 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
index e945ada..c01c6f4 100644
--- a/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
+++ b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
@@ -23,6 +23,7 @@ import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.cache.affinity.AffinityKey;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.ComputeJobAdapter;
@@ -97,6 +98,9 @@ public class PlatformComputeEchoTask extends ComputeTaskAdapter<Integer, Object>
/** Type: enum array. */
private static final int TYPE_ENUM_FIELD = 18;
+ /** Type: enum array. */
+ private static final int TYPE_AFFINITY_KEY = 19;
+
/** {@inheritDoc} */
@Nullable @Override public Map<? extends ComputeJob, ClusterNode> map(List<ClusterNode> subgrid,
@Nullable Integer arg) {
@@ -124,7 +128,7 @@ public class PlatformComputeEchoTask extends ComputeTaskAdapter<Integer, Object>
*
* @param type Result type.
*/
- public EchoJob(Integer type) {
+ private EchoJob(Integer type) {
this.type = type;
}
@@ -150,7 +154,7 @@ public class PlatformComputeEchoTask extends ComputeTaskAdapter<Integer, Object>
return 1;
case TYPE_LONG:
- return (long)1;
+ return 1L;
case TYPE_FLOAT:
return (float)1;
@@ -200,6 +204,9 @@ public class PlatformComputeEchoTask extends ComputeTaskAdapter<Integer, Object>
return val.deserialize();
+ case TYPE_AFFINITY_KEY:
+ return new AffinityKey<>("interopAffinityKey");
+
default:
throw new IgniteException("Unknown type: " + type);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/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 bb25536..bb56a3d 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
@@ -61,6 +61,7 @@
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Cache\CacheAffinityFieldTest.cs" />
<Compile Include="Cache\CacheConfigurationTest.cs" />
<Compile Include="Cache\CacheDynamicStartTest.cs" />
<Compile Include="Cache\CacheTestAsyncWrapper.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityFieldTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityFieldTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityFieldTest.cs
new file mode 100644
index 0000000..4fb7738
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityFieldTest.cs
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+// ReSharper disable UnusedAutoPropertyAccessor.Local
+namespace Apache.Ignite.Core.Tests.Cache
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Affinity;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Tests.Compute;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests custom affinity mapping.
+ /// </summary>
+ public class CacheAffinityFieldTest
+ {
+ /** */
+ private ICache<object, string> _cache1;
+
+ /** */
+ private ICache<object, string> _cache2;
+
+ /// <summary>
+ /// Fixture set up.
+ /// </summary>
+ [TestFixtureSetUp]
+ public void FixtureSetUp()
+ {
+ var grid1 = Ignition.Start(GetConfig());
+ var grid2 = Ignition.Start(GetConfig("grid2"));
+
+ _cache1 = grid1.CreateCache<object, string>(new CacheConfiguration
+ {
+ CacheMode = CacheMode.Partitioned
+ });
+ _cache2 = grid2.GetCache<object, string>(null);
+ }
+
+ /// <summary>
+ /// Fixture tear down.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void FixtureTearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Tests the metadata.
+ /// </summary>
+ [Test]
+ public void TestMetadata()
+ {
+ // Put keys to update meta
+ _cache1.Put(new CacheKey(), string.Empty);
+ _cache1.Put(new CacheKeyAttr(), string.Empty);
+ _cache1.Put(new CacheKeyAttrOverride(), string.Empty);
+
+ // Verify
+ foreach (var type in new[] { typeof(CacheKey) , typeof(CacheKeyAttr), typeof(CacheKeyAttrOverride)})
+ {
+ Assert.AreEqual("AffinityKey", _cache1.Ignite.GetBinary().GetBinaryType(type).AffinityKeyFieldName);
+ Assert.AreEqual("AffinityKey", _cache2.Ignite.GetBinary().GetBinaryType(type).AffinityKeyFieldName);
+ }
+ }
+
+ /// <summary>
+ /// Tests that keys are located properly in cache partitions.
+ /// </summary>
+ [Test]
+ public void TestKeyLocation()
+ {
+ TestKeyLocation0((key, affKey) => new CacheKey {Key = key, AffinityKey = affKey});
+ TestKeyLocation0((key, affKey) => new CacheKeyAttr {Key = key, AffinityKey = affKey});
+ TestKeyLocation0((key, affKey) => new CacheKeyAttrOverride {Key = key, AffinityKey = affKey});
+ }
+
+ /// <summary>
+ /// Tests the <see cref="AffinityKey"/> class.
+ /// </summary>
+ [Test]
+ public void TestAffinityKeyClass()
+ {
+ // Check location
+ TestKeyLocation0((key, affKey) => new AffinityKey(key, affKey));
+
+ // Check meta
+ Assert.AreEqual("affKey",
+ _cache1.Ignite.GetBinary().GetBinaryType(typeof (AffinityKey)).AffinityKeyFieldName);
+ }
+
+ /// <summary>
+ /// Tests <see cref="AffinityKey"/> class interoperability.
+ /// </summary>
+ [Test]
+ public void TestInterop()
+ {
+ var affKey = _cache1.Ignite.GetCompute()
+ .ExecuteJavaTask<AffinityKey>(ComputeApiTest.EchoTask, ComputeApiTest.EchoTypeAffinityKey);
+
+ Assert.AreEqual("interopAffinityKey", affKey.Key);
+ }
+
+ /// <summary>
+ /// Tests the key location.
+ /// </summary>
+ private void TestKeyLocation0<T>(Func<int, int, T> ctor)
+ {
+ var aff = _cache1.Ignite.GetAffinity(_cache1.Name);
+
+ foreach (var cache in new[] { _cache1, _cache2 })
+ {
+ cache.RemoveAll();
+
+ var localNode = cache.Ignite.GetCluster().GetLocalNode();
+
+ var localKeys = Enumerable.Range(1, int.MaxValue)
+ .Where(x => aff.MapKeyToNode(x).Id == localNode.Id).Take(100).ToArray();
+
+ for (int index = 0; index < localKeys.Length; index++)
+ {
+ var cacheKey = ctor(index, localKeys[index]);
+
+ cache.Put(cacheKey, index.ToString());
+
+ // Verify that key is stored locally accroding to AffinityKeyFieldName
+ Assert.AreEqual(index.ToString(), cache.LocalPeek(cacheKey, CachePeekMode.Primary));
+
+ // Other cache does not have this key locally
+ var otherCache = cache == _cache1 ? _cache2 : _cache1;
+ Assert.Throws<KeyNotFoundException>(() => otherCache.LocalPeek(cacheKey, CachePeekMode.All));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the configuration.
+ /// </summary>
+ private static IgniteConfiguration GetConfig(string gridName = null)
+ {
+ return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ GridName = gridName,
+ BinaryConfiguration = new BinaryConfiguration
+ {
+ TypeConfigurations = new[]
+ {
+ new BinaryTypeConfiguration(typeof (CacheKey))
+ {
+ AffinityKeyFieldName = "AffinityKey"
+ },
+ new BinaryTypeConfiguration(typeof(CacheKeyAttr)),
+ new BinaryTypeConfiguration(typeof (CacheKeyAttrOverride))
+ {
+ AffinityKeyFieldName = "AffinityKey"
+ }
+ }
+ },
+ };
+ }
+
+ private class CacheKey
+ {
+ public int Key { get; set; }
+ public int AffinityKey { get; set; }
+ }
+
+ private class CacheKeyAttr
+ {
+ public int Key { get; set; }
+ [AffinityKeyMapped] public int AffinityKey { get; set; }
+ }
+
+ private class CacheKeyAttrOverride
+ {
+ [AffinityKeyMapped] public int Key { get; set; }
+ public int AffinityKey { get; set; }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
index 2e6a8a1..9f019832 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
@@ -49,24 +49,15 @@ namespace Apache.Ignite.Core.Tests.Cache
[TestFixtureSetUp]
public void FixtureSetUp()
{
- var cfg = new IgniteConfiguration
+ var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
{
CacheConfiguration = new List<CacheConfiguration>
{
new CacheConfiguration(),
GetCustomCacheConfiguration()
},
- JvmClasspath = TestUtils.CreateTestClasspath(),
- JvmOptions = TestUtils.TestJavaOptions(),
GridName = CacheName,
- BinaryConfiguration = new BinaryConfiguration(typeof(Entity)),
- DiscoverySpi = new TcpDiscoverySpi
- {
- IpFinder = new TcpDiscoveryStaticIpFinder
- {
- Endpoints = new[] { "127.0.0.1:47500", "127.0.0.1:47501" }
- }
- }
+ BinaryConfiguration = new BinaryConfiguration(typeof (Entity))
};
_ignite = Ignition.Start(cfg);
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
index 26696b9..c33d095 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
@@ -37,7 +37,7 @@ namespace Apache.Ignite.Core.Tests.Compute
public class ComputeApiTest
{
/** Echo task name. */
- private const string EchoTask = "org.apache.ignite.platform.PlatformComputeEchoTask";
+ public const string EchoTask = "org.apache.ignite.platform.PlatformComputeEchoTask";
/** Binary argument task name. */
private const string BinaryArgTask = "org.apache.ignite.platform.PlatformComputeBinarizableArgTask";
@@ -108,6 +108,9 @@ namespace Apache.Ignite.Core.Tests.Compute
/** Type: enum field. */
private const int EchoTypeEnumField = 18;
+ /** Type: affinity key. */
+ public const int EchoTypeAffinityKey = 19;
+
/** First node. */
private IIgnite _grid1;
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 6acc7c4..f1511d9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -67,6 +67,8 @@
<ItemGroup>
<Compile Include="Binary\BinaryReflectiveSerializer.cs" />
<Compile Include="Binary\Package-Info.cs" />
+ <Compile Include="Cache\Affinity\AffinityKey.cs" />
+ <Compile Include="Cache\Affinity\AffinityKeyMappedAttribute.cs" />
<Compile Include="Cache\CacheAtomicUpdateTimeoutException.cs" />
<Compile Include="Cache\CacheEntryProcessorException.cs" />
<Compile Include="Cache\CacheException.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKey.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKey.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKey.cs
new file mode 100644
index 0000000..1d27d65
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKey.cs
@@ -0,0 +1,162 @@
+/*
+ * 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.Cache.Affinity
+{
+ using System;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Impl.Binary;
+ using Apache.Ignite.Core.Impl.Common;
+
+ /// <summary>
+ /// Optional wrapper for cache keys to provide support for custom affinity mapping.
+ /// The value returned by <see cref="Affinity"/> will be used for key-to-node affinity.
+ /// </summary>
+ public struct AffinityKey : IEquatable<AffinityKey>, IBinaryWriteAware
+ {
+ /** User key. */
+ private readonly object _key;
+
+ /** Affinity key. */
+ private readonly object _affinity;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AffinityKey"/> struct.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ public AffinityKey(object key)
+ {
+ _key = key;
+ _affinity = null;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AffinityKey"/> struct.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <param name="affinity">The affinity key.</param>
+ public AffinityKey(object key, object affinity)
+ {
+ _key = key;
+ _affinity = affinity;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AffinityKey"/> struct.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ internal AffinityKey(IBinaryReader reader)
+ {
+ _key = reader.ReadObject<object>("key");
+ _affinity = reader.ReadObject<object>("affKey");
+ }
+
+ /// <summary>
+ /// Writes this object to the given writer.
+ /// </summary>
+ /// <param name="writer">Writer.</param>
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ IgniteArgumentCheck.NotNull(writer, "writer");
+
+ writer.WriteObject("key", _key);
+ writer.WriteObject("affKey", _affinity);
+ }
+
+ /// <summary>
+ /// Gets the key.
+ /// </summary>
+ public object Key
+ {
+ get { return _key; }
+ }
+
+ /// <summary>
+ /// Gets the affinity key.
+ /// </summary>
+ public object Affinity
+ {
+ get { return _affinity ?? _key; }
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns>
+ /// true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
+ /// </returns>
+ public bool Equals(AffinityKey other)
+ {
+ return Equals(_key, other._key) && Equals(_affinity, other._affinity);
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="object" />, is equal to this instance.
+ /// </summary>
+ /// <param name="obj">The <see cref="object" /> to compare with this instance.</param>
+ /// <returns>
+ /// <c>true</c> if the specified <see cref="object" /> is equal to this instance; otherwise, <c>false</c>.
+ /// </returns>
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ return obj is AffinityKey && Equals((AffinityKey) obj);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this instance.
+ /// </summary>
+ /// <returns>
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ /// </returns>
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ((_key != null ? _key.GetHashCode() : 0)*397) ^
+ (_affinity != null ? _affinity.GetHashCode() : 0);
+ }
+ }
+
+ /// <summary>
+ /// Implements the operator ==.
+ /// </summary>
+ /// <param name="left">The left.</param>
+ /// <param name="right">The right.</param>
+ /// <returns>
+ /// The result of the operator.
+ /// </returns>
+ public static bool operator ==(AffinityKey left, AffinityKey right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <summary>
+ /// Implements the operator !=.
+ /// </summary>
+ /// <param name="left">The left.</param>
+ /// <param name="right">The right.</param>
+ /// <returns>
+ /// The result of the operator.
+ /// </returns>
+ public static bool operator !=(AffinityKey left, AffinityKey right)
+ {
+ return !left.Equals(right);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKeyMappedAttribute.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKeyMappedAttribute.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKeyMappedAttribute.cs
new file mode 100644
index 0000000..1bfda9a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityKeyMappedAttribute.cs
@@ -0,0 +1,46 @@
+/*
+ * 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.Cache.Affinity
+{
+ using System;
+ using Apache.Ignite.Core.Binary;
+
+ /// <summary>
+ /// Specifies cache key field to be used to determine a node on which given cache key will be stored.
+ /// Only one field or property can be marked with this attribute.
+ /// <para />
+ /// This attribute is an alternative to <see cref="BinaryTypeConfiguration.AffinityKeyFieldName"/> setting.
+ /// This attribute has lower priority than <see cref="BinaryTypeConfiguration.AffinityKeyFieldName"/> setting.
+ /// <para />
+ /// One of the major use cases for this attribute is the routing of grid computations
+ /// to the nodes where the data for this computation is cached, the concept otherwise known as
+ /// Colocation Of Computations And Data.
+ /// <para />
+ /// For example, if a Person object is always accessed together with a Company object for which this person
+ /// is an employee, then for better performance and scalability it makes sense to colocate Person objects
+ /// together with their Company object when storing them in cache.
+ /// To achieve that, cache key used to cache Person objects should have a field or property marked with
+ /// <see cref="AffinityKeyMappedAttribute"/> attribute, which will provide the value of
+ /// the company key for which that person works.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
+ public sealed class AffinityKeyMappedAttribute : Attribute
+ {
+ // No-op.
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/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 73f3618..538fbcf 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -22,6 +22,7 @@ namespace Apache.Ignite.Core.Impl.Binary
using System.Diagnostics;
using System.Linq;
using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Cache.Affinity;
using Apache.Ignite.Core.Impl.Binary.IO;
using Apache.Ignite.Core.Impl.Binary.Metadata;
using Apache.Ignite.Core.Impl.Cache;
@@ -434,8 +435,10 @@ namespace Apache.Ignite.Core.Impl.Binary
"Configuration value: IsEnum={0}, actual type: IsEnum={1}",
typeCfg.IsEnum, type.IsEnum));
+ var affKeyFld = typeCfg.AffinityKeyFieldName ?? GetAffinityKeyFieldNameFromAttribute(type);
+
AddType(type, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, serializer,
- typeCfg.AffinityKeyFieldName, type.IsEnum);
+ affKeyFld, type.IsEnum);
}
else
{
@@ -450,6 +453,24 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Gets the affinity key field name from attribute.
+ /// </summary>
+ private static string GetAffinityKeyFieldNameFromAttribute(Type type)
+ {
+ var res = type.GetMembers()
+ .Where(x => x.GetCustomAttributes(false).OfType<AffinityKeyMappedAttribute>().Any())
+ .Select(x => x.Name).ToArray();
+
+ if (res.Length > 1)
+ {
+ throw new BinaryObjectException(string.Format("Multiple '{0}' attributes found on type '{1}'. " +
+ "There can be only one affinity field.", typeof (AffinityKeyMappedAttribute).Name, type));
+ }
+
+ return res.SingleOrDefault();
+ }
+
+ /// <summary>
/// Gets the <see cref="BinarizableSerializer"/> for a type if it is compatible.
/// </summary>
/// <param name="type">The type.</param>
@@ -512,13 +533,18 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Adds a predefined system type.
/// </summary>
- private void AddSystemType<T>(byte typeId, Func<BinaryReader, T> ctor) where T : IBinaryWriteAware
+ private void AddSystemType<T>(int typeId, Func<BinaryReader, T> ctor, string affKeyFldName = null)
+ where T : IBinaryWriteAware
{
var type = typeof(T);
var serializer = new BinarySystemTypeSerializer<T>(ctor);
- AddType(type, typeId, BinaryUtils.GetTypeName(type), false, false, null, null, serializer, null, false);
+ if (typeId == 0)
+ typeId = BinaryUtils.TypeId(type.Name, null, null);
+
+ AddType(type, typeId, BinaryUtils.GetTypeName(type), false, false, null, null, serializer, affKeyFldName,
+ false);
}
/// <summary>
@@ -541,6 +567,7 @@ namespace Apache.Ignite.Core.Impl.Binary
AddSystemType(BinaryUtils.TypeCacheEntryPredicateHolder, w => new CacheEntryFilterHolder(w));
AddSystemType(BinaryUtils.TypeMessageListenerHolder, w => new MessageListenerHolder(w));
AddSystemType(BinaryUtils.TypeStreamReceiverHolder, w => new StreamReceiverHolder(w));
+ AddSystemType(0, w => new AffinityKey(w), "affKey");
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f328e45/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/EmployeeKey.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/EmployeeKey.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/EmployeeKey.cs
index 04012be..16e5469 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/EmployeeKey.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/EmployeeKey.cs
@@ -18,6 +18,7 @@
namespace Apache.Ignite.ExamplesDll.Binary
{
using System;
+ using Apache.Ignite.Core.Cache.Affinity;
/// <summary>
/// Employee key. Used in query example to co-locate employees with their organizations.
@@ -44,6 +45,7 @@ namespace Apache.Ignite.ExamplesDll.Binary
/// <summary>
/// Organization ID.
/// </summary>
+ [AffinityKeyMapped]
public int OrganizationId { get; private set; }
/// <summary>