You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2016/06/30 09:10:53 UTC
ignite git commit: IGNITE-3371 .NET: Configure
PlatformAffinityFunction in Spring
Repository: ignite
Updated Branches:
refs/heads/master 140fe1933 -> 444d549ab
IGNITE-3371 .NET: Configure PlatformAffinityFunction in Spring
This closes #832
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/444d549a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/444d549a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/444d549a
Branch: refs/heads/master
Commit: 444d549ab51753f558120b718b093328e25ce85e
Parents: 140fe19
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Thu Jun 30 12:10:45 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Thu Jun 30 12:10:45 2016 +0300
----------------------------------------------------------------------
.../affinity/PlatformAffinityFunction.java | 24 ++-
.../PlatformDotNetConfigurationClosure.java | 41 ++++
.../dotnet/PlatformDotNetAffinityFunction.java | 211 +++++++++++++++++++
.../Apache.Ignite.Core.Tests.csproj | 4 +
.../Affinity/AffinityFunctionSpringTest.cs | 132 ++++++++++++
.../Cache/Affinity/AffinityFunctionTest.cs | 26 +++
.../Config/Cache/Affinity/affinity-function.xml | 87 ++++++++
.../Apache.Ignite.Core.Tests/TestRunner.cs | 2 +-
.../Cache/Affinity/AffinityFunctionBase.cs | 13 ++
.../dotnet/Apache.Ignite.Core/Ignition.cs | 41 ++--
.../Impl/Cache/Store/CacheStore.cs | 4 +-
.../Apache.Ignite.Core/Impl/IgniteUtils.cs | 12 +-
.../Impl/Unmanaged/UnmanagedCallbacks.cs | 8 +-
13 files changed, 579 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java
index 4da5e24..fc2496c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java
@@ -52,7 +52,13 @@ public class PlatformAffinityFunction implements AffinityFunction, Externalizabl
/** */
private Object userFunc;
- /** */
+ /**
+ * Partition count.
+ *
+ * 1) Java calls partitions() method very early (before LifecycleAware.start) during CacheConfiguration validation.
+ * 2) Partition count never changes.
+ * Therefore, we get the value on .NET side once, and pass it along with PlatformAffinity.
+ */
private int partitions;
/** */
@@ -76,13 +82,27 @@ public class PlatformAffinityFunction implements AffinityFunction, Externalizabl
* Ctor.
*
* @param func User fun object.
- * @param partitions Initial number of partitions.
+ * @param partitions Number of partitions.
*/
public PlatformAffinityFunction(Object func, int partitions) {
userFunc = func;
this.partitions = partitions;
}
+ /**
+ * Ctor.
+ *
+ * @param ptr User func ptr.
+ * @param partitions Number of partitions.
+ */
+ public PlatformAffinityFunction(PlatformContext ctx, long ptr, int partitions) {
+ this.ctx = ctx;
+ this.ptr = ptr;
+ this.partitions = partitions;
+
+ ignite = ctx.kernalContext().grid();
+ }
+
/** {@inheritDoc} */
public Object getUserFunc() {
return userFunc;
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
index db2fa4d..0a267fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
@@ -24,6 +24,7 @@ import org.apache.ignite.binary.BinaryBasicNameMapper;
import org.apache.ignite.binary.BinaryIdMapper;
import org.apache.ignite.binary.BinaryNameMapper;
import org.apache.ignite.configuration.BinaryConfiguration;
+import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.PlatformConfiguration;
import org.apache.ignite.internal.binary.BinaryMarshaller;
@@ -40,6 +41,7 @@ import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lifecycle.LifecycleBean;
import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction;
import org.apache.ignite.platform.dotnet.PlatformDotNetConfiguration;
import org.apache.ignite.platform.dotnet.PlatformDotNetLifecycleBean;
@@ -180,6 +182,7 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
PlatformConfigurationUtils.writeDotNetConfiguration(writer, interopCfg.unwrap());
+ // Write .NET beans
List<PlatformDotNetLifecycleBean> beans = beans(igniteCfg);
writer.writeInt(beans.size());
@@ -189,6 +192,14 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
writer.writeMap(bean.getProperties());
}
+ // Write .NET affinity funcs
+ List<PlatformDotNetAffinityFunction> affFuncs = affinityFunctions(igniteCfg);
+
+ writer.writeInt(affFuncs.size());
+
+ for (PlatformDotNetAffinityFunction func : affFuncs)
+ func.write(writer);
+
out.synchronize();
gate.extensionCallbackInLongLongOutLong(
@@ -209,6 +220,7 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
PlatformConfigurationUtils.readIgniteConfiguration(in, cfg);
+ // Process beans
List<PlatformDotNetLifecycleBean> beans = beans(cfg);
List<PlatformLifecycleBean> newBeans = new ArrayList<>();
@@ -240,6 +252,14 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
cfg.setLifecycleBeans(mergedBeans);
}
}
+
+ // Process affinity functions
+ List<PlatformDotNetAffinityFunction> affFuncs = affinityFunctions(cfg);
+
+ if (!affFuncs.isEmpty()) {
+ for (PlatformDotNetAffinityFunction aff : affFuncs)
+ aff.initPartitions(in.readInt());
+ }
}
/**
@@ -260,4 +280,25 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
return res;
}
+
+ /**
+ * Find .NET affinity functions in configuration.
+ *
+ * @param cfg Configuration.
+ * @return affinity functions.
+ */
+ private static List<PlatformDotNetAffinityFunction> affinityFunctions(IgniteConfiguration cfg) {
+ List<PlatformDotNetAffinityFunction> res = new ArrayList<>();
+
+ CacheConfiguration[] cacheCfg = cfg.getCacheConfiguration();
+
+ if (cacheCfg != null) {
+ for (CacheConfiguration ccfg : cacheCfg) {
+ if (ccfg.getAffinity() instanceof PlatformDotNetAffinityFunction)
+ res.add((PlatformDotNetAffinityFunction)ccfg.getAffinity());
+ }
+ }
+
+ return res;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java b/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java
new file mode 100644
index 0000000..6642693
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.platform.dotnet;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.cache.affinity.AffinityFunction;
+import org.apache.ignite.cache.affinity.AffinityFunctionContext;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.PlatformContext;
+import org.apache.ignite.internal.processors.platform.cache.affinity.PlatformAffinityFunction;
+import org.apache.ignite.internal.processors.platform.memory.PlatformMemory;
+import org.apache.ignite.internal.processors.platform.memory.PlatformOutputStream;
+import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
+import org.apache.ignite.lifecycle.LifecycleAware;
+import org.apache.ignite.resources.IgniteInstanceResource;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * AffinityFunction implementation which can be used to configure .NET affinity function in Java Spring configuration.
+ */
+public class PlatformDotNetAffinityFunction implements AffinityFunction, Externalizable, LifecycleAware {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** .NET type name. */
+ private String typName;
+
+ /** Properties. */
+ private Map<String, ?> props;
+
+ /**
+ * Partition count.
+ *
+ * 1) Java calls partitions() method very early (before LifecycleAware.start) during CacheConfiguration validation.
+ * 2) Partition count never changes.
+ * Therefore, we get the value on .NET side once, and pass it along with PlatformAffinity.
+ */
+ private int partitions;
+
+ /** Inner function. */
+ private transient PlatformAffinityFunction func;
+
+ /** Ignite. */
+ private transient Ignite ignite;
+
+ /**
+ * Gets .NET type name.
+ *
+ * @return .NET type name.
+ */
+ public String getTypeName() {
+ return typName;
+ }
+
+ /**
+ * Sets .NET type name.
+ *
+ * @param typName .NET type name.
+ */
+ public void setTypeName(String typName) {
+ this.typName = typName;
+ }
+
+ /**
+ * Get properties.
+ *
+ * @return Properties.
+ */
+ public Map<String, ?> getProperties() {
+ return props;
+ }
+
+ /**
+ * Set properties.
+ *
+ * @param props Properties.
+ */
+ public void setProperties(Map<String, ?> props) {
+ this.props = props;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void reset() {
+ assert func != null;
+
+ func.reset();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int partitions() {
+ return partitions;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int partition(Object key) {
+ assert func != null;
+
+ return func.partition(key);
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<List<ClusterNode>> assignPartitions(AffinityFunctionContext affCtx) {
+ assert func != null;
+
+ return func.assignPartitions(affCtx);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void removeNode(UUID nodeId) {
+ assert func != null;
+
+ func.removeNode(nodeId);
+ }
+
+ /**
+ * Writes this func to the writer.
+ *
+ * @param writer Writer.
+ */
+ public void write(BinaryRawWriter writer) {
+ assert writer != null;
+
+ writer.writeObject(typName);
+ writer.writeMap(props);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(typName);
+ out.writeObject(props);
+ out.writeInt(partitions);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ typName = (String)in.readObject();
+ props = (Map<String, ?>)in.readObject();
+ partitions = in.readInt();
+ }
+
+ /**
+ * Initializes the partitions count.
+ *
+ * @param partitions Number of partitions.
+ */
+ public void initPartitions(int partitions) {
+ this.partitions = partitions;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteException {
+ assert ignite != null;
+
+ PlatformContext ctx = PlatformUtils.platformContext(ignite);
+ assert ctx != null;
+
+ try (PlatformMemory mem = ctx.memory().allocate()) {
+ PlatformOutputStream out = mem.output();
+ BinaryRawWriterEx writer = ctx.writer(out);
+
+ write(writer);
+
+ out.synchronize();
+
+ long ptr = ctx.gateway().affinityFunctionInit(mem.pointer());
+
+ func = new PlatformAffinityFunction(ctx, ptr, partitions);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() throws IgniteException {
+ if (func != null)
+ func.stop();
+ }
+
+ /**
+ * Injects the Ignite.
+ *
+ * @param ignite Ignite.
+ */
+ @IgniteInstanceResource
+ private void setIgnite(Ignite ignite) {
+ this.ignite = ignite;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/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 15e46ae..a601dbd 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
@@ -60,6 +60,7 @@
<Compile Include="Binary\BinarySelfTestFullFooter.cs" />
<Compile Include="Binary\BinaryStringTest.cs" />
<Compile Include="Cache\Affinity\AffinityFieldTest.cs" />
+ <Compile Include="Cache\Affinity\AffinityFunctionSpringTest.cs" />
<Compile Include="Cache\Affinity\AffinityFunctionTest.cs" />
<Compile Include="Cache\CacheConfigurationTest.cs" />
<Compile Include="Cache\CacheDynamicStartTest.cs" />
@@ -208,6 +209,9 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Designer</SubType>
</Content>
+ <Content Include="Config\Cache\Affinity\affinity-function.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/444d549a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
new file mode 100644
index 0000000..33c0ce1
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
@@ -0,0 +1,132 @@
+\ufeff/*
+ * 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
+// ReSharper disable UnusedMember.Local
+namespace Apache.Ignite.Core.Tests.Cache.Affinity
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Affinity;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Resource;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests AffinityFunction defined in Spring XML.
+ /// </summary>
+ public class AffinityFunctionSpringTest : IgniteTestBase
+ {
+ /** */
+ private IIgnite _ignite;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AffinityFunctionSpringTest"/> class.
+ /// </summary>
+ public AffinityFunctionSpringTest() : base(3, "config\\cache\\affinity\\affinity-function.xml")
+ {
+ // No-op.
+ }
+
+ /** <inheritdoc /> */
+ public override void TestSetUp()
+ {
+ base.TestSetUp();
+
+ // Start another node without spring config
+ if (Ignition.TryGetIgnite("grid2") == null)
+ {
+ var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) {GridName = "grid2"};
+ _ignite = Ignition.Start(cfg);
+ }
+ }
+
+ /// <summary>
+ /// Tests the static cache.
+ /// </summary>
+ [Test]
+ public void TestStaticCache()
+ {
+ ValidateAffinityFunction(Grid.GetCache<int, int>("cache1"));
+ ValidateAffinityFunction(_ignite.GetCache<int, int>("cache1"));
+ }
+
+ /// <summary>
+ /// Tests the dynamic cache.
+ /// </summary>
+ [Test]
+ public void TestDynamicCache()
+ {
+ ValidateAffinityFunction(Grid.CreateCache<int, int>("dyn-cache-1"));
+ ValidateAffinityFunction(_ignite.GetCache<int, int>("dyn-cache-1"));
+
+ ValidateAffinityFunction(_ignite.CreateCache<int, int>("dyn-cache-2"));
+ ValidateAffinityFunction(Grid.GetCache<int, int>("dyn-cache-2"));
+ }
+
+ /// <summary>
+ /// Validates the affinity function.
+ /// </summary>
+ /// <param name="cache">The cache.</param>
+ private static void ValidateAffinityFunction(ICache<int, int> cache)
+ {
+ Assert.IsNull(cache.GetConfiguration().AffinityFunction);
+
+ var aff = cache.Ignite.GetAffinity(cache.Name);
+ Assert.AreEqual(5, aff.Partitions);
+ Assert.AreEqual(4, aff.GetPartition(2));
+ Assert.AreEqual(3, aff.GetPartition(4));
+ }
+
+ [Serializable]
+ private class TestFunc : IAffinityFunction
+ {
+ [InstanceResource]
+ private readonly IIgnite _ignite = null;
+
+ private int Property1 { get; set; }
+
+ private string Property2 { get; set; }
+
+ public int Partitions
+ {
+ get { return 5; }
+ }
+
+ public int GetPartition(object key)
+ {
+ Assert.IsNotNull(_ignite);
+ Assert.AreEqual(1, Property1);
+ Assert.AreEqual("1", Property2);
+
+ return (int) key * 2 % 5;
+ }
+
+ public void RemoveNode(Guid nodeId)
+ {
+ // No-op.
+ }
+
+ public IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)
+ {
+ return Enumerable.Range(0, Partitions).Select(x => context.CurrentTopologySnapshot);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
index 70e0d78..ed0a95b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
@@ -23,6 +23,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
using System.Linq;
using Apache.Ignite.Core.Cache;
using Apache.Ignite.Core.Cache.Affinity;
+ using Apache.Ignite.Core.Cache.Affinity.Fair;
using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Cluster;
using Apache.Ignite.Core.Common;
@@ -216,6 +217,25 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
Assert.AreEqual("User error", ex.InnerException.Message);
}
+ /// <summary>
+ /// Tests user-defined function that inherits predefined function.
+ /// </summary>
+ [Test]
+ public void TestInheritPredefinedFunction()
+ {
+ var ex = Assert.Throws<IgniteException>(() =>
+ _ignite.CreateCache<int, int>(
+ new CacheConfiguration("failCache3")
+ {
+ AffinityFunction = new FairAffinityFunctionInheritor()
+ }));
+
+ Assert.AreEqual("User-defined AffinityFunction can not inherit from " +
+ "Apache.Ignite.Core.Cache.Affinity.AffinityFunctionBase: " +
+ "Apache.Ignite.Core.Tests.Cache.Affinity.AffinityFunctionTest" +
+ "+FairAffinityFunctionInheritor", ex.Message);
+ }
+
[Serializable]
private class SimpleAffinityFunction : IAffinityFunction
{
@@ -278,5 +298,11 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
return Enumerable.Range(0, Partitions).Select(x => context.CurrentTopologySnapshot);
}
}
+
+ [Serializable]
+ private class FairAffinityFunctionInheritor : FairAffinityFunction
+ {
+ // No-op.
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml
new file mode 100644
index 0000000..e7fc516
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml
@@ -0,0 +1,87 @@
+\ufeff<?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="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="affinity">
+ <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction">
+ <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityFunctionSpringTest+TestFunc, Apache.Ignite.Core.Tests"/>
+ <property name="properties">
+ <map>
+ <entry key="Property1">
+ <value type="java.lang.Integer">1</value>
+ </entry>
+ <entry key="Property2" value="1"/>
+ </map>
+ </property>
+ </bean>
+ </property>
+ </bean>
+ <bean class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="dyn-cache-*"/>
+
+ <property name="affinity">
+ <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction">
+ <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityFunctionSpringTest+TestFunc, Apache.Ignite.Core.Tests"/>
+ <property name="properties">
+ <map>
+ <entry key="Property1">
+ <value type="java.lang.Integer">1</value>
+ </entry>
+ <entry key="Property2" value="1"/>
+ </map>
+ </property>
+ </bean>
+ </property>
+ </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/444d549a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
index 726fa3b..8f11122 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
@@ -50,7 +50,7 @@ namespace Apache.Ignite.Core.Tests
//TestOne(typeof(BinaryStringTest), "Test");
- TestAll(typeof (AffinityFunctionTest));
+ TestAll(typeof (AffinityFunctionSpringTest));
//TestAllInAssembly();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs
index 9b89780..3434384 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs
@@ -163,6 +163,7 @@ namespace Apache.Ignite.Core.Cache.Affinity
if (p != null)
{
+ ValidateAffinityFunctionType(p.GetType());
writer.WriteByte(p is FairAffinityFunction ? TypeCodeFair : TypeCodeRendezvous);
writer.WriteInt(p.Partitions);
writer.WriteBoolean(p.ExcludeNeighbors);
@@ -180,6 +181,18 @@ namespace Apache.Ignite.Core.Cache.Affinity
}
/// <summary>
+ /// Validates the type of the affinity function.
+ /// </summary>
+ private static void ValidateAffinityFunctionType(Type funcType)
+ {
+ if (funcType == typeof(FairAffinityFunction) || funcType == typeof(RendezvousAffinityFunction))
+ return;
+
+ throw new IgniteException(string.Format("User-defined AffinityFunction can not inherit from {0}: {1}",
+ typeof(AffinityFunctionBase), funcType));
+ }
+
+ /// <summary>
/// Gets the direct usage error.
/// </summary>
private Exception GetDirectUsageError()
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index a22c9d0..48eeec2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -27,6 +27,7 @@ namespace Apache.Ignite.Core
using System.Runtime;
using System.Threading;
using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Cache.Affinity;
using Apache.Ignite.Core.Common;
using Apache.Ignite.Core.Impl;
using Apache.Ignite.Core.Impl.Binary;
@@ -249,7 +250,7 @@ namespace Apache.Ignite.Core
/// <summary>
/// Prepare callback invoked from Java.
/// </summary>
- /// <param name="inStream">Intput stream with data.</param>
+ /// <param name="inStream">Input stream with data.</param>
/// <param name="outStream">Output stream.</param>
/// <param name="handleRegistry">Handle registry.</param>
internal static void OnPrepare(PlatformMemoryStream inStream, PlatformMemoryStream outStream,
@@ -262,6 +263,10 @@ namespace Apache.Ignite.Core
PrepareConfiguration(reader, outStream);
PrepareLifecycleBeans(reader, outStream, handleRegistry);
+
+ PrepareAffinityFunctions(reader, outStream);
+
+ outStream.SynchronizeOutput();
}
catch (Exception e)
{
@@ -306,7 +311,7 @@ namespace Apache.Ignite.Core
/// <param name="reader">Reader.</param>
/// <param name="outStream">Output stream.</param>
/// <param name="handleRegistry">Handle registry.</param>
- private static void PrepareLifecycleBeans(BinaryReader reader, PlatformMemoryStream outStream,
+ private static void PrepareLifecycleBeans(IBinaryRawReader reader, IBinaryStream outStream,
HandleRegistry handleRegistry)
{
IList<LifecycleBeanHolder> beans = new List<LifecycleBeanHolder>
@@ -318,9 +323,9 @@ namespace Apache.Ignite.Core
int cnt = reader.ReadInt();
for (int i = 0; i < cnt; i++)
- beans.Add(new LifecycleBeanHolder(CreateLifecycleBean(reader)));
+ beans.Add(new LifecycleBeanHolder(CreateObject<ILifecycleBean>(reader)));
- // 2. Append beans definied in local configuration.
+ // 2. Append beans defined in local configuration.
ICollection<ILifecycleBean> nativeBeans = _startup.Configuration.LifecycleBeans;
if (nativeBeans != null)
@@ -335,28 +340,32 @@ namespace Apache.Ignite.Core
foreach (LifecycleBeanHolder bean in beans)
outStream.WriteLong(handleRegistry.AllocateCritical(bean));
- outStream.SynchronizeOutput();
-
// 4. Set beans to STARTUP object.
_startup.LifecycleBeans = beans;
}
/// <summary>
- /// Create lifecycle bean.
+ /// Prepares the affinity functions.
/// </summary>
- /// <param name="reader">Reader.</param>
- /// <returns>Lifecycle bean.</returns>
- private static ILifecycleBean CreateLifecycleBean(BinaryReader reader)
+ private static void PrepareAffinityFunctions(BinaryReader reader, PlatformMemoryStream outStream)
{
- // 1. Instantiate.
- var bean = IgniteUtils.CreateInstance<ILifecycleBean>(reader.ReadString());
+ var cnt = reader.ReadInt();
- // 2. Set properties.
- var props = reader.ReadDictionaryAsGeneric<string, object>();
+ var writer = reader.Marshaller.StartMarshal(outStream);
- IgniteUtils.SetProperties(bean, props);
+ for (var i = 0; i < cnt; i++)
+ writer.WriteInt(CreateObject<IAffinityFunction>(reader).Partitions);
+ }
- return bean;
+ /// <summary>
+ /// Creates an object and sets the properties.
+ /// </summary>
+ /// <param name="reader">Reader.</param>
+ /// <returns>Resulting object.</returns>
+ private static T CreateObject<T>(IBinaryRawReader reader)
+ {
+ return IgniteUtils.CreateInstance<T>(reader.ReadString(),
+ reader.ReadDictionaryAsGeneric<string, object>());
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStore.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStore.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStore.cs
index 7785280..a297075 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStore.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Store/CacheStore.cs
@@ -115,9 +115,7 @@ namespace Apache.Ignite.Core.Impl.Cache.Store
var className = reader.ReadString();
var propertyMap = reader.ReadDictionaryAsGeneric<string, object>();
- store = IgniteUtils.CreateInstance<ICacheStore>(className);
-
- IgniteUtils.SetProperties(store, propertyMap);
+ store = IgniteUtils.CreateInstance<ICacheStore>(className, propertyMap);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
index e992e81..94f6166 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
@@ -140,8 +140,9 @@ namespace Apache.Ignite.Core.Impl
/// Create new instance of specified class.
/// </summary>
/// <param name="typeName">Class name</param>
+ /// <param name="props">Properties to set.</param>
/// <returns>New Instance.</returns>
- public static T CreateInstance<T>(string typeName)
+ public static T CreateInstance<T>(string typeName, IEnumerable<KeyValuePair<string, object>> props = null)
{
IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
@@ -150,7 +151,12 @@ namespace Apache.Ignite.Core.Impl
if (type == null)
throw new IgniteException("Failed to create class instance [className=" + typeName + ']');
- return (T) Activator.CreateInstance(type);
+ var res = (T) Activator.CreateInstance(type);
+
+ if (props != null)
+ SetProperties(res, props);
+
+ return res;
}
/// <summary>
@@ -158,7 +164,7 @@ namespace Apache.Ignite.Core.Impl
/// </summary>
/// <param name="target">Target object.</param>
/// <param name="props">Properties.</param>
- public static void SetProperties(object target, IEnumerable<KeyValuePair<string, object>> props)
+ private static void SetProperties(object target, IEnumerable<KeyValuePair<string, object>> props)
{
if (props == null)
return;
http://git-wip-us.apache.org/repos/asf/ignite/blob/444d549a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
index 408b48f..176d3b4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@ -1115,7 +1115,13 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
{
using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
{
- var func = _ignite.Marshaller.Unmarshal<IAffinityFunction>(stream);
+ var reader = _ignite.Marshaller.StartUnmarshal(stream);
+
+ var funcOrTypeName = reader.ReadObject<object>();
+
+ var func = funcOrTypeName as IAffinityFunction
+ ?? IgniteUtils.CreateInstance<IAffinityFunction>((string) funcOrTypeName,
+ reader.ReadDictionaryAsGeneric<string, object>());
ResourceProcessor.Inject(func, _ignite);