You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/09/04 18:28:00 UTC

[46/55] [abbrv] 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/Datastream/IDataStreamer.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/IDataStreamer.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/IDataStreamer.cs
new file mode 100644
index 0000000..2713040
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/IDataStreamer.cs
@@ -0,0 +1,206 @@
+/*
+ * 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.Datastream
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache.Store;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// Data streamer is responsible for loading external data into cache. It achieves it by
+    /// properly buffering updates and properly mapping keys to nodes responsible for the data
+    /// to make sure that there is the least amount of data movement possible and optimal
+    /// network and memory utilization.
+    /// <para />
+    /// Note that streamer will load data concurrently by multiple internal threads, so the
+    /// data may get to remote nodes in different order from which it was added to
+    /// the streamer.
+    /// <para />
+    /// Also note that <c>IDataStreamer</c> is not the only way to load data into cache.
+    /// Alternatively you can use 
+    /// <see cref="ICacheStore.LoadCache(Action{object, object}, object[])"/>
+    /// method to load data from underlying data store. You can also use standard cache
+    /// <c>put</c> and <c>putAll</c> operations as well, but they most likely will not perform 
+    /// as well as this class for loading data. And finally, data can be loaded from underlying 
+    /// data store on demand, whenever it is accessed - for this no explicit data loading step 
+    /// is needed.
+    /// <para />
+    /// <c>IDataStreamer</c> supports the following configuration properties:
+    /// <list type="bullet">
+    ///     <item>
+    ///         <term>PerNodeBufferSize</term>
+    ///         <description>When entries are added to data streamer they are not sent to Ignite 
+    ///         right away and are buffered internally for better performance and network utilization. 
+    ///         This setting controls the size of internal per-node buffer before buffered data is sent to 
+    ///         remote node. Default value is 1024.</description>
+    ///     </item>
+    ///     <item>
+    ///         <term>PerNodeParallelOperations</term>
+    ///         <description>Sometimes data may be added to the data streamer faster than it can be put 
+    ///         in cache. In this case, new buffered load messages are sent to remote nodes before 
+    ///         responses from previous ones are received. This could cause unlimited heap memory 
+    ///         utilization growth on local and remote nodes. To control memory utilization, this 
+    ///         setting limits maximum allowed number of parallel buffered load messages that are 
+    ///         being processed on remote nodes. If this number is exceeded, then data streamer add/remove
+    ///         methods will block to control memory utilization. Default value is 16.</description>
+    ///     </item>
+    ///     <item>
+    ///         <term>AutoFlushFrequency</term>
+    ///         <description>Automatic flush frequency in milliseconds. Essentially, this is the time 
+    ///         after which the streamer will make an attempt to submit all data added so far to remote 
+    ///         nodes. Note that there is no guarantee that data will be delivered after this concrete 
+    ///         attempt (e.g., it can fail when topology is changing), but it won't be lost anyway. 
+    ///         Disabled by default (default value is <c>0</c>).</description>
+    ///     </item>
+    ///     <item>
+    ///         <term>Isolated</term>
+    ///         <description>Defines if data streamer will assume that there are no other concurrent 
+    ///         updates and allow data streamer choose most optimal concurrent implementation. Default value 
+    ///         is <c>false</c>.</description>
+    ///     </item>
+    /// </list>
+    /// <para/>
+    /// All members are thread-safe and may be used concurrently from multiple threads.
+    /// </summary>
+    public interface IDataStreamer<TK, TV> : IDisposable
+    {
+        /// <summary>
+        /// Name of the cache to load data to.
+        /// </summary>
+        string CacheName { get; }
+
+        /// <summary>
+        /// Flag value indicating that this data streamer assumes that there could be concurrent updates to the cache. 
+        /// <para />
+        /// Default is <code>false</code>.
+        /// </summary>
+        bool AllowOverwrite { get; set; }
+
+        /// <summary>
+        /// Flag indicating that write-through behavior should be disabled for data loading.
+        /// <para />
+        /// Default is <code>false</code>.
+        /// </summary>
+        bool SkipStore { get; set; }
+
+        /// <summary>
+        /// Size of per node key-value pairs buffer.
+        /// <para />
+        /// Setter must be called before any add/remove operation.
+        /// <para />
+        /// Default is <code>1024</code>.
+        /// </summary>
+        int PerNodeBufferSize { get; set; }
+
+        /// <summary>
+        /// Maximum number of parallel load operations for a single node.
+        /// <para />
+        /// Setter must be called before any add/remove operation.
+        /// <para />
+        /// Default is <code>16</code>.
+        /// </summary>
+        int PerNodeParallelOperations { get; set; }
+
+        /// <summary>
+        /// Automatic flush frequency in milliseconds. Essentially, this is the time after which the
+        /// streamer will make an attempt to submit all data added so far to remote nodes.
+        /// Note that there is no guarantee that data will be delivered after this concrete
+        /// attempt (e.g., it can fail when topology is changing), but it won't be lost anyway.
+        /// <para />
+        /// If set to <code>0</code>, automatic flush is disabled.
+        /// <para />
+        /// Default is <code>0</code> (disabled).
+        /// </summary>
+        long AutoFlushFrequency { get; set; }
+
+        /// <summary>
+        /// Gets future for this loading process. This future completes whenever method
+        /// <see cref="IDataStreamer{K,V}.Close(bool)"/> completes.
+        /// </summary>
+        IFuture Future { get; }
+
+        /// <summary>
+        /// Gets or sets custom stream receiver.
+        /// </summary>
+        IStreamReceiver<TK, TV> Receiver { get; set; }
+
+        /// <summary>
+        /// Adds single key-value pair for loading. Passing <c>null</c> as value will be 
+        /// interpreted as removal.
+        /// </summary>
+        /// <param name="key">Key.</param>
+        /// <param name="val">Value.</param>
+        /// <returns>Future for this operation.</returns>
+        IFuture AddData(TK key, TV val);
+
+        /// <summary>
+        /// Adds single key-value pair for loading. Passing <c>null</c> as pair's value will 
+        /// be interpreted as removal.
+        /// </summary>
+        /// <param name="pair">Key-value pair.</param>
+        /// <returns>Future for this operation.</returns>
+        IFuture AddData(KeyValuePair<TK, TV> pair);
+
+        /// <summary>
+        /// Adds collection of key-value pairs for loading. 
+        /// </summary>
+        /// <param name="entries">Entries.</param>
+        /// <returns>Future for this operation.</returns>
+        IFuture AddData(ICollection<KeyValuePair<TK, TV>> entries);
+
+        /// <summary>
+        /// Adds key for removal.
+        /// </summary>
+        /// <param name="key">Key.</param>
+        /// <returns>Future for this operation.</returns>
+        IFuture RemoveData(TK key);
+
+        /// <summary>
+        /// Makes an attempt to load remaining data. This method is mostly similar to 
+        /// <see cref="IDataStreamer{K,V}.Flush()"/> with the difference that it won't wait and 
+        /// will exit immediately.
+        /// </summary>
+        void TryFlush();
+
+        /// <summary>
+        /// Loads any remaining data, but doesn't close the streamer. Data can be still added after
+        /// flush is finished. This method blocks and doesn't allow to add any data until all data
+        /// is loaded.
+        /// </summary>
+        void Flush();
+
+        /// <summary>
+        /// Closes this streamer optionally loading any remaining data.
+        /// </summary>
+        /// <param name="cancel">Whether to cancel ongoing loading operations. When set to <c>true</c>
+        /// there is not guarantees what data will be actually loaded to cache.</param>
+        void Close(bool cancel);
+
+        /// <summary>
+        /// Gets streamer instance with portable mode enabled, changing key and/or value types if necessary.
+        /// In portable mode stream receiver gets data in portable format.
+        /// You can only change key/value types when transitioning from non-portable to portable streamer;
+        /// Changing type of portable streamer is not allowed and will throw an <see cref="InvalidOperationException"/>
+        /// </summary>
+        /// <typeparam name="TK1">Key type in portable mode.</typeparam>
+        /// <typeparam name="TV1">Value type in protable mode.</typeparam>
+        /// <returns>Streamer instance with portable mode enabled.</returns>
+        IDataStreamer<TK1, TV1> WithKeepPortable<TK1, TV1>();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/IStreamReceiver.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/IStreamReceiver.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/IStreamReceiver.cs
new file mode 100644
index 0000000..d75dc54
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/IStreamReceiver.cs
@@ -0,0 +1,38 @@
+/*
+ * 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.Datastream
+{
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache;
+
+    /// <summary>
+    /// Updates cache with batch of entries. 
+    /// Usually it is enough to configure <see cref="IDataStreamer{K,V}.AllowOverwrite" /> property and appropriate 
+    /// internal cache receiver will be chosen automatically. But in some cases custom implementation may help 
+    /// to achieve better performance.
+    /// </summary>
+    public interface IStreamReceiver<TK, TV>
+    {
+        /// <summary>
+        /// Updates cache with batch of entries.
+        /// </summary>
+        /// <param name="cache">Cache.</param>
+        /// <param name="entries">Entries.</param>
+        void Receive(ICache<TK, TV> cache, ICollection<ICacheEntry<TK, TV>> entries);
+    }
+}
\ 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/Datastream/StreamTransformer.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/StreamTransformer.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/StreamTransformer.cs
new file mode 100644
index 0000000..0398342
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/StreamTransformer.cs
@@ -0,0 +1,73 @@
+/*
+ * 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.Datastream
+{
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Impl.Common;
+    using Apache.Ignite.Core.Impl.Datastream;
+    using Apache.Ignite.Core.Impl.Portable;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// Convenience adapter to transform update existing values in streaming cache 
+    /// based on the previously cached value.
+    /// </summary>
+    /// <typeparam name="TK">Key type.</typeparam>
+    /// <typeparam name="TV">Value type.</typeparam>
+    /// <typeparam name="TA">The type of the processor argument.</typeparam>
+    /// <typeparam name="TR">The type of the processor result.</typeparam>
+    public sealed class StreamTransformer<TK, TV, TA, TR> : IStreamReceiver<TK, TV>, 
+        IPortableWriteAware
+    {
+        /** Entry processor. */
+        private readonly ICacheEntryProcessor<TK, TV, TA, TR> _proc;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="StreamTransformer{K, V, A, R}"/> class.
+        /// </summary>
+        /// <param name="proc">Entry processor.</param>
+        public StreamTransformer(ICacheEntryProcessor<TK, TV, TA, TR> proc)
+        {
+            IgniteArgumentCheck.NotNull(proc, "proc");
+
+            _proc = proc;
+        }
+
+        /** <inheritdoc /> */
+        public void Receive(ICache<TK, TV> cache, ICollection<ICacheEntry<TK, TV>> entries)
+        {
+            var keys = new List<TK>(entries.Count);
+
+            foreach (var entry in entries)
+                keys.Add(entry.Key);
+
+            cache.InvokeAll(keys, _proc, default(TA));
+        }
+
+        /** <inheritdoc /> */
+        void IPortableWriteAware.WritePortable(IPortableWriter writer)
+        {
+            var w = (PortableWriterImpl)writer;
+
+            w.WriteByte(StreamReceiverHolder.RcvTransformer);
+
+            PortableUtils.WritePortableOrSerializable(w, _proc);
+        }
+    }
+}
\ 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/Datastream/StreamVisitor.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/StreamVisitor.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/StreamVisitor.cs
new file mode 100644
index 0000000..5d155d7
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Datastream/StreamVisitor.cs
@@ -0,0 +1,55 @@
+/*
+ * 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.Datastream
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Convenience adapter to visit every key-value tuple in the stream.
+    /// Note that the visitor does not update the cache.
+    /// </summary>
+    /// <typeparam name="TK">The type of the cache key.</typeparam>
+    /// <typeparam name="TV">The type of the cache value.</typeparam>
+    [Serializable]
+    public sealed class StreamVisitor<TK, TV> : IStreamReceiver<TK, TV>
+    {
+        /** Visitor action */
+        private readonly Action<ICache<TK, TV>, ICacheEntry<TK, TV>> _action;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="StreamVisitor{K, V}"/> class.
+        /// </summary>
+        /// <param name="action">The action to be called on each stream entry.</param>
+        public StreamVisitor(Action<ICache<TK, TV>, ICacheEntry<TK, TV>> action)
+        {
+            IgniteArgumentCheck.NotNull(action, "action");
+
+            _action = action;
+        }
+
+        /** <inheritdoc /> */
+        public void Receive(ICache<TK, TV> cache, ICollection<ICacheEntry<TK, TV>> entries)
+        {
+            foreach (var entry in entries)
+                _action(cache, entry);
+        }
+    }
+}
\ 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/Events/CacheEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheEvent.cs
new file mode 100644
index 0000000..ff5084b
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheEvent.cs
@@ -0,0 +1,176 @@
+/*
+ * 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>
+    /// In-memory database (cache) event.
+    /// </summary>
+    public sealed class CacheEvent : EventBase
+	{
+        /** */
+        private readonly string _cacheName;
+
+        /** */
+        private readonly int _partition;
+
+        /** */
+        private readonly bool _isNear;
+
+        /** */
+        private readonly IClusterNode _eventNode;
+
+        /** */
+        private readonly object _key;
+
+        /** */
+        private readonly IgniteGuid _xid;
+
+        /** */
+        private readonly object _lockId;
+
+        /** */
+        private readonly object _newValue;
+
+        /** */
+        private readonly object _oldValue;
+
+        /** */
+        private readonly bool _hasOldValue;
+
+        /** */
+        private readonly bool _hasNewValue;
+
+        /** */
+        private readonly Guid _subjectId;
+
+        /** */
+        private readonly string _closureClassName;
+
+        /** */
+        private readonly string _taskName;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="r">The reader to read data from.</param>
+        internal CacheEvent(IPortableRawReader r) : base(r)
+        {
+            _cacheName = r.ReadString();
+            _partition = r.ReadInt();
+            _isNear = r.ReadBoolean();
+            _eventNode = ReadNode(r);
+            _key = r.ReadObject<object>();
+            _xid = IgniteGuid.ReadPortable(r);
+            _lockId = r.ReadObject<object>();
+            _newValue = r.ReadObject<object>();
+            _oldValue = r.ReadObject<object>();
+            _hasOldValue = r.ReadBoolean();
+            _hasNewValue = r.ReadBoolean();
+            _subjectId = r.ReadGuid() ?? Guid.Empty;
+            _closureClassName = r.ReadString();
+            _taskName = r.ReadString();
+        }
+		
+        /// <summary>
+        /// Gets cache name. 
+        /// </summary>
+        public string CacheName { get { return _cacheName; } }
+
+        /// <summary>
+        /// Gets partition for the event which is the partition the key belongs to. 
+        /// </summary>
+        public int Partition { get { return _partition; } }
+
+        /// <summary>
+        /// Gets flag indicating whether event happened on near or partitioned cache. 
+        /// </summary>
+        public bool IsNear { get { return _isNear; } }
+
+        /// <summary>
+        /// Gets node which initiated cache operation or null if that node is not available. 
+        /// </summary>
+        public IClusterNode EventNode { get { return _eventNode; } }
+
+        /// <summary>
+        /// Gets cache entry associated with event. 
+        /// </summary>
+        public object Key { get { return _key; } }
+
+        /// <summary>
+        /// ID of surrounding cache cache transaction or null if there is no surrounding transaction. 
+        /// </summary>
+        public IgniteGuid Xid { get { return _xid; } }
+
+        /// <summary>
+        /// ID of the lock if held or null if no lock held. 
+        /// </summary>
+        public object LockId { get { return _lockId; } }
+
+        /// <summary>
+        /// Gets new value for this event. 
+        /// </summary>
+        public object NewValue { get { return _newValue; } }
+
+        /// <summary>
+        /// Gets old value associated with this event. 
+        /// </summary>
+        public object OldValue { get { return _oldValue; } }
+
+        /// <summary>
+        /// Gets flag indicating whether cache entry has old value in case if we only have old value in serialized form 
+        /// in which case <see cref="OldValue" /> will return null. 
+        /// </summary>
+        public bool HasOldValue { get { return _hasOldValue; } }
+
+        /// <summary>
+        /// Gets flag indicating whether cache entry has new value in case if we only have new value in serialized form 
+        /// in which case <see cref="NewValue" /> will return null. 
+        /// </summary>
+        public bool HasNewValue { get { return _hasNewValue; } }
+
+        /// <summary>
+        /// Gets security subject ID initiated this cache event, if available. This property is available only for <see 
+        /// cref="EventType.EvtCacheObjectPut" />, <see cref="EventType.EvtCacheObjectRemoved" /> and <see 
+        /// cref="EventType.EvtCacheObjectRead" /> cache events. Subject ID will be set either to nodeId initiated 
+        /// cache update or read or client ID initiated cache update or read. 
+        /// </summary>
+        public Guid SubjectId { get { return _subjectId; } }
+
+        /// <summary>
+        /// Gets closure class name (applicable only for TRANSFORM operations). 
+        /// </summary>
+        public string ClosureClassName { get { return _closureClassName; } }
+
+        /// <summary>
+        /// Gets task name if cache event was caused by an operation initiated within task execution. 
+        /// </summary>
+        public string TaskName { get { return _taskName; } }
+        
+        /** <inheritDoc /> */
+	    public override string ToShortString()
+	    {
+	        return string.Format("{0}: IsNear={1}, Key={2}, HasNewValue={3}, HasOldValue={4}, NodeId={5}", Name, 
+                _isNear, _key, HasNewValue, HasOldValue, Node.Id);
+	    }
+    }
+}
\ 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/Events/CacheQueryExecutedEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheQueryExecutedEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheQueryExecutedEvent.cs
new file mode 100644
index 0000000..8443c68
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheQueryExecutedEvent.cs
@@ -0,0 +1,97 @@
+/*
+ * 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.Portable;
+
+    /// <summary>
+    /// Cache query execution event.
+    /// </summary>
+    public sealed class CacheQueryExecutedEvent : EventBase
+	{
+        /** */
+        private readonly string _queryType;
+
+        /** */
+        private readonly string _cacheName;
+
+        /** */
+        private readonly string _className;
+
+        /** */
+        private readonly string _clause;
+
+        /** */
+        private readonly Guid _subjectId;
+
+        /** */
+        private readonly string _taskName;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="r">The reader to read data from.</param>
+        internal CacheQueryExecutedEvent(IPortableRawReader r) : base(r)
+        {
+            _queryType = r.ReadString();
+            _cacheName = r.ReadString();
+            _className = r.ReadString();
+            _clause = r.ReadString();
+            _subjectId = r.ReadGuid() ?? Guid.Empty;
+            _taskName = r.ReadString();
+        }
+		
+        /// <summary>
+        /// Gets query type. 
+        /// </summary>
+        public string QueryType { get { return _queryType; } }
+
+        /// <summary>
+        /// Gets cache name on which query was executed. 
+        /// </summary>
+        public string CacheName { get { return _cacheName; } }
+
+        /// <summary>
+        /// Gets queried class name. Applicable for SQL and full text queries. 
+        /// </summary>
+        public string ClassName { get { return _className; } }
+
+        /// <summary>
+        /// Gets query clause. Applicable for SQL, SQL fields and full text queries. 
+        /// </summary>
+        public string Clause { get { return _clause; } }
+
+        /// <summary>
+        /// Gets security subject ID. 
+        /// </summary>
+        public Guid SubjectId { get { return _subjectId; } }
+
+        /// <summary>
+        /// Gets the name of the task that executed the query (if any). 
+        /// </summary>
+        public string TaskName { get { return _taskName; } }
+
+        /** <inheritDoc /> */
+	    public override string ToShortString()
+	    {
+	        return string.Format("{0}: QueryType={1}, CacheName={2}, ClassName={3}, Clause={4}, SubjectId={5}, " +
+	                             "TaskName={6}", Name, QueryType, CacheName, ClassName, Clause, SubjectId, TaskName);
+	    }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheQueryReadEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheQueryReadEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheQueryReadEvent.cs
new file mode 100644
index 0000000..7338eab
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheQueryReadEvent.cs
@@ -0,0 +1,134 @@
+/*
+ * 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.Portable;
+
+    /// <summary>
+    /// Cache query read event.
+    /// </summary>
+    public sealed class CacheQueryReadEvent : EventBase
+	{
+        /** */
+        private readonly string _queryType;
+
+        /** */
+        private readonly string _cacheName;
+
+        /** */
+        private readonly string _className;
+
+        /** */
+        private readonly string _clause;
+
+        /** */
+        private readonly Guid _subjectId;
+
+        /** */
+        private readonly string _taskName;
+
+        /** */
+        private readonly object _key;
+
+        /** */
+        private readonly object _value;
+
+        /** */
+        private readonly object _oldValue;
+
+        /** */
+        private readonly object _row;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="r">The reader to read data from.</param>
+        internal CacheQueryReadEvent(IPortableRawReader r) : base(r)
+        {
+            _queryType = r.ReadString();
+            _cacheName = r.ReadString();
+            _className = r.ReadString();
+            _clause = r.ReadString();
+            _subjectId = r.ReadGuid() ?? Guid.Empty;
+            _taskName = r.ReadString();
+            _key = r.ReadObject<object>();
+            _value = r.ReadObject<object>();
+            _oldValue = r.ReadObject<object>();
+            _row = r.ReadObject<object>();
+        }
+		
+        /// <summary>
+        /// Gets query type. 
+        /// </summary>
+        public string QueryType { get { return _queryType; } }
+
+        /// <summary>
+        /// Gets cache name on which query was executed. 
+        /// </summary>
+        public string CacheName { get { return _cacheName; } }
+
+        /// <summary>
+        /// Gets queried class name. Applicable for SQL and full text queries. 
+        /// </summary>
+        public string ClassName { get { return _className; } }
+
+        /// <summary>
+        /// Gets query clause. Applicable for SQL, SQL fields and full text queries. 
+        /// </summary>
+        public string Clause { get { return _clause; } }
+
+        /// <summary>
+        /// Gets security subject ID. 
+        /// </summary>
+        public Guid SubjectId { get { return _subjectId; } }
+
+        /// <summary>
+        /// Gets the name of the task that executed the query (if any). 
+        /// </summary>
+        public string TaskName { get { return _taskName; } }
+
+        /// <summary>
+        /// Gets read entry key. 
+        /// </summary>
+        public object Key { get { return _key; } }
+
+        /// <summary>
+        /// Gets read entry value. 
+        /// </summary>
+        public object Value { get { return _value; } }
+
+        /// <summary>
+        /// Gets read entry old value (applicable for continuous queries). 
+        /// </summary>
+        public object OldValue { get { return _oldValue; } }
+
+        /// <summary>
+        /// Gets read results set row. 
+        /// </summary>
+        public object Row { get { return _row; } }
+
+        /** <inheritDoc /> */
+	    public override string ToShortString()
+	    {
+	        return string.Format("{0}: QueryType={1}, CacheName={2}, ClassName={3}, Clause={4}, SubjectId={5}, " +
+	                             "TaskName={6}, Key={7}, Value={8}, OldValue={9}, Row={10}", Name, QueryType, 
+                                 CacheName, ClassName, Clause, SubjectId, TaskName, Key, Value, OldValue, Row);
+	    }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheRebalancingEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheRebalancingEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheRebalancingEvent.cs
new file mode 100644
index 0000000..656550a
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CacheRebalancingEvent.cs
@@ -0,0 +1,98 @@
+/*
+ * 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.Cluster;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// In-memory database (cache) rebalancing event. Rebalance event happens every time there is a change
+    /// </summary>
+    public sealed class CacheRebalancingEvent : EventBase
+	{
+        /** */
+        private readonly string _cacheName;
+
+        /** */
+        private readonly int _partition;
+
+        /** */
+        private readonly IClusterNode _discoveryNode;
+
+        /** */
+        private readonly int _discoveryEventType;
+
+        /** */
+        private readonly string _discoveryEventName;
+
+        /** */
+        private readonly long _discoveryTimestamp;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="r">The reader to read data from.</param>
+        internal CacheRebalancingEvent(IPortableRawReader r) : base(r)
+        {
+            _cacheName = r.ReadString();
+            _partition = r.ReadInt();
+            _discoveryNode = ReadNode(r);
+            _discoveryEventType = r.ReadInt();
+            _discoveryEventName = r.ReadString();
+            _discoveryTimestamp = r.ReadLong();
+        }
+		
+        /// <summary>
+        /// Gets cache name. 
+        /// </summary>
+        public string CacheName { get { return _cacheName; } }
+
+        /// <summary>
+        /// Gets partition for the event. 
+        /// </summary>
+        public int Partition { get { return _partition; } }
+
+        /// <summary>
+        /// Gets shadow of the node that triggered this rebalancing event. 
+        /// </summary>
+        public IClusterNode DiscoveryNode { get { return _discoveryNode; } }
+
+        /// <summary>
+        /// Gets type of discovery event that triggered this rebalancing event. 
+        /// </summary>
+        public int DiscoveryEventType { get { return _discoveryEventType; } }
+
+        /// <summary>
+        /// Gets name of discovery event that triggered this rebalancing event. 
+        /// </summary>
+        public string DiscoveryEventName { get { return _discoveryEventName; } }
+
+        /// <summary>
+        /// Gets timestamp of discovery event that caused this rebalancing event. 
+        /// </summary>
+        public long DiscoveryTimestamp { get { return _discoveryTimestamp; } }
+
+        /** <inheritDoc /> */
+	    public override string ToShortString()
+	    {
+	        return string.Format("{0}: CacheName={1}, Partition={2}, DiscoveryNode={3}, DiscoveryEventType={4}, " +
+	                             "DiscoveryEventName={5}, DiscoveryTimestamp={6}", Name, CacheName, Partition,
+	                             DiscoveryNode, DiscoveryEventType, DiscoveryEventName, DiscoveryTimestamp);
+	    }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CheckpointEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CheckpointEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CheckpointEvent.cs
new file mode 100644
index 0000000..7b7ea59
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/CheckpointEvent.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 checkpoint event.
+    /// </summary>
+    public sealed class CheckpointEvent : EventBase
+	{
+        /** */
+        private readonly string _key;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="r">The reader to read data from.</param>
+        internal CheckpointEvent(IPortableRawReader r) : base(r)
+        {
+            _key = r.ReadString();
+        }
+		
+        /// <summary>
+        /// Gets checkpoint key associated with this event. 
+        /// </summary>
+        public string Key { get { return _key; } }
+
+        /** <inheritDoc /> */
+	    public override string ToShortString()
+	    {
+	        return string.Format("{0}: Key={1}", Name, Key);
+	    }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/DiscoveryEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/DiscoveryEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/DiscoveryEvent.cs
new file mode 100644
index 0000000..5b5443c
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/DiscoveryEvent.cs
@@ -0,0 +1,80 @@
+/*
+ * 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.Collections.Generic;
+    using System.Collections.ObjectModel;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Impl;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// Grid discovery event.
+    /// </summary>
+    public sealed class DiscoveryEvent : EventBase
+	{
+        /** */
+        private readonly IClusterNode _eventNode;
+
+        /** */
+        private readonly long _topologyVersion;
+
+        /** */
+        private readonly ReadOnlyCollection<IClusterNode> _topologyNodes;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="r">The reader to read data from.</param>
+        internal DiscoveryEvent(IPortableRawReader r) : base(r)
+        {
+            _eventNode = ReadNode(r);
+            _topologyVersion = r.ReadLong();
+
+            var nodes = IgniteUtils.ReadNodes(r);
+
+            _topologyNodes = nodes == null ? null : new ReadOnlyCollection<IClusterNode>(nodes);
+        }
+
+        /// <summary>
+        /// Gets node that caused this event to be generated. It is potentially different from the node on which this 
+        /// event was recorded. For example, node A locally recorded the event that a remote node B joined the topology. 
+        /// In this case this method will return ID of B. 
+        /// </summary>
+        public IClusterNode EventNode { get { return _eventNode; } }
+
+        /// <summary>
+        /// Gets topology version if this event is raised on topology change and configured discovery
+        /// SPI implementation supports topology versioning.
+        /// </summary>
+        public long TopologyVersion { get { return _topologyVersion; } }
+
+        /// <summary>
+        /// Gets topology nodes from topology snapshot. If SPI implementation does not support versioning, the best 
+        /// effort snapshot will be captured. 
+        /// </summary>
+        public ICollection<IClusterNode> TopologyNodes { get { return _topologyNodes; } }
+
+        /** <inheritDoc /> */
+	    public override string ToShortString()
+	    {
+	        return string.Format("{0}: EventNode={1}, TopologyVersion={2}, TopologyNodes={3}", Name, EventNode, 
+                TopologyVersion, TopologyNodes.Count);
+	    }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventBase.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventBase.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventBase.cs
new file mode 100644
index 0000000..2b905a1
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventBase.cs
@@ -0,0 +1,160 @@
+/*
+ * 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.Impl.Portable;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// Base event implementation.
+    /// </summary>
+    public abstract class EventBase : IEvent, IEquatable<EventBase>
+    {
+        /** */
+        private readonly IgniteGuid _id;
+
+        /** */
+        private readonly long _localOrder;
+
+        /** */
+        private readonly IClusterNode _node;
+
+        /** */
+        private readonly string _message;
+
+        /** */
+        private readonly int _type;
+
+        /** */
+        private readonly string _name;
+
+        /** */
+        private readonly DateTime _timeStamp;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="EventBase"/> class.
+        /// </summary>
+        /// <param name="r">The reader to read data from.</param>
+        protected EventBase(IPortableRawReader r)
+        {
+            _id = IgniteGuid.ReadPortable(r);
+
+            _localOrder = r.ReadLong();
+
+            _node = ReadNode(r);
+
+            _message = r.ReadString();
+            _type = r.ReadInt();
+            _name = r.ReadString();
+            _timeStamp = r.ReadDate() ?? DateTime.Now;
+        }
+
+        /** <inheritDoc /> */
+        public IgniteGuid Id
+        {
+            get { return _id; }
+        }
+
+        /** <inheritDoc /> */
+        public long LocalOrder
+        {
+            get { return _localOrder; }
+        }
+
+        /** <inheritDoc /> */
+        public IClusterNode Node
+        {
+            get { return _node; }
+        }
+
+        /** <inheritDoc /> */
+        public string Message
+        {
+            get { return _message; }
+        }
+
+        /** <inheritDoc /> */
+        public int Type
+        {
+            get { return _type; }
+        }
+
+        /** <inheritDoc /> */
+        public string Name
+        {
+            get { return _name; }
+        }
+
+        /** <inheritDoc /> */
+        public DateTime TimeStamp
+        {
+            get { return _timeStamp; }
+        }
+
+        /** <inheritDoc /> */
+        public virtual string ToShortString()
+        {
+            return ToString();
+        }
+
+        /** <inheritDoc /> */
+        public bool Equals(EventBase other)
+        {
+            if (ReferenceEquals(null, other)) return false;
+            if (ReferenceEquals(this, other)) return true;
+            
+            return _id.Equals(other._id);
+        }
+
+        /** <inheritDoc /> */
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            
+            return Equals((EventBase) obj);
+        }
+
+        /** <inheritDoc /> */
+        public override int GetHashCode()
+        {
+            return _id.GetHashCode();
+        }
+
+        /** <inheritDoc /> */
+        public override string ToString()
+        {
+            return string.Format("CacheEntry [Name={0}, Type={1}, TimeStamp={2}, Message={3}]", Name, Type, TimeStamp,
+                Message);
+        }
+
+        /// <summary>
+        /// Reads a node from stream.
+        /// </summary>
+        /// <param name="reader">Reader.</param>
+        /// <returns>Node or null.</returns>
+        protected static IClusterNode ReadNode(IPortableRawReader reader)
+        {
+            return ((PortableReaderImpl)reader).Marshaller.Ignite.GetNode(reader.ReadGuid());
+        }
+    }
+}
\ 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/Events/EventReader.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventReader.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventReader.cs
new file mode 100644
index 0000000..aa9f538
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventReader.cs
@@ -0,0 +1,72 @@
+/*
+ * 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.Portable;
+
+    /// <summary>
+    /// Event reader.
+    /// </summary>
+    internal static class EventReader
+    {
+        /// <summary>
+        /// Reads an event.
+        /// </summary>
+        /// <typeparam name="T">Type of the event</typeparam>
+        /// <param name="reader">Reader.</param>
+        /// <returns>Deserialized event.</returns>
+        /// <exception cref="System.InvalidCastException">Incompatible event type.</exception>
+        public static T Read<T>(IPortableReader reader) where T : IEvent
+        {
+            var r = reader.RawReader();
+
+            var clsId = r.ReadInt();
+
+            if (clsId == -1)
+                return default(T);
+
+            return (T) CreateInstance(clsId, r);
+        }
+
+        /// <summary>
+        /// Creates an event instance by type id.
+        /// </summary>
+        /// <param name="clsId">Type id.</param>
+        /// <param name="reader">Reader.</param>
+        /// <returns>Created and deserialized instance.</returns>
+        /// <exception cref="System.InvalidOperationException">Invalid event class id:  + clsId</exception>
+        private static IEvent CreateInstance(int clsId, IPortableRawReader reader)
+        {
+            switch (clsId)
+            {
+                case 2: return new CacheEvent(reader);
+                case 3: return new CacheQueryExecutedEvent(reader);
+                case 4: return new CacheQueryReadEvent(reader);
+                case 5: return new CacheRebalancingEvent(reader);
+                case 6: return new CheckpointEvent(reader);
+                case 7: return new DiscoveryEvent(reader);
+                case 8: return new JobEvent(reader);
+                case 9: return new SwapSpaceEvent(reader);
+                case 10: return new TaskEvent(reader);
+            }
+
+            throw new InvalidOperationException("Invalid event class id: " + clsId);
+        }
+    }
+}
\ 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/Events/EventType.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventType.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventType.cs
new file mode 100644
index 0000000..1e649bb
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/EventType.cs
@@ -0,0 +1,514 @@
+/*
+ * 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.Diagnostics.CodeAnalysis;
+    using System.Linq;
+    using System.Reflection;
+
+    /// <summary>
+    /// Contains event type constants. The decision to use class and not enumeration is dictated 
+    /// by allowing users to create their own events and/or event types which would be impossible with enumerations.
+    /// <para />
+    /// Note that this interface defines not only individual type constants, 
+    /// but arrays of types as well to be conveniently used with <see cref="IEvents"/> methods.
+    /// <para />
+    /// NOTE: all types in range <b>from 1 to 1000 are reserved</b> for internal Ignite events 
+    /// and should not be used by user-defined events.
+    /// </summary>
+    public static class EventType
+    {
+        /// <summary>
+        /// Built-in event type: checkpoint was saved.
+        /// </summary>
+        public static readonly int EvtCheckpointSaved = 1;
+
+        /// <summary>
+        /// Built-in event type: checkpoint was loaded.
+        /// </summary>
+        public static readonly int EvtCheckpointLoaded = 2;
+
+        /// <summary>
+        /// Built-in event type: checkpoint was removed. Reasons are: timeout expired, or or it was manually removed, 
+        /// or it was automatically removed by the task session.
+        /// </summary>
+        public static readonly int EvtCheckpointRemoved = 3;
+
+        /// <summary>
+        /// Built-in event type: node joined topology. New node has been discovered and joined grid topology. Note that 
+        /// even though a node has been discovered there could be a number of warnings in the log. In certain 
+        /// situations Ignite doesn't prevent a node from joining but prints warning messages into the log.
+        /// </summary>
+        public static readonly int EvtNodeJoined = 10;
+
+        /// <summary>
+        /// Built-in event type: node has normally left topology.
+        /// </summary>
+        public static readonly int EvtNodeLeft = 11;
+
+        /// <summary>
+        /// Built-in event type: node failed. Ignite detected that node has presumably crashed and is considered 
+        /// failed.
+        /// </summary>
+        public static readonly int EvtNodeFailed = 12;
+
+        /// <summary>
+        /// Built-in event type: node metrics updated. Generated when node's metrics are updated. In most cases this 
+        /// callback is invoked with every heartbeat received from a node (including local node).
+        /// </summary>
+        public static readonly int EvtNodeMetricsUpdated = 13;
+
+        /// <summary>
+        /// Built-in event type: local node segmented. Generated when node determines that it runs in invalid network 
+        /// segment.
+        /// </summary>
+        public static readonly int EvtNodeSegmented = 14;
+
+        /// <summary>
+        /// Built-in event type: client node disconnected.
+        /// </summary>
+        public static readonly int EvtClientNodeDisconnected = 16;
+
+        /// <summary>
+        /// Built-in event type: client node reconnected.
+        /// </summary>
+        public static readonly int EvtClientNodeReconnected = 17;
+
+        /// <summary>
+        /// Built-in event type: task started.
+        /// </summary>
+        public static readonly int EvtTaskStarted = 20;
+
+        /// <summary>
+        /// Built-in event type: task finished. Task got finished. This event is triggered every time a task finished 
+        /// without exception.
+        /// </summary>
+        public static readonly int EvtTaskFinished = 21;
+
+        /// <summary>
+        /// Built-in event type: task failed. Task failed. This event is triggered every time a task finished with an 
+        /// exception. Note that prior to this event, there could be other events recorded specific to the failure.
+        /// </summary>
+        public static readonly int EvtTaskFailed = 22;
+
+        /// <summary>
+        /// Built-in event type: task timed out.
+        /// </summary>
+        public static readonly int EvtTaskTimedout = 23;
+
+        /// <summary>
+        /// Built-in event type: task session attribute set.
+        /// </summary>
+        public static readonly int EvtTaskSessionAttrSet = 24;
+
+        /// <summary>
+        /// Built-in event type: task reduced.
+        /// </summary>
+        public static readonly int EvtTaskReduced = 25;
+
+        /// <summary>
+        /// Built-in event type: Ignite job was mapped in {@link org.apache.ignite.compute.ComputeTask#map(List, Object)} 
+        /// method.
+        /// </summary>
+        public static readonly int EvtJobMapped = 40;
+
+        /// <summary>
+        /// Built-in event type: Ignite job result was received by {@link 
+        /// org.apache.ignite.compute.ComputeTask#result(org.apache.ignite.compute.ComputeJobResult, List)} method.
+        /// </summary>
+        public static readonly int EvtJobResulted = 41;
+
+        /// <summary>
+        /// Built-in event type: Ignite job failed over.
+        /// </summary>
+        public static readonly int EvtJobFailedOver = 43;
+
+        /// <summary>
+        /// Built-in event type: Ignite job started.
+        /// </summary>
+        public static readonly int EvtJobStarted = 44;
+
+        /// <summary>
+        /// Built-in event type: Ignite job finished. Job has successfully completed and produced a result which from the 
+        /// user perspective can still be either negative or positive.
+        /// </summary>
+        public static readonly int EvtJobFinished = 45;
+
+        /// <summary>
+        /// Built-in event type: Ignite job timed out.
+        /// </summary>
+        public static readonly int EvtJobTimedout = 46;
+
+        /// <summary>
+        /// Built-in event type: Ignite job rejected during collision resolution.
+        /// </summary>
+        public static readonly int EvtJobRejected = 47;
+
+        /// <summary>
+        /// Built-in event type: Ignite job failed. Job has failed. This means that there was some error event during job 
+        /// execution and job did not produce a result.
+        /// </summary>
+        public static readonly int EvtJobFailed = 48;
+
+        /// <summary>
+        /// Built-in event type: Ignite job queued. Job arrived for execution and has been queued (added to passive queue 
+        /// during collision resolution).
+        /// </summary>
+        public static readonly int EvtJobQueued = 49;
+
+        /// <summary>
+        /// Built-in event type: Ignite job cancelled.
+        /// </summary>
+        public static readonly int EvtJobCancelled = 50;
+
+        /// <summary>
+        /// Built-in event type: entry created.
+        /// </summary>
+        public static readonly int EvtCacheEntryCreated = 60;
+
+        /// <summary>
+        /// Built-in event type: entry destroyed.
+        /// </summary>
+        public static readonly int EvtCacheEntryDestroyed = 61;
+
+        /// <summary>
+        /// Built-in event type: entry evicted.
+        /// </summary>
+        public static readonly int EvtCacheEntryEvicted = 62;
+
+        /// <summary>
+        /// Built-in event type: object put.
+        /// </summary>
+        public static readonly int EvtCacheObjectPut = 63;
+
+        /// <summary>
+        /// Built-in event type: object read.
+        /// </summary>
+        public static readonly int EvtCacheObjectRead = 64;
+
+        /// <summary>
+        /// Built-in event type: object removed.
+        /// </summary>
+        public static readonly int EvtCacheObjectRemoved = 65;
+
+        /// <summary>
+        /// Built-in event type: object locked.
+        /// </summary>
+        public static readonly int EvtCacheObjectLocked = 66;
+
+        /// <summary>
+        /// Built-in event type: object unlocked.
+        /// </summary>
+        public static readonly int EvtCacheObjectUnlocked = 67;
+
+        /// <summary>
+        /// Built-in event type: cache object swapped from swap storage.
+        /// </summary>
+        public static readonly int EvtCacheObjectSwapped = 68;
+
+        /// <summary>
+        /// Built-in event type: cache object unswapped from swap storage.
+        /// </summary>
+        public static readonly int EvtCacheObjectUnswapped = 69;
+
+        /// <summary>
+        /// Built-in event type: cache object was expired when reading it.
+        /// </summary>
+        public static readonly int EvtCacheObjectExpired = 70;
+
+        /// <summary>
+        /// Built-in event type: swap space data read.
+        /// </summary>
+        public static readonly int EvtSwapSpaceDataRead = 71;
+
+        /// <summary>
+        /// Built-in event type: swap space data stored.
+        /// </summary>
+        public static readonly int EvtSwapSpaceDataStored = 72;
+
+        /// <summary>
+        /// Built-in event type: swap space data removed.
+        /// </summary>
+        public static readonly int EvtSwapSpaceDataRemoved = 73;
+
+        /// <summary>
+        /// Built-in event type: swap space cleared.
+        /// </summary>
+        public static readonly int EvtSwapSpaceCleared = 74;
+
+        /// <summary>
+        /// Built-in event type: swap space data evicted.
+        /// </summary>
+        public static readonly int EvtSwapSpaceDataEvicted = 75;
+
+        /// <summary>
+        /// Built-in event type: cache object stored in off-heap storage.
+        /// </summary>
+        public static readonly int EvtCacheObjectToOffheap = 76;
+
+        /// <summary>
+        /// Built-in event type: cache object moved from off-heap storage back into memory.
+        /// </summary>
+        public static readonly int EvtCacheObjectFromOffheap = 77;
+
+        /// <summary>
+        /// Built-in event type: cache rebalance started.
+        /// </summary>
+        public static readonly int EvtCacheRebalanceStarted = 80;
+
+        /// <summary>
+        /// Built-in event type: cache rebalance stopped.
+        /// </summary>
+        public static readonly int EvtCacheRebalanceStopped = 81;
+
+        /// <summary>
+        /// Built-in event type: cache partition loaded.
+        /// </summary>
+        public static readonly int EvtCacheRebalancePartLoaded = 82;
+
+        /// <summary>
+        /// Built-in event type: cache partition unloaded.
+        /// </summary>
+        public static readonly int EvtCacheRebalancePartUnloaded = 83;
+
+        /// <summary>
+        /// Built-in event type: cache entry rebalanced.
+        /// </summary>
+        public static readonly int EvtCacheRebalanceObjectLoaded = 84;
+
+        /// <summary>
+        /// Built-in event type: cache entry unloaded.
+        /// </summary>
+        public static readonly int EvtCacheRebalanceObjectUnloaded = 85;
+
+        /// <summary>
+        /// Built-in event type: all nodes that hold partition left topology.
+        /// </summary>
+        public static readonly int EvtCacheRebalancePartDataLost = 86;
+
+        /// <summary>
+        /// Built-in event type: query executed.
+        /// </summary>
+        public static readonly int EvtCacheQueryExecuted = 96;
+
+        /// <summary>
+        /// Built-in event type: query entry read.
+        /// </summary>
+        public static readonly int EvtCacheQueryObjectRead = 97;
+
+        /// <summary>
+        /// Built-in event type: cache started.
+        /// </summary>
+        public static readonly int EvtCacheStarted = 98;
+
+        /// <summary>
+        /// Built-in event type: cache started.
+        /// </summary>
+        public static readonly int EvtCacheStopped = 99;
+
+        /// <summary>
+        /// Built-in event type: cache nodes left.
+        /// </summary>
+        public static readonly int EvtCacheNodesLeft = 100;
+
+        /// <summary>
+        /// All events indicating an error or failure condition. It is convenient to use when fetching all events 
+        /// indicating error or failure.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsError =
+        {
+            EvtJobTimedout,
+            EvtJobFailed,
+            EvtJobFailedOver,
+            EvtJobRejected,
+            EvtJobCancelled,
+            EvtTaskTimedout,
+            EvtTaskFailed,
+            EvtCacheRebalanceStarted,
+            EvtCacheRebalanceStopped
+        };
+
+        /// <summary>
+        /// All discovery events except for <see cref="EvtNodeMetricsUpdated" />. Subscription to <see 
+        /// cref="EvtNodeMetricsUpdated" /> can generate massive amount of event processing in most cases is not 
+        /// necessary. If this event is indeed required you can subscribe to it individually or use <see 
+        /// cref="EvtsDiscoveryAll" /> array.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsDiscovery =
+        {
+            EvtNodeJoined,
+            EvtNodeLeft,
+            EvtNodeFailed,
+            EvtNodeSegmented,
+            EvtClientNodeDisconnected,
+            EvtClientNodeReconnected
+        };
+
+        /// <summary>
+        /// All discovery events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsDiscoveryAll =
+        {
+            EvtNodeJoined,
+            EvtNodeLeft,
+            EvtNodeFailed,
+            EvtNodeSegmented,
+            EvtNodeMetricsUpdated,
+            EvtClientNodeDisconnected,
+            EvtClientNodeReconnected
+        };
+
+        /// <summary>
+        /// All Ignite job execution events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsJobExecution =
+        {
+            EvtJobMapped,
+            EvtJobResulted,
+            EvtJobFailedOver,
+            EvtJobStarted,
+            EvtJobFinished,
+            EvtJobTimedout,
+            EvtJobRejected,
+            EvtJobFailed,
+            EvtJobQueued,
+            EvtJobCancelled
+        };
+
+        /// <summary>
+        /// All Ignite task execution events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsTaskExecution =
+        {
+            EvtTaskStarted,
+            EvtTaskFinished,
+            EvtTaskFailed,
+            EvtTaskTimedout,
+            EvtTaskSessionAttrSet,
+            EvtTaskReduced
+        };
+
+        /// <summary>
+        /// All cache events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsCache =
+        {
+            EvtCacheEntryCreated,
+            EvtCacheEntryDestroyed,
+            EvtCacheObjectPut,
+            EvtCacheObjectRead,
+            EvtCacheObjectRemoved,
+            EvtCacheObjectLocked,
+            EvtCacheObjectUnlocked,
+            EvtCacheObjectSwapped,
+            EvtCacheObjectUnswapped,
+            EvtCacheObjectExpired
+        };
+
+        /// <summary>
+        /// All cache rebalance events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsCacheRebalance =
+        {
+            EvtCacheRebalanceStarted,
+            EvtCacheRebalanceStopped,
+            EvtCacheRebalancePartLoaded,
+            EvtCacheRebalancePartUnloaded,
+            EvtCacheRebalanceObjectLoaded,
+            EvtCacheRebalanceObjectUnloaded,
+            EvtCacheRebalancePartDataLost
+        };
+
+        /// <summary>
+        /// All cache lifecycle events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsCacheLifecycle =
+        {
+            EvtCacheStarted,
+            EvtCacheStopped,
+            EvtCacheNodesLeft
+        };
+
+        /// <summary>
+        /// All cache query events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsCacheQuery =
+        {
+            EvtCacheQueryExecuted,
+            EvtCacheQueryObjectRead
+        };
+
+        /// <summary>
+        /// All swap space events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsSwapspace =
+        {
+            EvtSwapSpaceCleared,
+            EvtSwapSpaceDataRemoved,
+            EvtSwapSpaceDataRead,
+            EvtSwapSpaceDataStored,
+            EvtSwapSpaceDataEvicted
+        };
+
+        /// <summary>
+        /// All Ignite events.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsAll = GetAllEvents();
+
+        /// <summary>
+        /// All Ignite events (<b>excluding</b> metric update event).
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly",
+            Justification = "Breaking change. Should be fixed in the next non-compatible release.")]
+        public static readonly int[] EvtsAllMinusMetricUpdate =
+            EvtsAll.Where(x => x != EvtNodeMetricsUpdated).ToArray();
+
+        /// <summary>
+        /// Gets all the events.
+        /// </summary>
+        /// <returns>All event ids.</returns>
+        private static int[] GetAllEvents()
+        {
+            return typeof (EventType).GetFields(BindingFlags.Public | BindingFlags.Static)
+                .Where(x => x.FieldType == typeof (int))
+                .Select(x => (int) x.GetValue(null)).ToArray();
+        }
+    }
+}
\ 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/Events/IEvent.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEvent.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEvent.cs
new file mode 100644
index 0000000..181aeef
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEvent.cs
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+    /// <summary>
+    /// Represents a Ignite event.
+    /// </summary>
+    public interface IEvent
+    {
+        /// <summary>
+        /// Gets globally unique ID of this event.
+        /// </summary>
+        IgniteGuid Id { get; }
+
+        /// <summary>
+        /// Gets locally unique ID that is atomically incremented for each event. Unlike global <see cref="Id" />
+        /// this local ID can be used for ordering events on this node. 
+        /// <para/> 
+        /// Note that for performance considerations Ignite doesn't order events globally.
+        /// </summary>
+        long LocalOrder { get; }
+
+        /// <summary>
+        /// Node where event occurred and was recorded.
+        /// </summary>
+        IClusterNode Node { get; }
+
+        /// <summary>
+        /// Gets optional message for this event.
+        /// </summary>
+        string Message { get; }
+
+        /// <summary>
+        /// Gets type of this event. All system event types are defined in <see cref="EventType"/>
+        /// </summary>
+        int Type { get; }
+
+        /// <summary>
+        /// Gets name of this event.
+        /// </summary>
+        string Name { get; }
+
+        /// <summary>
+        /// Gets event timestamp. Timestamp is local to the node on which this event was produced. 
+        /// Note that more than one event can be generated with the same timestamp. 
+        /// For ordering purposes use <see cref="LocalOrder"/> instead.
+        /// </summary>
+        DateTime TimeStamp { get; }
+
+        /// <summary>
+        /// Gets shortened version of ToString result.
+        /// </summary>
+        string ToShortString();
+    }
+}
\ 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/Events/IEventFilter.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEventFilter.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEventFilter.cs
new file mode 100644
index 0000000..7523c52
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEventFilter.cs
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+    /// <summary>
+    /// Represents an event filter.
+    /// </summary>
+    /// <typeparam name="T">Event type.</typeparam>
+    public interface IEventFilter<in T> where T : IEvent
+    {
+        /// <summary>
+        /// Determines whether specified event passes this filtger.
+        /// </summary>
+        /// <param name="nodeId">Node identifier.</param>
+        /// <param name="evt">Event.</param>
+        /// <returns>Value indicating whether specified event passes this filtger.</returns>
+        bool Invoke(Guid nodeId, T evt);
+    }
+}
\ 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/Events/IEvents.cs
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEvents.cs b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEvents.cs
new file mode 100644
index 0000000..e13513c
--- /dev/null
+++ b/modules/platform/src/main/dotnet/Apache.Ignite.Core/Events/IEvents.cs
@@ -0,0 +1,182 @@
+/*
+ * 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 System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// Provides functionality for local and remote event notifications on nodes defined by <see cref="ClusterGroup"/>.
+    /// <para/>
+    /// All members are thread-safe and may be used concurrently from multiple threads.
+    /// </summary>
+    public interface IEvents : IAsyncSupport<IEvents>
+    {
+        /// <summary>
+        /// Gets the cluster group to which this instance belongs.
+        /// </summary>
+        IClusterGroup ClusterGroup { get; }
+
+        /// <summary>
+        /// Queries nodes in this cluster group for events using passed in predicate filter for event selection.
+        /// </summary>
+        /// <typeparam name="T">Type of events.</typeparam>
+        /// <param name="filter">Predicate filter used to query events on remote nodes.</param>
+        /// <param name="timeout">Maximum time to wait for result, null or 0 to wait forever.</param>
+        /// <param name="types">Event types to be queried.</param>
+        /// <returns>Collection of Ignite events returned from specified nodes.</returns>
+        [AsyncSupported]
+        [SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
+        List<T> RemoteQuery<T>(IEventFilter<T> filter, TimeSpan? timeout = null, params int[] types) 
+            where T : IEvent;
+
+        /// <summary>
+        /// Adds event listener for specified events to all nodes in the cluster group (possibly including local node 
+        /// if it belongs to the cluster group as well). This means that all events occurring on any node within this 
+        /// cluster group that pass remote filter will be sent to local node for local listener notifications.
+        /// <para/>
+        /// The listener can be unsubscribed automatically if local node stops, if localListener callback 
+        /// returns false or if <see cref="StopRemoteListen"/> is called.
+        /// </summary>
+        /// <typeparam name="T">Type of events.</typeparam>
+        /// <param name="bufSize">Remote events buffer size. Events from remote nodes won't be sent until buffer
+        /// is full or time interval is exceeded.</param>
+        /// <param name="interval">Maximum time interval after which events from remote node will be sent. Events
+        /// from remote nodes won't be sent until buffer is full or time interval is exceeded.</param>
+        /// <param name="autoUnsubscribe">Flag indicating that event listeners on remote nodes should be automatically 
+        /// unregistered if master node (node that initiated event listening) leaves topology. 
+        /// If this flag is false, listeners will be unregistered only when <see cref="StopRemoteListen"/>
+        /// method is called, or the localListener returns false.</param>
+        /// <param name="localListener"> Listener callback that is called on local node. If null, these events will 
+        /// be handled on remote nodes by passed in remoteFilter.</param>
+        /// <param name="remoteFilter">
+        /// Filter callback that is called on remote node. Only events that pass the remote filter will be 
+        /// sent to local node. If null, all events of specified types will be sent to local node. 
+        /// This remote filter can be used to pre-handle events remotely, before they are passed in to local callback.
+        /// It will be auto-unsubscribed on the node where event occurred in case if it returns false.
+        /// </param>
+        /// <param name="types">
+        /// Types of events to listen for. If not provided, all events that pass the provided remote filter 
+        /// will be sent to local node.
+        /// </param>
+        /// <returns>
+        /// Operation ID that can be passed to <see cref="StopRemoteListen"/> method to stop listening.
+        /// </returns>
+        [AsyncSupported]
+        Guid RemoteListen<T>(int bufSize = 1, TimeSpan? interval = null, bool autoUnsubscribe = true,
+            IEventFilter<T> localListener = null, IEventFilter<T> remoteFilter = null, params int[] types) 
+            where T : IEvent;
+
+        /// <summary>
+        /// Stops listening to remote events. This will unregister all listeners identified with provided operation ID 
+        /// on all nodes defined by <see cref="ClusterGroup"/>.
+        /// </summary>
+        /// <param name="opId">Operation ID that was returned from <see cref="RemoteListen{T}"/>.</param>
+        [AsyncSupported]
+        void StopRemoteListen(Guid opId);
+
+        /// <summary>
+        /// Waits for the specified events.
+        /// </summary>
+        /// <param name="types">Types of the events to wait for. 
+        /// If not provided, all events will be passed to the filter.</param>
+        /// <returns>Ignite event.</returns>
+        [AsyncSupported]
+        IEvent WaitForLocal(params int[] types);
+
+        /// <summary>
+        /// Waits for the specified events.
+        /// </summary>
+        /// <typeparam name="T">Type of events.</typeparam>
+        /// <param name="filter">Optional filtering predicate. Event wait will end as soon as it returns false.</param>
+        /// <param name="types">Types of the events to wait for. 
+        /// If not provided, all events will be passed to the filter.</param>
+        /// <returns>Ignite event.</returns>
+        [AsyncSupported]
+        T WaitForLocal<T>(IEventFilter<T> filter, params int[] types) where T : IEvent;
+
+        /// <summary>
+        /// Queries local node for events using of specified types.
+        /// </summary>
+        /// <param name="types">Event types to be queried. Optional.</param>
+        /// <returns>Collection of Ignite events found on local node.</returns>
+        [SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
+        List<IEvent> LocalQuery(params int[] types);
+
+        /// <summary>
+        /// Records customer user generated event. All registered local listeners will be notified.
+        /// <para/>
+        /// NOTE: all types in range <b>from 1 to 1000 are reserved</b> for
+        /// internal Ignite events and should not be used by user-defined events.
+        /// Attempt to record internal event with this method will cause <see cref="ArgumentException"/> to be thrown.
+        /// </summary>
+        /// <param name="evt">Locally generated event.</param>
+        /// <exception cref="ArgumentException">If event type is within Ignite reserved range (1 � 1000)</exception>
+        void RecordLocal(IEvent evt);
+
+        /// <summary>
+        /// Adds an event listener for local events. Note that listener will be added regardless of whether 
+        /// local node is in this cluster group or not.
+        /// </summary>
+        /// <typeparam name="T">Type of events.</typeparam>
+        /// <param name="listener">Predicate that is called on each received event. If predicate returns false,
+        /// it will be unregistered and will stop receiving events.</param>
+        /// <param name="types">Event types for which this listener will be notified, should not be empty.</param>
+        void LocalListen<T>(IEventFilter<T> listener, params int[] types) where T : IEvent;
+
+        /// <summary>
+        /// Removes local event listener.
+        /// </summary>
+        /// <typeparam name="T">Type of events.</typeparam>
+        /// <param name="listener">Local event listener to remove.</param>
+        /// <param name="types">Types of events for which to remove listener. If not specified, then listener
+        /// will be removed for all types it was registered for.</param>
+        /// <returns>True if listener was removed, false otherwise.</returns>
+        bool StopLocalListen<T>(IEventFilter<T> listener, params int[] types) where T : IEvent;
+
+        /// <summary>
+        /// Enables provided events. Allows to start recording events that were disabled before. 
+        /// Note that provided events will be enabled regardless of whether local node is in this cluster group or not.
+        /// </summary>
+        /// <param name="types">Events to enable.</param>
+        void EnableLocal(params int[] types);
+
+        /// <summary>
+        /// Disables provided events. Allows to stop recording events that were enabled before. Note that specified 
+        /// events will be disabled regardless of whether local node is in this cluster group or not.
+        /// </summary>
+        /// <param name="types">Events to disable.</param>
+        void DisableLocal(params int[] types);
+
+        /// <summary>
+        /// Gets types of enabled events.
+        /// </summary>
+        /// <returns>Types of enabled events.</returns>
+        int[] GetEnabledEvents();
+
+        /// <summary>
+        /// Determines whether the specified event is enabled.
+        /// </summary>
+        /// <param name="type">Event type.</param>
+        /// <returns>Value indicating whether the specified event is enabled.</returns>
+        bool IsEnabled(int type);
+    }
+}
\ No newline at end of file