You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2015/09/05 04:32:16 UTC
[33/45] ignite git commit: IGNITE-1348: Moved GridGain's .Net module
to Ignite.
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/JobEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/JobEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/JobEvent.cs
new file mode 100644
index 0000000..81d537f
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/JobEvent.cs
@@ -0,0 +1,100 @@
+/*
+ * 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.Events
+{
+ using System;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Ignite job event.
+ /// </summary>
+ public sealed class JobEvent : EventBase
+ {
+ /** */
+ private readonly string _taskName;
+
+ /** */
+ private readonly string _taskClassName;
+
+ /** */
+ private readonly IgniteGuid _taskSessionId;
+
+ /** */
+ private readonly IgniteGuid _jobId;
+
+ /** */
+ private readonly IClusterNode _taskNode;
+
+ /** */
+ private readonly Guid _taskSubjectId;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="r">The reader to read data from.</param>
+ internal JobEvent(IPortableRawReader r) : base(r)
+ {
+ _taskName = r.ReadString();
+ _taskClassName = r.ReadString();
+ _taskSessionId = IgniteGuid.ReadPortable(r);
+ _jobId = IgniteGuid.ReadPortable(r);
+ _taskNode = ReadNode(r);
+ _taskSubjectId = r.ReadGuid() ?? Guid.Empty;
+ }
+
+ /// <summary>
+ /// Gets name of the task that triggered the event.
+ /// </summary>
+ public string TaskName { get { return _taskName; } }
+
+ /// <summary>
+ /// Gets name of task class that triggered this event.
+ /// </summary>
+ public string TaskClassName { get { return _taskClassName; } }
+
+ /// <summary>
+ /// Gets task session ID of the task that triggered this event.
+ /// </summary>
+ public IgniteGuid TaskSessionId { get { return _taskSessionId; } }
+
+ /// <summary>
+ /// Gets job ID.
+ /// </summary>
+ public IgniteGuid JobId { get { return _jobId; } }
+
+ /// <summary>
+ /// Get node where parent task of the job has originated.
+ /// </summary>
+ public IClusterNode TaskNode { get { return _taskNode; } }
+
+ /// <summary>
+ /// Gets task subject ID.
+ /// </summary>
+ public Guid TaskSubjectId { get { return _taskSubjectId; } }
+
+ /** <inheritDoc /> */
+ public override string ToShortString()
+ {
+ return string.Format("{0}: TaskName={1}, TaskClassName={2}, TaskSessionId={3}, JobId={4}, TaskNode={5}, " +
+ "TaskSubjectId={6}", Name, TaskName, TaskClassName, TaskSessionId, JobId, TaskNode,
+ TaskSubjectId);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/SwapSpaceEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/SwapSpaceEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/SwapSpaceEvent.cs
new file mode 100644
index 0000000..676c2e0
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/SwapSpaceEvent.cs
@@ -0,0 +1,50 @@
+/*
+ * 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.Events
+{
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Grid swap space event.
+ /// </summary>
+ public sealed class SwapSpaceEvent : EventBase
+ {
+ /** */
+ private readonly string _space;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="r">The reader to read data from.</param>
+ internal SwapSpaceEvent(IPortableRawReader r) : base(r)
+ {
+ _space = r.ReadString();
+ }
+
+ /// <summary>
+ /// Gets swap space name.
+ /// </summary>
+ public string Space { get { return _space; } }
+
+ /** <inheritDoc /> */
+ public override string ToShortString()
+ {
+ return string.Format("{0}: Space={1}", Name, Space);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/TaskEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/TaskEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/TaskEvent.cs
new file mode 100644
index 0000000..7149fb3
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/TaskEvent.cs
@@ -0,0 +1,91 @@
+/*
+ * 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.Events
+{
+ using System;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Ignite task event.
+ /// </summary>
+ public sealed class TaskEvent : EventBase
+ {
+ /** */
+ private readonly string _taskName;
+
+ /** */
+ private readonly string _taskClassName;
+
+ /** */
+ private readonly IgniteGuid _taskSessionId;
+
+ /** */
+ private readonly bool _internal;
+
+ /** */
+ private readonly Guid _subjectId;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="r">The reader to read data from.</param>
+ internal TaskEvent(IPortableRawReader r) : base(r)
+ {
+ _taskName = r.ReadString();
+ _taskClassName = r.ReadString();
+ _taskSessionId = IgniteGuid.ReadPortable(r);
+ _internal = r.ReadBoolean();
+ _subjectId = r.ReadGuid() ?? Guid.Empty;
+ }
+
+ /// <summary>
+ /// Gets name of the task that triggered the event.
+ /// </summary>
+ public string TaskName { get { return _taskName; } }
+
+ /// <summary>
+ /// Gets name of task class that triggered this event.
+ /// </summary>
+ public string TaskClassName { get { return _taskClassName; } }
+
+ /// <summary>
+ /// Gets session ID of the task that triggered the event.
+ /// </summary>
+ public IgniteGuid TaskSessionId { get { return _taskSessionId; } }
+
+ /// <summary>
+ /// Returns true if task is created by Ignite and is used for system needs.
+ /// </summary>
+ public bool Internal { get { return _internal; } }
+
+ /// <summary>
+ /// Gets security subject ID initiated this task event, if available. This property is not available for
+ /// <see cref="EventType.EvtTaskSessionAttrSet" /> task event.
+ /// Subject ID will be set either to node ID or client ID initiated task execution.
+ /// </summary>
+ public Guid SubjectId { get { return _subjectId; } }
+
+ /** <inheritDoc /> */
+ public override string ToShortString()
+ {
+ return string.Format("{0}: TaskName={1}, TaskClassName={2}, TaskSessionId={3}, Internal={4}, " +
+ "SubjectId={5}", Name, TaskName, TaskClassName, TaskSessionId, Internal, SubjectId);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/IIgnite.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/IIgnite.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/IIgnite.cs
new file mode 100644
index 0000000..b691254
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/IIgnite.cs
@@ -0,0 +1,168 @@
+/*
+ * 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
+{
+ using System;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Compute;
+ using Apache.Ignite.Core.Datastream;
+ using Apache.Ignite.Core.Events;
+ using Apache.Ignite.Core.Messaging;
+ using Apache.Ignite.Core.Portable;
+ using Apache.Ignite.Core.Services;
+ using Apache.Ignite.Core.Transactions;
+
+ /// <summary>
+ /// Main entry point for all Ignite APIs.
+ /// You can obtain an instance of <c>IGrid</c> through <see cref="Ignition.GetIgnite()"/>,
+ /// or for named grids you can use <see cref="Ignition.GetIgnite(string)"/>. Note that you
+ /// can have multiple instances of <c>IGrid</c> running in the same process by giving
+ /// each instance a different name.
+ /// <para/>
+ /// All members are thread-safe and may be used concurrently from multiple threads.
+ /// </summary>
+ public interface IIgnite : IDisposable
+ {
+ /// <summary>
+ /// Gets the name of the grid this Ignite instance (and correspondingly its local node) belongs to.
+ /// Note that single process can have multiple Ignite instances all belonging to different grids. Grid
+ /// name allows to indicate to what grid this particular Ignite instance (i.e. Ignite runtime and its
+ /// local node) belongs to.
+ /// <p/>
+ /// If default Ignite instance is used, then <c>null</c> is returned. Refer to <see cref="Ignition"/> documentation
+ /// for information on how to start named grids.
+ /// </summary>
+ /// <returns>Name of the grid, or <c>null</c> for default grid.</returns>
+ string Name { get; }
+
+ /// <summary>
+ /// Gets an instance of <see cref="ICluster" /> interface.
+ /// </summary>
+ ICluster Cluster { get; }
+
+ /// <summary>
+ /// Gets compute functionality over this grid projection. All operations
+ /// on the returned ICompute instance will only include nodes from
+ /// this projection.
+ /// </summary>
+ /// <returns>Compute instance over this grid projection.</returns>
+ ICompute Compute();
+
+ /// <summary>
+ /// Gets compute functionality over specified grid projection. All operations
+ /// on the returned ICompute instance will only include nodes from
+ /// that projection.
+ /// </summary>
+ /// <returns>Compute instance over specified grid projection.</returns>
+ ICompute Compute(IClusterGroup clusterGroup);
+
+ /// <summary>
+ /// Gets the cache instance for the given name to work with keys and values of specified types.
+ /// <para/>
+ /// You can get instances of ICache of the same name, but with different key/value types.
+ /// These will use the same named cache, but only allow working with entries of specified types.
+ /// Attempt to retrieve an entry of incompatible type will result in <see cref="InvalidCastException"/>.
+ /// Use <see cref="Cache{Object, Object}"/> in order to work with entries of arbitrary types.
+ /// </summary>
+ /// <param name="name">Cache name.</param>
+ /// <returns>Cache instance for given name.</returns>
+ /// <typeparam name="TK">Cache key type.</typeparam>
+ /// <typeparam name="TV">Cache value type.</typeparam>
+ ICache<TK, TV> Cache<TK, TV>(string name);
+
+ /// <summary>
+ /// Gets existing cache with the given name or creates new one using template configuration.
+ /// </summary>
+ /// <typeparam name="TK">Cache key type.</typeparam>
+ /// <typeparam name="TV">Cache value type.</typeparam>
+ /// <param name="name">Cache name.</param>
+ /// <returns>Existing or newly created cache.</returns>
+ ICache<TK, TV> GetOrCreateCache<TK, TV>(string name);
+
+ /// <summary>
+ /// Dynamically starts new cache using template configuration.
+ /// </summary>
+ /// <typeparam name="TK">Cache key type.</typeparam>
+ /// <typeparam name="TV">Cache value type.</typeparam>
+ /// <param name="name">Cache name.</param>
+ /// <returns>Existing or newly created cache.</returns>
+ ICache<TK, TV> CreateCache<TK, TV>(string name);
+
+ /// <summary>
+ /// Gets a new instance of data streamer associated with given cache name. Data streamer
+ /// is responsible for loading external data into Ignite. For more information
+ /// refer to <see cref="IDataStreamer{K,V}"/> documentation.
+ /// </summary>
+ /// <param name="cacheName">Cache name (<c>null</c> for default cache).</param>
+ /// <returns>Data streamer.</returns>
+ IDataStreamer<TK, TV> DataStreamer<TK, TV>(string cacheName);
+
+ /// <summary>
+ /// Gets an instance of <see cref="IPortables"/> interface.
+ /// </summary>
+ /// <returns>Instance of <see cref="IPortables"/> interface</returns>
+ IPortables Portables();
+
+ /// <summary>
+ /// Gets affinity service to provide information about data partitioning and distribution.
+ /// </summary>
+ /// <param name="name">Cache name.</param>
+ /// <returns>Cache data affinity service.</returns>
+ ICacheAffinity Affinity(string name);
+
+ /// <summary>
+ /// Gets Ignite transactions facade.
+ /// </summary>
+ ITransactions Transactions { get; }
+
+ /// <summary>
+ /// Gets messaging facade over all cluster nodes.
+ /// </summary>
+ /// <returns>Messaging instance over all cluster nodes.</returns>
+ IMessaging Message();
+
+ /// <summary>
+ /// Gets messaging facade over nodes within the cluster group. All operations on the returned
+ /// <see cref="IMessaging"/>> instance will only include nodes from the specified cluster group.
+ /// </summary>
+ /// <param name="clusterGroup">Cluster group.</param>
+ /// <returns>Messaging instance over given cluster group.</returns>
+ IMessaging Message(IClusterGroup clusterGroup);
+
+ /// <summary>
+ /// Gets events facade over all cluster nodes.
+ /// </summary>
+ /// <returns>Events facade over all cluster nodes.</returns>
+ IEvents Events();
+
+ /// <summary>
+ /// Gets events facade over nodes within the cluster group. All operations on the returned
+ /// <see cref="IEvents"/>> instance will only include nodes from the specified cluster group.
+ /// </summary>
+ /// <param name="clusterGroup">Cluster group.</param>
+ /// <returns>Events instance over given cluster group.</returns>
+ IEvents Events(IClusterGroup clusterGroup);
+
+ /// <summary>
+ /// Gets services facade over all cluster nodes.
+ /// </summary>
+ /// <returns>Services facade over all cluster nodes.</returns>
+ IServices Services();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
new file mode 100644
index 0000000..5a03e93
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -0,0 +1,140 @@
+/*
+ * 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
+{
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using Apache.Ignite.Core.Lifecycle;
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Grid configuration.
+ /// </summary>
+ public class IgniteConfiguration
+ {
+ /// <summary>
+ /// Default initial JVM memory in megabytes.
+ /// </summary>
+ public const int DefaultJvmInitMem = 512;
+
+ /// <summary>
+ /// Default maximum JVM memory in megabytes.
+ /// </summary>
+ public const int DefaultJvmMaxMem = 1024;
+
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ public IgniteConfiguration()
+ {
+ JvmInitialMemoryMb = DefaultJvmInitMem;
+ JvmMaxMemoryMb = DefaultJvmMaxMem;
+ }
+
+ /// <summary>
+ /// Copying constructor.
+ /// </summary>
+ /// <param name="cfg">Configuration.</param>
+ internal IgniteConfiguration(IgniteConfiguration cfg)
+ {
+ SpringConfigUrl = cfg.SpringConfigUrl;
+ JvmDllPath = cfg.JvmDllPath;
+ IgniteHome = cfg.IgniteHome;
+ JvmClasspath = cfg.JvmClasspath;
+ SuppressWarnings = cfg.SuppressWarnings;
+
+ JvmOptions = cfg.JvmOptions != null ? new List<string>(cfg.JvmOptions) : null;
+ Assemblies = cfg.Assemblies != null ? new List<string>(cfg.Assemblies) : null;
+
+ PortableConfiguration = cfg.PortableConfiguration != null
+ ? new PortableConfiguration(cfg.PortableConfiguration)
+ : null;
+
+ LifecycleBeans = cfg.LifecycleBeans != null ? new List<ILifecycleBean>(cfg.LifecycleBeans) : null;
+
+ JvmInitialMemoryMb = cfg.JvmInitialMemoryMb;
+ JvmMaxMemoryMb = cfg.JvmMaxMemoryMb;
+ }
+
+ /// <summary>
+ /// Gets or sets the portable configuration.
+ /// </summary>
+ /// <value>
+ /// The portable configuration.
+ /// </value>
+ public PortableConfiguration PortableConfiguration { get; set; }
+
+ /// <summary>
+ /// URL to Spring configuration file.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]
+ public string SpringConfigUrl { get; set; }
+
+ /// <summary>
+ /// Path jvm.dll file. If not set, it's location will be determined
+ /// using JAVA_HOME environment variable.
+ /// If path is neither set nor determined automatically, an exception
+ /// will be thrown.
+ /// </summary>
+ public string JvmDllPath { get; set; }
+
+ /// <summary>
+ /// Path to Ignite home. If not set environment variable IGNITE_HOME will be used.
+ /// </summary>
+ public string IgniteHome { get; set; }
+
+ /// <summary>
+ /// Classpath used by JVM on Ignite start.
+ /// </summary>
+ public string JvmClasspath { get; set; }
+
+ /// <summary>
+ /// Collection of options passed to JVM on Ignite start.
+ /// </summary>
+ public ICollection<string> JvmOptions { get; set; }
+
+ /// <summary>
+ /// List of additional .Net assemblies to load on Ignite start. Each item can be either
+ /// fully qualified assembly name, path to assembly to DLL or path to a directory when
+ /// assemblies reside.
+ /// </summary>
+ public IList<string> Assemblies { get; set; }
+
+ /// <summary>
+ /// Whether to suppress warnings.
+ /// </summary>
+ public bool SuppressWarnings { get; set; }
+
+ /// <summary>
+ /// Lifecycle beans.
+ /// </summary>
+ public ICollection<ILifecycleBean> LifecycleBeans { get; set; }
+
+ /// <summary>
+ /// Initial amount of memory in megabytes given to JVM. Maps to -Xms Java option.
+ /// Defaults to <see cref="DefaultJvmInitMem"/>.
+ /// </summary>
+ public int JvmInitialMemoryMb { get; set; }
+
+ /// <summary>
+ /// Maximum amount of memory in megabytes given to JVM. Maps to -Xmx Java option.
+ /// Defaults to <see cref="DefaultJvmMaxMem"/>.
+ /// </summary>
+ public int JvmMaxMemoryMb { get; set; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Ignition.cs
index a61a1a8..ef79008 100644
--- a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -1,4 +1,4 @@
-/*
+/*
* 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.
@@ -15,9 +15,629 @@
* limitations under the License.
*/
-namespace Apache.Ignite.Core
+namespace Apache.Ignite.Core
{
- public class Ignition
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Reflection;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Impl;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Impl.Handle;
+ using Apache.Ignite.Core.Impl.Interop;
+ using Apache.Ignite.Core.Impl.Memory;
+ using Apache.Ignite.Core.Impl.Portable;
+ using Apache.Ignite.Core.Impl.Portable.IO;
+ using Apache.Ignite.Core.Impl.Unmanaged;
+ using Apache.Ignite.Core.Lifecycle;
+ using UU = Apache.Ignite.Core.Impl.Unmanaged.UnmanagedUtils;
+ using PU = Apache.Ignite.Core.Impl.Portable.PortableUtils;
+
+ /// <summary>
+ /// This class defines a factory for the main Ignite API.
+ /// <p/>
+ /// Use <see cref="Ignition.Start()"/> method to start Ignite with default configuration.
+ /// <para/>
+ /// All members are thread-safe and may be used concurrently from multiple threads.
+ /// <example>
+ /// You can also use <see cref="IgniteConfiguration"/> to override some default configuration.
+ /// Below is an example on how to start Ignite with custom configuration for portable types and
+ /// provide path to Spring XML configuration file:
+ /// <code>
+ /// IgniteConfiguration cfg = new IgniteConfiguration();
+ ///
+ /// // Create portable type configuration.
+ /// PortableConfiguration portableCfg = new PortableConfiguration();
+ ///
+ /// cfg.SpringConfigUrl = "examples\\config\\example-cache.xml";
+ ///
+ /// portableCfg.TypeConfigurations = new List<PortableTypeConfiguration>
+ /// {
+ /// new PortableTypeConfiguration(typeof(Address)),
+ /// new PortableTypeConfiguration(typeof(Organization))
+ /// };
+ ///
+ /// cfg.PortableConfiguration = portableCfg;
+ ///
+ /// // Start Ignite node with Ignite configuration.
+ /// var ignite = Ignition.Start(cfg);
+ /// </code>
+ /// </example>
+ /// </summary>
+ public static class Ignition
{
+ /** */
+ private const string DefaultCfg = "config/default-config.xml";
+
+ /** */
+ private static readonly object SyncRoot = new object();
+
+ /** GC warning flag. */
+ private static int _gcWarn;
+
+ /** */
+ private static readonly IDictionary<NodeKey, Ignite> Nodes = new Dictionary<NodeKey, Ignite>();
+
+ /** Current DLL name. */
+ private static readonly string IgniteDllName = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
+
+ /** Startup info. */
+ [ThreadStatic]
+ private static Startup _startup;
+
+ /** Client mode flag. */
+ [ThreadStatic]
+ private static bool _clientMode;
+
+ /// <summary>
+ /// Static initializer.
+ /// </summary>
+ static Ignition()
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Ignite should be started in client mode.
+ /// Client nodes cannot hold data in caches.
+ /// </summary>
+ public static bool ClientMode
+ {
+ get { return _clientMode; }
+ set { _clientMode = value; }
+ }
+
+ /// <summary>
+ /// Starts Ignite with default configuration. By default this method will
+ /// use Ignite configuration defined in <code>IGNITE/config/default-config.xml</code>
+ /// configuration file. If such file is not found, then all system defaults will be used.
+ /// </summary>
+ /// <returns>Started Ignite.</returns>
+ public static IIgnite Start()
+ {
+ return Start(new IgniteConfiguration());
+ }
+
+ /// <summary>
+ /// Starts all grids specified within given Spring XML configuration file. If Ignite with given name
+ /// is already started, then exception is thrown. In this case all instances that may
+ /// have been started so far will be stopped too.
+ /// </summary>
+ /// <param name="springCfgPath">Spring XML configuration file path or URL. Note, that the path can be
+ /// absolute or relative to IGNITE_HOME.</param>
+ /// <returns>Started Ignite. If Spring configuration contains multiple Ignite instances, then the 1st
+ /// found instance is returned.</returns>
+ public static IIgnite Start(string springCfgPath)
+ {
+ return Start(new IgniteConfiguration {SpringConfigUrl = springCfgPath});
+ }
+
+ /// <summary>
+ /// Starts Ignite with given configuration.
+ /// </summary>
+ /// <returns>Started Ignite.</returns>
+ public unsafe static IIgnite Start(IgniteConfiguration cfg)
+ {
+ IgniteArgumentCheck.NotNull(cfg, "cfg");
+
+ // Copy configuration to avoid changes to user-provided instance.
+ IgniteConfigurationEx cfgEx = cfg as IgniteConfigurationEx;
+
+ cfg = cfgEx == null ? new IgniteConfiguration(cfg) : new IgniteConfigurationEx(cfgEx);
+
+ // Set default Spring config if needed.
+ if (cfg.SpringConfigUrl == null)
+ cfg.SpringConfigUrl = DefaultCfg;
+
+ lock (SyncRoot)
+ {
+ // 1. Check GC settings.
+ CheckServerGc(cfg);
+
+ // 2. Create context.
+ IgniteUtils.LoadDlls(cfg.JvmDllPath);
+
+ var cbs = new UnmanagedCallbacks();
+
+ void* ctx = IgniteManager.GetContext(cfg, cbs);
+
+ sbyte* cfgPath0 = IgniteUtils.StringToUtf8Unmanaged(cfg.SpringConfigUrl ?? DefaultCfg);
+
+ string gridName = cfgEx != null ? cfgEx.GridName : null;
+ sbyte* gridName0 = IgniteUtils.StringToUtf8Unmanaged(gridName);
+
+ // 3. Create startup object which will guide us through the rest of the process.
+ _startup = new Startup(cfg) { Context = ctx };
+
+ IUnmanagedTarget interopProc = null;
+
+ try
+ {
+ // 4. Initiate Ignite start.
+ interopProc = UU.IgnitionStart(cbs.Context, cfg.SpringConfigUrl ?? DefaultCfg,
+ cfgEx != null ? cfgEx.GridName : null, ClientMode);
+
+ // 5. At this point start routine is finished. We expect STARTUP object to have all necessary data.
+ Ignite node = new Ignite(cfg, _startup.Name, interopProc, _startup.Marshaller,
+ _startup.LifecycleBeans, cbs);
+
+ // 6. On-start callback (notify lifecycle components).
+ node.OnStart();
+
+ Nodes[new NodeKey(_startup.Name)] = node;
+
+ return node;
+ }
+ catch (Exception)
+ {
+ // 1. Perform keys cleanup.
+ string name = _startup.Name;
+
+ if (name != null)
+ {
+ NodeKey key = new NodeKey(name);
+
+ if (Nodes.ContainsKey(key))
+ Nodes.Remove(key);
+ }
+
+ // 2. Stop Ignite node if it was started.
+ if (interopProc != null)
+ UU.IgnitionStop(interopProc.Context, gridName, true);
+
+ // 3. Throw error further (use startup error if exists because it is more precise).
+ if (_startup.Error != null)
+ throw _startup.Error;
+
+ throw;
+ }
+ finally
+ {
+ _startup = null;
+
+ Marshal.FreeHGlobal((IntPtr)cfgPath0);
+
+ if ((IntPtr)gridName0 != IntPtr.Zero)
+ Marshal.FreeHGlobal((IntPtr)gridName0);
+
+ if (interopProc != null)
+ UU.ProcessorReleaseStart(interopProc);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Check whether GC is set to server mode.
+ /// </summary>
+ /// <param name="cfg">Configuration.</param>
+ private static void CheckServerGc(IgniteConfiguration cfg)
+ {
+ if (!cfg.SuppressWarnings && !GCSettings.IsServerGC && Interlocked.CompareExchange(ref _gcWarn, 1, 0) == 0)
+ Console.WriteLine("GC server mode is not enabled, this could lead to less " +
+ "than optimal performance on multi-core machines (to enable see " +
+ "http://msdn.microsoft.com/en-us/library/ms229357(v=vs.110).aspx).");
+ }
+
+ /// <summary>
+ /// Prepare callback invoked from Java.
+ /// </summary>
+ /// <param name="inStream">Intput stream with data.</param>
+ /// <param name="outStream">Output stream.</param>
+ /// <param name="handleRegistry">Handle registry.</param>
+ internal static void OnPrepare(PlatformMemoryStream inStream, PlatformMemoryStream outStream,
+ HandleRegistry handleRegistry)
+ {
+ try
+ {
+ PortableReaderImpl reader = PU.Marshaller.StartUnmarshal(inStream);
+
+ PrepareConfiguration(reader.ReadObject<InteropDotNetConfiguration>());
+
+ PrepareLifecycleBeans(reader, outStream, handleRegistry);
+ }
+ catch (Exception e)
+ {
+ _startup.Error = e;
+
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// Preapare configuration.
+ /// </summary>
+ /// <param name="dotNetCfg">Dot net configuration.</param>
+ private static void PrepareConfiguration(InteropDotNetConfiguration dotNetCfg)
+ {
+ // 1. Load assemblies.
+ IgniteConfiguration cfg = _startup.Configuration;
+
+ LoadAssemblies(cfg.Assemblies);
+
+ if (dotNetCfg != null)
+ LoadAssemblies(dotNetCfg.Assemblies);
+
+ // 2. Create marshaller only after assemblies are loaded.
+ if (cfg.PortableConfiguration == null && dotNetCfg != null && dotNetCfg.PortableCfg != null)
+ cfg.PortableConfiguration = dotNetCfg.PortableCfg.ToPortableConfiguration();
+
+ _startup.Marshaller = new PortableMarshaller(cfg.PortableConfiguration);
+ }
+
+ /// <summary>
+ /// Prepare lifecycle beans.
+ /// </summary>
+ /// <param name="reader">Reader.</param>
+ /// <param name="outStream">Output stream.</param>
+ /// <param name="handleRegistry">Handle registry.</param>
+ private static void PrepareLifecycleBeans(PortableReaderImpl reader, PlatformMemoryStream outStream,
+ HandleRegistry handleRegistry)
+ {
+ IList<LifecycleBeanHolder> beans = new List<LifecycleBeanHolder>();
+
+ // 1. Read beans defined in Java.
+ int cnt = reader.ReadInt();
+
+ for (int i = 0; i < cnt; i++)
+ beans.Add(new LifecycleBeanHolder(CreateLifecycleBean(reader)));
+
+ // 2. Append beans definied in local configuration.
+ ICollection<ILifecycleBean> nativeBeans = _startup.Configuration.LifecycleBeans;
+
+ if (nativeBeans != null)
+ {
+ foreach (ILifecycleBean nativeBean in nativeBeans)
+ beans.Add(new LifecycleBeanHolder(nativeBean));
+ }
+
+ // 3. Write bean pointers to Java stream.
+ outStream.WriteInt(beans.Count);
+
+ 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.
+ /// </summary>
+ /// <param name="reader">Reader.</param>
+ /// <returns>Lifecycle bean.</returns>
+ internal static ILifecycleBean CreateLifecycleBean(PortableReaderImpl reader)
+ {
+ // 1. Instantiate.
+ string assemblyName = reader.ReadString();
+ string clsName = reader.ReadString();
+
+ object bean = IgniteUtils.CreateInstance(assemblyName, clsName);
+
+ // 2. Set properties.
+ IDictionary<string, object> props = reader.ReadGenericDictionary<string, object>();
+
+ IgniteUtils.SetProperties(bean, props);
+
+ return bean as ILifecycleBean;
+ }
+
+ /// <summary>
+ /// Kernal start callback.
+ /// </summary>
+ /// <param name="stream">Stream.</param>
+ internal static void OnStart(IPortableStream stream)
+ {
+ try
+ {
+ // 1. Read data and leave critical state ASAP.
+ PortableReaderImpl reader = PU.Marshaller.StartUnmarshal(stream);
+
+ // ReSharper disable once PossibleInvalidOperationException
+ var name = reader.ReadString();
+
+ // 2. Set ID and name so that Start() method can use them later.
+ _startup.Name = name;
+
+ if (Nodes.ContainsKey(new NodeKey(name)))
+ throw new IgniteException("Ignite with the same name already started: " + name);
+
+ }
+ catch (Exception e)
+ {
+ // 5. Preserve exception to throw it later in the "Start" method and throw it further
+ // to abort startup in Java.
+ _startup.Error = e;
+
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// Load assemblies.
+ /// </summary>
+ /// <param name="assemblies">Assemblies.</param>
+ private static void LoadAssemblies(IEnumerable<string> assemblies)
+ {
+ if (assemblies != null)
+ {
+ foreach (string s in assemblies)
+ {
+ // 1. Try loading as directory.
+ if (Directory.Exists(s))
+ {
+ string[] files = Directory.GetFiles(s, "*.dll");
+
+#pragma warning disable 0168
+
+ foreach (string dllPath in files)
+ {
+ if (!SelfAssembly(dllPath))
+ {
+ try
+ {
+ Assembly.LoadFile(dllPath);
+ }
+
+ catch (BadImageFormatException)
+ {
+ // No-op.
+ }
+ }
+ }
+
+#pragma warning restore 0168
+
+ continue;
+ }
+
+ // 2. Try loading using full-name.
+ try
+ {
+ Assembly assembly = Assembly.Load(s);
+
+ if (assembly != null)
+ continue;
+ }
+ catch (Exception e)
+ {
+ if (!(e is FileNotFoundException || e is FileLoadException))
+ throw new IgniteException("Failed to load assembly: " + s, e);
+ }
+
+ // 3. Try loading using file path.
+ try
+ {
+ Assembly assembly = Assembly.LoadFrom(s);
+
+ if (assembly != null)
+ continue;
+ }
+ catch (Exception e)
+ {
+ if (!(e is FileNotFoundException || e is FileLoadException))
+ throw new IgniteException("Failed to load assembly: " + s, e);
+ }
+
+ // 4. Not found, exception.
+ throw new IgniteException("Failed to load assembly: " + s);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Whether assembly points to Ignite binary.
+ /// </summary>
+ /// <param name="assembly">Assembly to check..</param>
+ /// <returns><c>True</c> if this is one of GG assemblies.</returns>
+ private static bool SelfAssembly(string assembly)
+ {
+ return assembly.EndsWith(IgniteDllName, StringComparison.OrdinalIgnoreCase);
+ }
+
+ /// <summary>
+ /// Gets a named Ignite instance. If Ignite name is {@code null} or empty string,
+ /// then default no-name Ignite will be returned. Note that caller of this method
+ /// should not assume that it will return the same instance every time.
+ /// <p/>
+ /// Note that single process can run multiple Ignite instances and every Ignite instance (and its
+ /// node) can belong to a different grid. Ignite name defines what grid a particular Ignite
+ /// instance (and correspondingly its node) belongs to.
+ /// </summary>
+ /// <param name="name">Ignite name to which requested Ignite instance belongs. If <code>null</code>,
+ /// then Ignite instance belonging to a default no-name Ignite will be returned.
+ /// </param>
+ /// <returns>An instance of named grid.</returns>
+ public static IIgnite GetIgnite(string name)
+ {
+ lock (SyncRoot)
+ {
+ Ignite result;
+
+ if (!Nodes.TryGetValue(new NodeKey(name), out result))
+ throw new IgniteException("Ignite instance was not properly started or was already stopped: " + name);
+
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Gets an instance of default no-name grid. Note that
+ /// caller of this method should not assume that it will return the same
+ /// instance every time.
+ /// </summary>
+ /// <returns>An instance of default no-name grid.</returns>
+ public static IIgnite GetIgnite()
+ {
+ return GetIgnite(null);
+ }
+
+ /// <summary>
+ /// Stops named grid. If <code>cancel</code> flag is set to <code>true</code> then
+ /// all jobs currently executing on local node will be interrupted. If
+ /// grid name is <code>null</code>, then default no-name Ignite will be stopped.
+ /// </summary>
+ /// <param name="name">Grid name. If <code>null</code>, then default no-name Ignite will be stopped.</param>
+ /// <param name="cancel">If <code>true</code> then all jobs currently executing will be cancelled
+ /// by calling <code>ComputeJob.cancel</code>method.</param>
+ /// <returns><code>true</code> if named Ignite instance was indeed found and stopped, <code>false</code>
+ /// othwerwise (the instance with given <code>name</code> was not found).</returns>
+ public static bool Stop(string name, bool cancel)
+ {
+ lock (SyncRoot)
+ {
+ NodeKey key = new NodeKey(name);
+
+ Ignite node;
+
+ if (!Nodes.TryGetValue(key, out node))
+ return false;
+
+ node.Stop(cancel);
+
+ Nodes.Remove(key);
+
+ GC.Collect();
+
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Stops <b>all</b> started grids. If <code>cancel</code> flag is set to <code>true</code> then
+ /// all jobs currently executing on local node will be interrupted.
+ /// </summary>
+ /// <param name="cancel">If <code>true</code> then all jobs currently executing will be cancelled
+ /// by calling <code>ComputeJob.cancel</code>method.</param>
+ public static void StopAll(bool cancel)
+ {
+ lock (SyncRoot)
+ {
+ while (Nodes.Count > 0)
+ {
+ var entry = Nodes.First();
+
+ entry.Value.Stop(cancel);
+
+ Nodes.Remove(entry.Key);
+ }
+ }
+
+ GC.Collect();
+ }
+
+ /// <summary>
+ /// Handles the AssemblyResolve event of the CurrentDomain control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="args">The <see cref="ResolveEventArgs"/> instance containing the event data.</param>
+ /// <returns>Manually resolved assembly, or null.</returns>
+ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ return LoadedAssembliesResolver.Instance.GetAssembly(args.Name);
+ }
+
+ /// <summary>
+ /// Grid key.
+ /// </summary>
+ private class NodeKey
+ {
+ /** */
+ private readonly string _name;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NodeKey"/> class.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ internal NodeKey(string name)
+ {
+ _name = name;
+ }
+
+ /** <inheritdoc /> */
+ public override bool Equals(object obj)
+ {
+ var other = obj as NodeKey;
+
+ return other != null && Equals(_name, other._name);
+ }
+
+ /** <inheritdoc /> */
+ public override int GetHashCode()
+ {
+ return _name == null ? 0 : _name.GetHashCode();
+ }
+ }
+
+ /// <summary>
+ /// Value object to pass data between .Net methods during startup bypassing Java.
+ /// </summary>
+ private unsafe class Startup
+ {
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="cfg">Configuration.</param>
+ internal Startup(IgniteConfiguration cfg)
+ {
+ Configuration = cfg;
+ }
+
+ /// <summary>
+ /// Configuration.
+ /// </summary>
+ internal IgniteConfiguration Configuration { get; private set; }
+
+ /// <summary>
+ /// Lifecycle beans.
+ /// </summary>
+ internal IList<LifecycleBeanHolder> LifecycleBeans { get; set; }
+
+ /// <summary>
+ /// Node name.
+ /// </summary>
+ internal string Name { get; set; }
+
+ /// <summary>
+ /// Marshaller.
+ /// </summary>
+ internal PortableMarshaller Marshaller { get; set; }
+
+ /// <summary>
+ /// Start error.
+ /// </summary>
+ internal Exception Error { get; set; }
+
+ /// <summary>
+ /// Gets or sets the context.
+ /// </summary>
+ internal void* Context { get; set; }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheAffinityImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheAffinityImpl.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheAffinityImpl.cs
new file mode 100644
index 0000000..6d577ce
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheAffinityImpl.cs
@@ -0,0 +1,275 @@
+/*
+ * 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.Impl.Cache
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Impl.Portable;
+ using Apache.Ignite.Core.Impl.Portable.IO;
+ using Apache.Ignite.Core.Impl.Unmanaged;
+ using UU = Apache.Ignite.Core.Impl.Unmanaged.UnmanagedUtils;
+
+ /// <summary>
+ /// Cache affinity implementation.
+ /// </summary>
+ internal class CacheAffinityImpl : PlatformTarget, ICacheAffinity
+ {
+ /** */
+ private const int OpAffinityKey = 1;
+
+ /** */
+ private const int OpAllPartitions = 2;
+
+ /** */
+ private const int OpBackupPartitions = 3;
+
+ /** */
+ private const int OpIsBackup = 4;
+
+ /** */
+ private const int OpIsPrimary = 5;
+
+ /** */
+ private const int OpIsPrimaryOrBackup = 6;
+
+ /** */
+ private const int OpMapKeyToNode = 7;
+
+ /** */
+ private const int OpMapKeyToPrimaryAndBackups = 8;
+
+ /** */
+ private const int OpMapKeysToNodes = 9;
+
+ /** */
+ private const int OpMapPartitionToNode = 10;
+
+ /** */
+ private const int OpMapPartitionToPrimaryAndBackups = 11;
+
+ /** */
+ private const int OpMapPartitionsToNodes = 12;
+
+ /** */
+ private const int OpPartition = 13;
+
+ /** */
+ private const int OpPrimaryPartitions = 14;
+
+ /** */
+ private readonly bool _keepPortable;
+
+ /** Grid. */
+ private readonly Ignite _ignite;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheAffinityImpl" /> class.
+ /// </summary>
+ /// <param name="target">Target.</param>
+ /// <param name="marsh">Marshaller.</param>
+ /// <param name="keepPortable">Keep portable flag.</param>
+ /// <param name="ignite">Grid.</param>
+ public CacheAffinityImpl(IUnmanagedTarget target, PortableMarshaller marsh, bool keepPortable,
+ Ignite ignite) : base(target, marsh)
+ {
+ _keepPortable = keepPortable;
+
+ Debug.Assert(ignite != null);
+
+ _ignite = ignite;
+ }
+
+ /** <inheritDoc /> */
+ public int Partitions
+ {
+ get { return UU.AffinityPartitions(Target); }
+ }
+
+ /** <inheritDoc /> */
+ public int Partition<TK>(TK key)
+ {
+ IgniteArgumentCheck.NotNull(key, "key");
+
+ return (int)DoOutOp(OpPartition, key);
+ }
+
+ /** <inheritDoc /> */
+ public bool IsPrimary<TK>(IClusterNode n, TK key)
+ {
+ IgniteArgumentCheck.NotNull(n, "n");
+
+ IgniteArgumentCheck.NotNull(key, "key");
+
+ return DoOutOp(OpIsPrimary, n.Id, key) == True;
+ }
+
+ /** <inheritDoc /> */
+ public bool IsBackup<TK>(IClusterNode n, TK key)
+ {
+ IgniteArgumentCheck.NotNull(n, "n");
+
+ IgniteArgumentCheck.NotNull(key, "key");
+
+ return DoOutOp(OpIsBackup, n.Id, key) == True;
+ }
+
+ /** <inheritDoc /> */
+ public bool IsPrimaryOrBackup<TK>(IClusterNode n, TK key)
+ {
+ IgniteArgumentCheck.NotNull(n, "n");
+
+ IgniteArgumentCheck.NotNull(key, "key");
+
+ return DoOutOp(OpIsPrimaryOrBackup, n.Id, key) == True;
+ }
+
+ /** <inheritDoc /> */
+ public int[] PrimaryPartitions(IClusterNode n)
+ {
+ IgniteArgumentCheck.NotNull(n, "n");
+
+ return DoOutInOp<Guid, int[]>(OpPrimaryPartitions, n.Id);
+ }
+
+ /** <inheritDoc /> */
+ public int[] BackupPartitions(IClusterNode n)
+ {
+ IgniteArgumentCheck.NotNull(n, "n");
+
+ return DoOutInOp<Guid, int[]>(OpBackupPartitions, n.Id);
+ }
+
+ /** <inheritDoc /> */
+ public int[] AllPartitions(IClusterNode n)
+ {
+ IgniteArgumentCheck.NotNull(n, "n");
+
+ return DoOutInOp<Guid, int[]>(OpAllPartitions, n.Id);
+ }
+
+ /** <inheritDoc /> */
+ public TR AffinityKey<TK, TR>(TK key)
+ {
+ IgniteArgumentCheck.NotNull(key, "key");
+
+ return DoOutInOp<TK, TR>(OpAffinityKey, key);
+ }
+
+ /** <inheritDoc /> */
+ public IDictionary<IClusterNode, IList<TK>> MapKeysToNodes<TK>(IList<TK> keys)
+ {
+ IgniteArgumentCheck.NotNull(keys, "keys");
+
+ return DoOutInOp(OpMapKeysToNodes, w => w.WriteObject(keys),
+ reader => ReadDictionary(reader, ReadNode, r => r.ReadObject<IList<TK>>()));
+ }
+
+ /** <inheritDoc /> */
+ public IClusterNode MapKeyToNode<TK>(TK key)
+ {
+ IgniteArgumentCheck.NotNull(key, "key");
+
+ return GetNode(DoOutInOp<TK, Guid?>(OpMapKeyToNode, key));
+ }
+
+ /** <inheritDoc /> */
+ public IList<IClusterNode> MapKeyToPrimaryAndBackups<TK>(TK key)
+ {
+ IgniteArgumentCheck.NotNull(key, "key");
+
+ return DoOutInOp(OpMapKeyToPrimaryAndBackups, w => w.WriteObject(key), r => ReadNodes(r));
+ }
+
+ /** <inheritDoc /> */
+ public IClusterNode MapPartitionToNode(int part)
+ {
+ return GetNode(DoOutInOp<int, Guid?>(OpMapPartitionToNode, part));
+ }
+
+ /** <inheritDoc /> */
+ public IDictionary<int, IClusterNode> MapPartitionsToNodes(IList<int> parts)
+ {
+ IgniteArgumentCheck.NotNull(parts, "parts");
+
+ return DoOutInOp(OpMapPartitionsToNodes,
+ w => w.WriteObject(parts),
+ reader => ReadDictionary(reader, r => r.ReadInt(), ReadNode));
+ }
+
+ /** <inheritDoc /> */
+ public IList<IClusterNode> MapPartitionToPrimaryAndBackups(int part)
+ {
+ return DoOutInOp(OpMapPartitionToPrimaryAndBackups, w => w.WriteObject(part), r => ReadNodes(r));
+ }
+
+ /** <inheritDoc /> */
+ protected override T Unmarshal<T>(IPortableStream stream)
+ {
+ return Marshaller.Unmarshal<T>(stream, _keepPortable);
+ }
+
+
+ /// <summary>
+ /// Gets the node by id.
+ /// </summary>
+ /// <param name="id">The id.</param>
+ /// <returns>Node.</returns>
+ private IClusterNode GetNode(Guid? id)
+ {
+ return _ignite.GetNode(id);
+ }
+
+ /// <summary>
+ /// Reads a node from stream.
+ /// </summary>
+ private IClusterNode ReadNode(PortableReaderImpl r)
+ {
+ return GetNode(r.ReadGuid());
+ }
+
+ /// <summary>
+ /// Reads nodes from stream.
+ /// </summary>
+ private IList<IClusterNode> ReadNodes(IPortableStream reader)
+ {
+ return IgniteUtils.ReadNodes(Marshaller.StartUnmarshal(reader, _keepPortable));
+ }
+
+ /// <summary>
+ /// Reads a dictionary from stream.
+ /// </summary>
+ private Dictionary<TK, TV> ReadDictionary<TK, TV>(IPortableStream reader, Func<PortableReaderImpl, TK> readKey,
+ Func<PortableReaderImpl, TV> readVal)
+ {
+ var r = Marshaller.StartUnmarshal(reader, _keepPortable);
+
+ var cnt = r.ReadInt();
+
+ var dict = new Dictionary<TK, TV>(cnt);
+
+ for (var i = 0; i < cnt; i++)
+ dict[readKey(r)] = readVal(r);
+
+ return dict;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntry.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntry.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntry.cs
new file mode 100644
index 0000000..e28b3e2
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntry.cs
@@ -0,0 +1,126 @@
+/*
+ * 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.Impl.Cache
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Cache;
+
+ /// <summary>
+ /// Represents a cache entry.
+ /// </summary>
+ internal struct CacheEntry<TK, TV> : ICacheEntry<TK, TV>
+ {
+ /** Key. */
+ private readonly TK _key;
+
+ /** Value. */
+ private readonly TV _val;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntry{K,V}"/> struct.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <param name="val">The value.</param>
+ public CacheEntry(TK key, TV val)
+ {
+ _key = key;
+ _val = val;
+ }
+
+ /// <summary>
+ /// Gets the key.
+ /// </summary>
+ public TK Key
+ {
+ get { return _key; }
+ }
+
+ /// <summary>
+ /// Gets the value.
+ /// </summary>
+ public TV Value
+ {
+ get { return _val; }
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="CacheEntry{K,V}"/>, is equal to this instance.
+ /// </summary>
+ /// <param name="other">The <see cref="CacheEntry{K,V}"/> to compare with this instance.</param>
+ /// <returns>
+ /// <c>true</c> if the specified <see cref="CacheEntry{K,V}"/> is equal to this instance;
+ /// otherwise, <c>false</c>.
+ /// </returns>
+ public bool Equals(CacheEntry<TK, TV> other)
+ {
+ return EqualityComparer<TK>.Default.Equals(_key, other._key) &&
+ EqualityComparer<TV>.Default.Equals(_val, other._val);
+ }
+
+ /** <inheritDoc /> */
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+
+ return obj is CacheEntry<TK, TV> && Equals((CacheEntry<TK, TV>) obj);
+ }
+
+ /** <inheritDoc /> */
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (EqualityComparer<TK>.Default.GetHashCode(_key) * 397) ^
+ EqualityComparer<TV>.Default.GetHashCode(_val);
+ }
+ }
+
+ /** <inheritDoc /> */
+ public override string ToString()
+ {
+ return string.Format("CacheEntry [Key={0}, Value={1}]", _key, _val);
+ }
+
+ /// <summary>
+ /// Implements the operator ==.
+ /// </summary>
+ /// <param name="a">First item.</param>
+ /// <param name="b">Second item.</param>
+ /// <returns>
+ /// The result of the operator.
+ /// </returns>
+ public static bool operator ==(CacheEntry<TK, TV> a, CacheEntry<TK, TV> b)
+ {
+ return a.Equals(b);
+ }
+
+ /// <summary>
+ /// Implements the operator !=.
+ /// </summary>
+ /// <param name="a">First item.</param>
+ /// <param name="b">Second item.</param>
+ /// <returns>
+ /// The result of the operator.
+ /// </returns>
+ public static bool operator !=(CacheEntry<TK, TV> a, CacheEntry<TK, TV> b)
+ {
+ return !(a == b);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryFilterHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryFilterHolder.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryFilterHolder.cs
new file mode 100644
index 0000000..1181645
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryFilterHolder.cs
@@ -0,0 +1,147 @@
+/*
+ * 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.Impl.Cache
+{
+ using System;
+ using System.Diagnostics;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Impl.Portable;
+ using Apache.Ignite.Core.Impl.Portable.IO;
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Non-generic portable filter wrapper.
+ /// </summary>
+ internal class CacheEntryFilterHolder : IPortableWriteAware
+ {
+ /** Wrapped ICacheEntryFilter */
+ private readonly object _pred;
+
+ /** Invoker function that takes key and value and invokes wrapped ICacheEntryFilter */
+ private readonly Func<object, object, bool> _invoker;
+
+ /** Keep portable flag. */
+ private readonly bool _keepPortable;
+
+ /** Grid. */
+ private readonly PortableMarshaller _marsh;
+
+ /** Handle. */
+ private readonly long _handle;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntryFilterHolder" /> class.
+ /// </summary>
+ /// <param name="pred">The <see cref="ICacheEntryFilter{TK,TV}" /> to wrap.</param>
+ /// <param name="invoker">The invoker func that takes key and value and invokes wrapped ICacheEntryFilter.</param>
+ /// <param name="marsh">Marshaller.</param>
+ /// <param name="keepPortable">Keep portable flag.</param>
+ public CacheEntryFilterHolder(object pred, Func<object, object, bool> invoker, PortableMarshaller marsh,
+ bool keepPortable)
+ {
+ Debug.Assert(pred != null);
+ Debug.Assert(invoker != null);
+ Debug.Assert(marsh != null);
+
+ _pred = pred;
+ _invoker = invoker;
+ _marsh = marsh;
+ _keepPortable = keepPortable;
+
+ _handle = marsh.Ignite.HandleRegistry.Allocate(this);
+ }
+
+ /// <summary>
+ /// Gets the handle.
+ /// </summary>
+ public long Handle
+ {
+ get { return _handle; }
+ }
+
+ /// <summary>
+ /// Invokes the cache filter.
+ /// </summary>
+ /// <param name="input">The input stream.</param>
+ /// <returns>Invocation result.</returns>
+ public int Invoke(IPortableStream input)
+ {
+ var rawReader = _marsh.StartUnmarshal(input, _keepPortable).RawReader();
+
+ return _invoker(rawReader.ReadObject<object>(), rawReader.ReadObject<object>()) ? 1 : 0;
+ }
+
+ /** <inheritdoc /> */
+ public void WritePortable(IPortableWriter writer)
+ {
+ var writer0 = (PortableWriterImpl)writer.RawWriter();
+
+ writer0.DetachNext();
+ PortableUtils.WritePortableOrSerializable(writer0, _pred);
+
+ writer0.WriteBoolean(_keepPortable);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntryFilterHolder"/> class.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public CacheEntryFilterHolder(IPortableReader reader)
+ {
+ var reader0 = (PortableReaderImpl)reader.RawReader();
+
+ _pred = PortableUtils.ReadPortableOrSerializable<object>(reader0);
+
+ _keepPortable = reader0.ReadBoolean();
+
+ _marsh = reader0.Marshaller;
+
+ _invoker = GetInvoker(_pred);
+
+ _handle = _marsh.Ignite.HandleRegistry.Allocate(this);
+ }
+
+ /// <summary>
+ /// Gets the invoker func.
+ /// </summary>
+ private static Func<object, object, bool> GetInvoker(object pred)
+ {
+ var func = DelegateTypeDescriptor.GetCacheEntryFilter(pred.GetType());
+
+ return (key, val) => func(pred, key, val);
+ }
+
+ /// <summary>
+ /// Creates an instance of this class from a stream.
+ /// </summary>
+ /// <param name="memPtr">Memory pointer.</param>
+ /// <param name="grid">Grid.</param>
+ /// <returns>Deserialized instance of <see cref="CacheEntryFilterHolder"/></returns>
+ public static CacheEntryFilterHolder CreateInstance(long memPtr, Ignite grid)
+ {
+ var stream = IgniteManager.Memory.Get(memPtr).Stream();
+
+ Debug.Assert(grid != null);
+
+ var marsh = grid.Marshaller;
+
+ return marsh.Unmarshal<CacheEntryFilterHolder>(stream);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorHolder.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorHolder.cs
new file mode 100644
index 0000000..4ec1e1e
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorHolder.cs
@@ -0,0 +1,145 @@
+/*
+ * 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.Impl.Cache
+{
+ using System;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Reflection;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Impl.Portable;
+ using Apache.Ignite.Core.Impl.Resource;
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Portable wrapper for the <see cref="ICacheEntryProcessor{TK,TV,TA,TR}"/> and it's argument.
+ /// Marshals and executes wrapped processor with a non-generic interface.
+ /// </summary>
+ internal class CacheEntryProcessorHolder : IPortableWriteAware
+ {
+ // generic processor
+ private readonly object _proc;
+
+ // argument
+ private readonly object _arg;
+
+ // func to invoke Process method on ICacheEntryProcessor in form of object.
+ private readonly Func<IMutableCacheEntryInternal, object, object> _processFunc;
+
+ // entry creator delegate
+ private readonly Func<object, object, bool, IMutableCacheEntryInternal> _entryCtor;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntryProcessorHolder"/> class.
+ /// </summary>
+ /// <param name="proc">The processor to wrap.</param>
+ /// <param name="arg">The argument.</param>
+ /// <param name="processFunc">Delegate to call generic <see cref="ICacheEntryProcessor{K, V, A, R}.Process"/> on local node.</param>
+ /// <param name="keyType">Type of the key.</param>
+ /// <param name="valType">Type of the value.</param>
+ public CacheEntryProcessorHolder(object proc, object arg,
+ Func<IMutableCacheEntryInternal, object, object> processFunc, Type keyType, Type valType)
+ {
+ Debug.Assert(proc != null);
+ Debug.Assert(processFunc != null);
+
+ _proc = proc;
+ _arg = arg;
+ _processFunc = processFunc;
+
+ _processFunc = GetProcessFunc(_proc);
+
+ _entryCtor = MutableCacheEntry.GetCtor(keyType, valType);
+ }
+
+ /// <summary>
+ /// Processes specified cache entry.
+ /// </summary>
+ /// <param name="key">The cache entry key.</param>
+ /// <param name="value">The cache entry value.</param>
+ /// <param name="exists">Indicates whether cache entry exists.</param>
+ /// <param name="grid"></param>
+ /// <returns>
+ /// Pair of resulting cache entry and result of processing it.
+ /// </returns>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
+ Justification = "User processor can throw any exception")]
+ public CacheEntryProcessorResultHolder Process(object key, object value, bool exists, Ignite grid)
+ {
+ ResourceProcessor.Inject(_proc, grid);
+
+ var entry = _entryCtor(key, value, exists);
+
+ try
+ {
+ return new CacheEntryProcessorResultHolder(entry, _processFunc(entry, _arg), null);
+ }
+ catch (TargetInvocationException ex)
+ {
+ return new CacheEntryProcessorResultHolder(null, null, ex.InnerException);
+ }
+ catch (Exception ex)
+ {
+ return new CacheEntryProcessorResultHolder(null, null, ex);
+ }
+ }
+
+ /** <inheritDoc /> */
+ public void WritePortable(IPortableWriter writer)
+ {
+ var writer0 = (PortableWriterImpl) writer.RawWriter();
+
+ writer0.DetachNext();
+ PortableUtils.WritePortableOrSerializable(writer0, _proc);
+ PortableUtils.WritePortableOrSerializable(writer0, _arg);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntryProcessorHolder"/> class.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public CacheEntryProcessorHolder(IPortableReader reader)
+ {
+ var reader0 = (PortableReaderImpl) reader.RawReader();
+
+ _proc = PortableUtils.ReadPortableOrSerializable<object>(reader0);
+ _arg = PortableUtils.ReadPortableOrSerializable<object>(reader0);
+
+ _processFunc = GetProcessFunc(_proc);
+
+ var kvTypes = DelegateTypeDescriptor.GetCacheEntryProcessorTypes(_proc.GetType());
+
+ _entryCtor = MutableCacheEntry.GetCtor(kvTypes.Item1, kvTypes.Item2);
+ }
+
+ /// <summary>
+ /// Gets a delegate to call generic <see cref="ICacheEntryProcessor{K, V, A, R}.Process"/>.
+ /// </summary>
+ /// <param name="proc">The processor instance.</param>
+ /// <returns>
+ /// Delegate to call generic <see cref="ICacheEntryProcessor{K, V, A, R}.Process"/>.
+ /// </returns>
+ private static Func<IMutableCacheEntryInternal, object, object> GetProcessFunc(object proc)
+ {
+ var func = DelegateTypeDescriptor.GetCacheEntryProcessor(proc.GetType());
+
+ return (entry, arg) => func(proc, entry, arg);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResult.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResult.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResult.cs
new file mode 100644
index 0000000..9a0af4f
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResult.cs
@@ -0,0 +1,65 @@
+/*
+ * 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.Impl.Cache
+{
+ using System;
+ using Apache.Ignite.Core.Cache;
+
+ /// <summary>
+ /// Represents a result of <see cref="ICacheEntryProcessor{TK,TV,TA,TR}"/> invocation.
+ /// </summary>
+ /// <typeparam name="T">Result type.</typeparam>
+ internal class CacheEntryProcessorResult<T> : ICacheEntryProcessorResult<T>
+ {
+ // Result
+ private readonly T _res;
+
+ // Error
+ private readonly Exception _err;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntryProcessorResult{T}"/> class.
+ /// </summary>
+ /// <param name="result">The result.</param>
+ public CacheEntryProcessorResult(T result)
+ {
+ _res = result;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntryProcessorResult{T}"/> class.
+ /// </summary>
+ /// <param name="error">The error.</param>
+ public CacheEntryProcessorResult(Exception error)
+ {
+ _err = error;
+ }
+
+ /** <inheritdoc /> */
+ public T Result
+ {
+ get
+ {
+ if (_err != null)
+ throw _err as CacheEntryProcessorException ?? new CacheEntryProcessorException(_err);
+
+ return _res;
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResultHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResultHolder.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResultHolder.cs
new file mode 100644
index 0000000..04cd557
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEntryProcessorResultHolder.cs
@@ -0,0 +1,127 @@
+/*
+ * 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.Impl.Cache
+{
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.IO;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Impl.Portable;
+ using Apache.Ignite.Core.Impl.Portable.IO;
+
+ /// <summary>
+ /// Manages cache entry processing result in non-generic form.
+ /// </summary>
+ internal class CacheEntryProcessorResultHolder
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheEntryProcessorResultHolder"/> class.
+ /// </summary>
+ /// <param name="entry">Entry.</param>
+ /// <param name="processResult">Process result.</param>
+ /// <param name="error">Error.</param>
+ public CacheEntryProcessorResultHolder(IMutableCacheEntryInternal entry, object processResult, Exception error)
+ {
+ Entry = entry;
+ ProcessResult = processResult;
+ Error = error;
+ }
+
+ /// <summary>
+ /// Gets the entry.
+ /// </summary>
+ public IMutableCacheEntryInternal Entry { get; private set; }
+
+ /// <summary>
+ /// Gets the process result.
+ /// </summary>
+ public object ProcessResult { get; private set; }
+
+ /// <summary>
+ /// Gets the error.
+ /// </summary>
+ public Exception Error { get; private set; }
+
+ /// <summary>
+ /// Writes this instance to the stream.
+ /// </summary>
+ /// <param name="stream">Stream.</param>
+ /// <param name="marsh">Marshaller.</param>
+ public void Write(IPortableStream stream, PortableMarshaller marsh)
+ {
+ var writer = marsh.StartMarshal(stream);
+
+ try
+ {
+ Marshal(writer);
+ }
+ finally
+ {
+ marsh.FinishMarshal(writer);
+ }
+ }
+
+ /// <summary>
+ /// Marshal this instance.
+ /// </summary>
+ /// <param name="writer">Writer.</param>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
+ Justification = "Any kind of exception can be thrown during user type marshalling.")]
+ private void Marshal(PortableWriterImpl writer)
+ {
+ var pos = writer.Stream.Position;
+
+ try
+ {
+ if (Error == null)
+ {
+ writer.WriteByte((byte) Entry.State);
+
+ if (Entry.State == MutableCacheEntryState.ValueSet)
+ writer.Write(Entry.Value);
+
+ writer.Write(ProcessResult);
+ }
+ else
+ {
+ writer.WriteByte((byte) MutableCacheEntryState.ErrPortable);
+ writer.Write(new PortableResultWrapper(Error));
+ }
+ }
+ catch (Exception marshErr)
+ {
+ writer.Stream.Seek(pos, SeekOrigin.Begin);
+
+ writer.WriteByte((byte) MutableCacheEntryState.ErrString);
+
+ if (Error == null)
+ {
+ writer.WriteString(string.Format(
+ "CacheEntryProcessor completed with error, but result serialization failed [errType={0}, " +
+ "err={1}, serializationErrMsg={2}]", marshErr.GetType().Name, marshErr, marshErr.Message));
+ }
+ else
+ {
+ writer.WriteString(string.Format(
+ "CacheEntryProcessor completed with error, and error serialization failed [errType={0}, " +
+ "err={1}, serializationErrMsg={2}]", marshErr.GetType().Name, marshErr, marshErr.Message));
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEnumerable.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEnumerable.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEnumerable.cs
new file mode 100644
index 0000000..2dd03c9
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Impl/Cache/CacheEnumerable.cs
@@ -0,0 +1,82 @@
+/*
+ * 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.Impl.Cache
+{
+ using System.Collections;
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Cache;
+
+ /// <summary>
+ /// Cache enumerable.
+ /// </summary>
+ internal class CacheEnumerable<TK, TV> : IEnumerable<ICacheEntry<TK, TV>>
+ {
+ /** Target cache. */
+ private readonly CacheImpl<TK, TV> _cache;
+
+ /** Local flag. */
+ private readonly bool _loc;
+
+ /** Peek modes. */
+ private readonly int _peekModes;
+
+ /// <summary>
+ /// Constructor for distributed iterator.
+ /// </summary>
+ /// <param name="cache">Target cache.</param>
+ public CacheEnumerable(CacheImpl<TK, TV> cache) : this(cache, false, 0)
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Constructor for local iterator.
+ /// </summary>
+ /// <param name="cache">Target cache.</param>
+ /// <param name="peekModes">Peek modes.</param>
+ public CacheEnumerable(CacheImpl<TK, TV> cache, int peekModes) : this(cache, true, peekModes)
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="cache">Target cache.</param>
+ /// <param name="loc">Local flag.</param>
+ /// <param name="peekModes">Peek modes.</param>
+ private CacheEnumerable(CacheImpl<TK, TV> cache, bool loc, int peekModes)
+ {
+ _cache = cache;
+ _loc = loc;
+ _peekModes = peekModes;
+ }
+
+ /** <inheritdoc /> */
+ public IEnumerator<ICacheEntry<TK, TV>> GetEnumerator()
+ {
+ return new CacheEnumeratorProxy<TK, TV>(_cache, _loc, _peekModes);
+ }
+
+ /** <inheritdoc /> */
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}