IGNITE-7301 .NET: Baseline topology

This closes #3352


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e21e2756
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e21e2756
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e21e2756

Branch: refs/heads/ignite-2.4
Commit: e21e2756b005fe3232b343ea5e81c1f1a6a1bd06
Parents: 107ea87
Author: Pavel Tupitsyn <[email protected]>
Authored: Wed Jan 17 15:38:20 2018 +0300
Committer: Pavel Tupitsyn <[email protected]>
Committed: Wed Jan 17 15:38:20 2018 +0300

----------------------------------------------------------------------
 .../platform/PlatformContextImpl.java           |  20 +--
 .../platform/PlatformProcessorImpl.java         |  46 +++++++
 .../platform/cluster/PlatformClusterGroup.java  |  13 +-
 .../platform/utils/PlatformUtils.java           |  41 ++++++
 .../Common/TestUtils.DotNetCore.cs              |   3 +-
 .../Apache.Ignite.Core.Tests.csproj             |   1 +
 .../ApiParity/ClusterNodeParityTest.cs          |  45 +++++++
 .../ApiParity/ClusterParityTest.cs              |   6 +-
 .../ApiParity/ParityTest.cs                     |  26 +++-
 .../Cache/DataStorageMetricsTest.cs             |   6 +-
 .../Cache/PersistenceTest.cs                    | 126 +++++++++++++++----
 .../Compute/ComputeApiTest.cs                   |  10 +-
 .../IgniteConfigurationTest.cs                  |   1 +
 .../TestUtils.Common.cs                         |  40 ++++++
 .../TestUtils.Windows.cs                        |   3 +-
 .../Apache.Ignite.Core.csproj                   |   3 +
 .../Apache.Ignite.Core/Cluster/IBaselineNode.cs |  37 ++++++
 .../Apache.Ignite.Core/Cluster/ICluster.cs      |  34 ++++-
 .../Apache.Ignite.Core/Cluster/IClusterNode.cs  |   3 +-
 .../dotnet/Apache.Ignite.Core/IIgnite.cs        |   2 +
 .../Apache.Ignite.Core/IgniteConfiguration.cs   |   4 +-
 .../Impl/Binary/BinarySystemHandlers.cs         |  16 +++
 .../Impl/Binary/BinaryTypeId.cs                 |   3 +
 .../Impl/Binary/OptimizedMarshallerObject.cs    |  54 ++++++++
 .../Impl/Cluster/BaselineNode.cs                |  89 +++++++++++++
 .../Impl/Cluster/ClusterNodeImpl.cs             |  38 +++++-
 .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs    |  39 +++++-
 .../Impl/Unmanaged/Jni/Env.cs                   |   2 -
 28 files changed, 643 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
index b141313..9e22f38 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
@@ -72,10 +72,7 @@ import org.jetbrains.annotations.Nullable;
 import java.sql.Timestamp;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
@@ -205,27 +202,14 @@ public class PlatformContextImpl implements 
PlatformContext {
             BinaryRawWriterEx w = writer(out);
 
             w.writeUuid(node.id());
-
-            Map<String, Object> attrs = new HashMap<>(node.attributes());
-
-            Iterator<Map.Entry<String, Object>> attrIter = 
attrs.entrySet().iterator();
-
-            while (attrIter.hasNext()) {
-                Map.Entry<String, Object> entry = attrIter.next();
-
-                Object val = entry.getValue();
-
-                if (val != null && 
!val.getClass().getName().startsWith("java.lang"))
-                    attrIter.remove();
-            }
-
-            w.writeMap(attrs);
+            PlatformUtils.writeNodeAttributes(w, node.attributes());
             w.writeCollection(node.addresses());
             w.writeCollection(node.hostNames());
             w.writeLong(node.order());
             w.writeBoolean(node.isLocal());
             w.writeBoolean(node.isDaemon());
             w.writeBoolean(node.isClient());
+            w.writeObjectDetached(node.consistentId());
             writeClusterMetrics(w, node.metrics());
 
             out.synchronize();

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
index 0d88fbb..de51b3d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformProcessorImpl.java
@@ -23,6 +23,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cluster.BaselineNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.configuration.PlatformConfiguration;
@@ -30,6 +31,7 @@ import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.binary.BinaryRawReaderEx;
 import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.cluster.DetachedClusterNode;
 import org.apache.ignite.internal.logger.platform.PlatformLogger;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
@@ -57,6 +59,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteFuture;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -140,6 +143,15 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
     /** */
     private static final int OP_ADD_CACHE_CONFIGURATION = 23;
 
+    /** */
+    private static final int OP_SET_BASELINE_TOPOLOGY_VER = 24;
+
+    /** */
+    private static final int OP_SET_BASELINE_TOPOLOGY_NODES = 25;
+
+    /** */
+    private static final int OP_GET_BASELINE_TOPOLOGY = 26;
+
     /** Start latch. */
     private final CountDownLatch startLatch = new CountDownLatch(1);
 
@@ -408,6 +420,12 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
 
                 return 0;
             }
+
+            case OP_SET_BASELINE_TOPOLOGY_VER: {
+                ctx.grid().cluster().setBaselineTopology(val);
+
+                return 0;
+            }
         }
 
         return PlatformAbstractTarget.throwUnsupported(type);
@@ -428,6 +446,22 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
                 return 0;
             }
 
+            case OP_SET_BASELINE_TOPOLOGY_NODES: {
+                int cnt = reader.readInt();
+                Collection<BaselineNode> nodes = new ArrayList<>(cnt);
+
+                for (int i = 0; i < cnt; i++) {
+                    Object consId = reader.readObjectDetached();
+                    Map<String, Object> attrs = 
PlatformUtils.readNodeAttributes(reader);
+
+                    nodes.add(new DetachedClusterNode(consId, attrs));
+                }
+
+                ctx.grid().cluster().setBaselineTopology(nodes);
+
+                return 0;
+            }
+
             case OP_ADD_CACHE_CONFIGURATION:
                 CacheConfiguration cfg = 
PlatformConfigurationUtils.readCacheConfiguration(reader);
 
@@ -614,6 +648,18 @@ public class PlatformProcessorImpl extends 
GridProcessorAdapter implements Platf
 
                 return;
             }
+
+            case OP_GET_BASELINE_TOPOLOGY: {
+                Collection<BaselineNode> blt = 
ignite().cluster().currentBaselineTopology();
+                writer.writeInt(blt.size());
+
+                for (BaselineNode n : blt) {
+                    writer.writeObjectDetached(n.consistentId());
+                    PlatformUtils.writeNodeAttributes(writer, n.attributes());
+                }
+
+                return;
+            }
         }
 
         PlatformAbstractTarget.throwUnsupported(type);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cluster/PlatformClusterGroup.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cluster/PlatformClusterGroup.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cluster/PlatformClusterGroup.java
index ef382d6..e0fff66 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cluster/PlatformClusterGroup.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cluster/PlatformClusterGroup.java
@@ -17,10 +17,6 @@
 
 package org.apache.ignite.internal.processors.platform.cluster;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.UUID;
-
 import org.apache.ignite.DataRegionMetrics;
 import org.apache.ignite.DataStorageMetrics;
 import org.apache.ignite.IgniteCache;
@@ -31,9 +27,9 @@ import org.apache.ignite.PersistenceMetrics;
 import org.apache.ignite.binary.BinaryRawWriter;
 import org.apache.ignite.cluster.ClusterMetrics;
 import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.internal.cluster.ClusterGroupEx;
 import org.apache.ignite.internal.binary.BinaryRawReaderEx;
 import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.cluster.ClusterGroupEx;
 import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget;
 import org.apache.ignite.internal.processors.platform.PlatformContext;
 import org.apache.ignite.internal.processors.platform.PlatformTarget;
@@ -46,6 +42,10 @@ import 
org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.UUID;
+
 /**
  * Interop projection.
  */
@@ -344,7 +344,7 @@ public class PlatformClusterGroup extends 
PlatformAbstractTarget {
             case OP_PING_NODE:
                 return pingNode(reader.readUuid()) ? TRUE : FALSE;
 
-            case OP_RESET_LOST_PARTITIONS:
+            case OP_RESET_LOST_PARTITIONS: {
                 int cnt = reader.readInt();
 
                 Collection<String> cacheNames = new ArrayList<>(cnt);
@@ -356,6 +356,7 @@ public class PlatformClusterGroup extends 
PlatformAbstractTarget {
                 
platformCtx.kernalContext().grid().resetLostPartitions(cacheNames);
 
                 return TRUE;
+            }
 
             default:
                 return super.processInStreamOutLong(type, reader);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
index aa11dfa..b65ca04 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformUtils.java
@@ -1225,6 +1225,47 @@ public class PlatformUtils {
     }
 
     /**
+     * Writes node attributes.
+     *
+     * @param writer Writer.
+     * @param attrs Attributes.
+     */
+    public static void writeNodeAttributes(BinaryRawWriterEx writer, 
Map<String, Object> attrs) {
+        assert writer != null;
+        assert attrs != null;
+
+        if (attrs != null) {
+            writer.writeInt(attrs.size());
+
+            for (Map.Entry<String, Object> e : attrs.entrySet()) {
+                writer.writeString(e.getKey());
+                writer.writeObjectDetached(e.getValue());
+            }
+        } else {
+            writer.writeInt(0);
+        }
+    }
+
+    /**
+     * Reads node attributes.
+     *
+     * @param reader Reader.
+     * @return Attributes.
+     */
+    public static Map<String, Object> readNodeAttributes(BinaryRawReaderEx 
reader) {
+        assert reader != null;
+
+        int attrCnt = reader.readInt();
+        Map<String, Object> attrs = new HashMap<>(attrCnt);
+
+        for (int j = 0; j < attrCnt; j++) {
+            attrs.put(reader.readString(), reader.readObjectDetached());
+        }
+
+        return attrs;
+    }
+
+    /**
      * Private constructor.
      */
     private PlatformUtils() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Common/TestUtils.DotNetCore.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Common/TestUtils.DotNetCore.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Common/TestUtils.DotNetCore.cs
index 99f732d..08cae96 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Common/TestUtils.DotNetCore.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Common/TestUtils.DotNetCore.cs
@@ -41,7 +41,8 @@ namespace Apache.Ignite.Core.Tests
                 Localhost = "127.0.0.1",
                 JvmOptions = TestJavaOptions(),
                 IgniteInstanceName = name,
-                Logger = TestLogger.Instance
+                Logger = TestLogger.Instance,
+                WorkDirectory = WorkDir
             };
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 22f4ad9..ab16bf1 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -75,6 +75,7 @@
     <Compile Include="ApiParity\CacheParityTest.cs" />
     <Compile Include="ApiParity\ClientConnectorConfigurationParityTest.cs" />
     <Compile Include="ApiParity\ClusterMetricsParityTest.cs" />
+    <Compile Include="ApiParity\ClusterNodeParityTest.cs" />
     <Compile Include="ApiParity\ClusterParityTest.cs" />
     <Compile Include="ApiParity\ComputeParityTest.cs" />
     <Compile Include="ApiParity\DataRegionConfigurationParityTest.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterNodeParityTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterNodeParityTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterNodeParityTest.cs
new file mode 100644
index 0000000..fcf7f89
--- /dev/null
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterNodeParityTest.cs
@@ -0,0 +1,45 @@
+/*
+ * 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.Tests.ApiParity
+{
+    using Apache.Ignite.Core.Cluster;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests that <see cref="IClusterNode"/> has all APIs from Java Ignite 
interface.
+    /// </summary>
+    public class ClusterNodeParityTest
+    {
+        /** Members that are missing on .NET side and should be added in 
future. */
+        private static readonly string[] MissingMembers =
+        {
+            "version"  // IGNITE-7101
+        };
+
+        /// <summary>
+        /// Tests the API parity.
+        /// </summary>
+        [Test]
+        public void TestClusterNode()
+        {
+            ParityTest.CheckInterfaceParity(
+                
@"modules\core\src\main\java\org\apache\ignite\cluster\ClusterNode.java",
+                typeof(IClusterNode), MissingMembers);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
index 4b4279f..b940d09 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
@@ -38,11 +38,7 @@
         /** Members that are missing on .NET side and should be added in 
future. */
         private static readonly string[] MissingMembers =
         {
-            "enableStatistics",  // IGNITE-7276
-            
-            // IGNITE-7301
-            "active",
-            "setBaselineTopology"
+            "enableStatistics"  // IGNITE-7276
         };
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ParityTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ParityTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ParityTest.cs
index d30d6d1..c9116af 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ParityTest.cs
@@ -80,7 +80,7 @@ namespace Apache.Ignite.Core.Tests.ApiParity
         {
             var path = GetFullPath(javaFilePath);
 
-            var dotNetMembers = type.GetMembers()
+            var dotNetMembers = GetMembers(type)
                 .GroupBy(x => x.Name)
                 .ToDictionary(x => x.Key, x => x.First(), 
StringComparer.OrdinalIgnoreCase);
 
@@ -91,6 +91,30 @@ namespace Apache.Ignite.Core.Tests.ApiParity
         }
 
         /// <summary>
+        /// Gets the members.
+        /// </summary>
+        private static IEnumerable<MemberInfo> GetMembers(Type type)
+        {
+            var types = new Stack<Type>();
+            types.Push(type);
+
+            while (types.Count > 0)
+            {
+                var t = types.Pop();
+
+                foreach (var m in t.GetMembers())
+                {
+                    yield return m;
+                }
+
+                foreach (var i in t.GetInterfaces())
+                {
+                    types.Push(i);
+                }
+            }
+        }
+
+        /// <summary>
         /// Gets the full path.
         /// </summary>
         private static string GetFullPath(string javaFilePath)

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataStorageMetricsTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataStorageMetricsTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataStorageMetricsTest.cs
index 1bc0218..d98254d 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataStorageMetricsTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataStorageMetricsTest.cs
@@ -56,7 +56,7 @@ namespace Apache.Ignite.Core.Tests.Cache
 
             using (var ignite = Ignition.Start(cfg))
             {
-                ignite.SetActive(true);
+                ignite.GetCluster().SetActive(true);
 
                 var cache = ignite.CreateCache<int, object>("c");
 
@@ -79,8 +79,8 @@ namespace Apache.Ignite.Core.Tests.Cache
                 Assert.AreEqual(0, metrics.WalArchiveSegments);
                 Assert.AreEqual(0, metrics.WalFsyncTimeAverage);
 
-                Assert.AreEqual(89, metrics.LastCheckpointTotalPagesNumber);
-                Assert.AreEqual(10, metrics.LastCheckpointDataPagesNumber);
+                Assert.Greater(metrics.LastCheckpointTotalPagesNumber, 26);
+                Assert.AreEqual(0, metrics.LastCheckpointDataPagesNumber);
                 Assert.AreEqual(0, 
metrics.LastCheckpointCopiedOnWritePagesNumber);
                 Assert.AreEqual(TimeSpan.Zero, 
metrics.LastCheckpointLockWaitDuration);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistenceTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistenceTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistenceTest.cs
index 4a60f7b..e3c0acf 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistenceTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistenceTest.cs
@@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Tests.Cache
 {
     using System;
     using System.IO;
+    using System.Linq;
     using Apache.Ignite.Core.Cache.Configuration;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Configuration;
@@ -34,6 +35,15 @@ namespace Apache.Ignite.Core.Tests.Cache
         private readonly string _tempDir = TestUtils.GetTempDirectoryName();
 
         /// <summary>
+        /// Sets up the test.
+        /// </summary>
+        [SetUp]
+        public void SetUp()
+        {
+            TestUtils.ClearWorkDir();
+        }
+
+        /// <summary>
         /// Tears down the test.
         /// </summary>
         [TearDown]
@@ -45,6 +55,8 @@ namespace Apache.Ignite.Core.Tests.Cache
             {
                 Directory.Delete(_tempDir, true);
             }
+
+            TestUtils.ClearWorkDir();
         }
 
         /// <summary>
@@ -84,7 +96,7 @@ namespace Apache.Ignite.Core.Tests.Cache
             // Start Ignite, put data, stop.
             using (var ignite = Ignition.Start(cfg))
             {
-                ignite.SetActive(true);
+                ignite.GetCluster().SetActive(true);
 
                 // Create cache with default region (persistence enabled), add 
data.
                 var cache = ignite.CreateCache<int, int>(cacheName);
@@ -110,7 +122,7 @@ namespace Apache.Ignite.Core.Tests.Cache
             // Start Ignite, verify data survival.
             using (var ignite = Ignition.Start(cfg))
             {
-                ignite.SetActive(true);
+                ignite.GetCluster().SetActive(true);
 
                 // Persistent cache already exists and contains data.
                 var cache = ignite.GetCache<int, int>(cacheName);
@@ -127,7 +139,7 @@ namespace Apache.Ignite.Core.Tests.Cache
             // Start Ignite, verify data loss.
             using (var ignite = Ignition.Start(cfg))
             {
-                ignite.SetActive(true);
+                ignite.GetCluster().SetActive(true);
 
                 Assert.IsFalse(ignite.GetCacheNames().Contains(cacheName));
             }
@@ -149,27 +161,17 @@ namespace Apache.Ignite.Core.Tests.Cache
         [Test]
         public void TestGridActivationWithPersistence()
         {
-            var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
-            {
-                DataStorageConfiguration = new DataStorageConfiguration
-                {
-                    DefaultDataRegionConfiguration = new 
DataRegionConfiguration
-                    {
-                        PersistenceEnabled = true,
-                        Name = "foo"
-                    }
-                }
-            };
+            var cfg = GetPersistentConfiguration();
 
             // Default config, inactive by default (IsActiveOnStart is ignored 
when persistence is enabled).
             using (var ignite = Ignition.Start(cfg))
             {
                 CheckIsActive(ignite, false);
 
-                ignite.SetActive(true);
+                ignite.GetCluster().SetActive(true);
                 CheckIsActive(ignite, true);
 
-                ignite.SetActive(false);
+                ignite.GetCluster().SetActive(false);
                 CheckIsActive(ignite, false);
             }
         }
@@ -187,10 +189,10 @@ namespace Apache.Ignite.Core.Tests.Cache
             {
                 CheckIsActive(ignite, true);
 
-                ignite.SetActive(false);
+                ignite.GetCluster().SetActive(false);
                 CheckIsActive(ignite, false);
 
-                ignite.SetActive(true);
+                ignite.GetCluster().SetActive(true);
                 CheckIsActive(ignite, true);
             }
 
@@ -200,20 +202,84 @@ namespace Apache.Ignite.Core.Tests.Cache
             {
                 CheckIsActive(ignite, false);
 
-                ignite.SetActive(true);
+                ignite.GetCluster().SetActive(true);
                 CheckIsActive(ignite, true);
 
-                ignite.SetActive(false);
+                ignite.GetCluster().SetActive(false);
                 CheckIsActive(ignite, false);
             }
         }
 
         /// <summary>
+        /// Tests the baseline topology.
+        /// </summary>
+        [Test]
+        public void TestBaselineTopology()
+        {
+            var cfg1 = new IgniteConfiguration(GetPersistentConfiguration())
+            {
+                ConsistentId = "node1"
+            };
+            var cfg2 = new IgniteConfiguration(GetPersistentConfiguration())
+            {
+                ConsistentId = "node2",
+                IgniteInstanceName = "2"
+            };
+
+            using (var ignite = Ignition.Start(cfg1))
+            {
+                // Start and stop to bump topology version.
+                Ignition.Start(cfg2);
+                Ignition.Stop(cfg2.IgniteInstanceName, true);
+
+                var cluster = ignite.GetCluster();
+                Assert.AreEqual(3, cluster.TopologyVersion);
+
+                // Can not set baseline while inactive.
+                var ex = Assert.Throws<IgniteException>(() => 
cluster.SetBaselineTopology(2));
+                Assert.AreEqual("Changing BaselineTopology on inactive cluster 
is not allowed.", ex.Message);
+
+                // Set with version.
+                cluster.SetActive(true);
+                cluster.SetBaselineTopology(2);
+
+                var res = cluster.GetBaselineTopology();
+                CollectionAssert.AreEquivalent(new[] {"node1", "node2"}, 
res.Select(x => x.ConsistentId));
+
+                cluster.SetBaselineTopology(1);
+                Assert.AreEqual("node1", 
cluster.GetBaselineTopology().Single().ConsistentId);
+
+                // Set with nodes.
+                cluster.SetBaselineTopology(res);
+                
+                res = cluster.GetBaselineTopology();
+                CollectionAssert.AreEquivalent(new[] { "node1", "node2" }, 
res.Select(x => x.ConsistentId));
+
+                cluster.SetBaselineTopology(cluster.GetTopology(1));
+                Assert.AreEqual("node1", 
cluster.GetBaselineTopology().Single().ConsistentId);
+
+                // Set to two nodes.
+                cluster.SetBaselineTopology(cluster.GetTopology(2));
+            }
+
+            // Check auto activation on cluster restart.
+            using (var ignite = Ignition.Start(cfg1))
+            using (Ignition.Start(cfg2))
+            {
+                var cluster = ignite.GetCluster();
+                Assert.IsTrue(cluster.IsActive());
+                
+                var res = cluster.GetBaselineTopology();
+                CollectionAssert.AreEquivalent(new[] { "node1", "node2" }, 
res.Select(x => x.ConsistentId));
+            }
+        }
+
+        /// <summary>
         /// Checks active state.
         /// </summary>
         private static void CheckIsActive(IIgnite ignite, bool isActive)
         {
-            Assert.AreEqual(isActive, ignite.IsActive());
+            Assert.AreEqual(isActive, ignite.GetCluster().IsActive());
 
             if (isActive)
             {
@@ -228,5 +294,23 @@ namespace Apache.Ignite.Core.Tests.Cache
                     ex.Message.Substring(0, 62));
             }
         }
+
+        /// <summary>
+        /// Gets the persistent configuration.
+        /// </summary>
+        private static IgniteConfiguration GetPersistentConfiguration()
+        {
+            return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+            {
+                DataStorageConfiguration = new DataStorageConfiguration
+                {
+                    DefaultDataRegionConfiguration = new 
DataRegionConfiguration
+                    {
+                        PersistenceEnabled = true,
+                        Name = "foo"
+                    }
+                }
+            };
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
index cf0ad40..d0c576d 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
@@ -142,9 +142,13 @@ namespace Apache.Ignite.Core.Tests.Compute
                 Assert.IsTrue(node.Addresses.Count > 0);
                 Assert.Throws<NotSupportedException>(() => 
node.Addresses.Add("addr"));
 
-                Assert.NotNull(node.GetAttributes());
-                Assert.IsTrue(node.GetAttributes().Count > 0);
-                Assert.Throws<NotSupportedException>(() => 
node.GetAttributes().Add("key", "val"));
+                Assert.NotNull(node.Attributes);
+                Assert.IsTrue(node.Attributes.Count > 0);
+                Assert.Throws<NotSupportedException>(() => 
node.Attributes.Add("key", "val"));
+
+#pragma warning disable 618
+                Assert.AreSame(node.Attributes, node.GetAttributes());
+#pragma warning restore 618
 
                 Assert.NotNull(node.HostNames);
                 Assert.Throws<NotSupportedException>(() => 
node.HostNames.Add("h"));

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
index 0bc4e0f..734b0cf 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
@@ -426,6 +426,7 @@ namespace Apache.Ignite.Core.Tests
                 using (var ignite = Ignition.Start(cfg))
                 {
                     Assert.AreEqual(id, 
ignite.GetConfiguration().ConsistentId);
+                    Assert.AreEqual(id ?? "127.0.0.1:47500", 
ignite.GetCluster().GetLocalNode().ConsistentId);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs
index c00ca49..bf2849e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs
@@ -20,7 +20,9 @@ namespace Apache.Ignite.Core.Tests
     using System;
     using System.Collections.Concurrent;
     using System.Collections.Generic;
+    using System.IO;
     using System.Linq;
+    using System.Reflection;
     using System.Threading;
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Cluster;
@@ -44,6 +46,11 @@ namespace Apache.Ignite.Core.Tests
         /** */
         private const int DfltBusywaitSleepInterval = 200;
 
+        /** Work dir. */
+        private static readonly string WorkDir = 
+            // ReSharper disable once AssignNullToNotNullAttribute
+            
Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 
"ignite_work");
+
         /** */
         private static readonly IList<string> TestJvmOpts = 
Environment.Is64BitProcess
             ? new List<string>
@@ -349,5 +356,38 @@ namespace Apache.Ignite.Core.Tests
 
             return marsh.Unmarshal<T>(marsh.Marshal(obj));
         }
+
+        /// <summary>
+        /// Clears the work dir.
+        /// </summary>
+        public static void ClearWorkDir()
+        {
+            if (!Directory.Exists(WorkDir))
+            {
+                return;
+            }
+
+            // Delete everything we can. Some files may be locked.
+            foreach (var e in Directory.GetFileSystemEntries(WorkDir, "*", 
SearchOption.AllDirectories))
+            {
+                try
+                {
+                    File.Delete(e);
+                }
+                catch (Exception)
+                {
+                    // Ignore
+                }
+
+                try
+                {
+                    Directory.Delete(e, true);
+                }
+                catch (Exception)
+                {
+                    // Ignore
+                }
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs
index 2169630..f8ff874 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs
@@ -78,7 +78,8 @@ namespace Apache.Ignite.Core.Tests
                             ? DataRegionConfiguration.DefaultMaxSize
                             : 256 * 1024 * 1024
                     }
-                }
+                },
+                WorkDirectory = WorkDir
             };
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj 
b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index f9b22fc..adae2b1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -56,6 +56,7 @@
     <Compile Include="Cache\Configuration\DataPageEvictionMode.cs" />
     <Compile Include="Client\Cache\CacheClientConfiguration.cs" />
     <Compile Include="Client\IgniteClientConfigurationSection.cs" />
+    <Compile Include="Cluster\IBaselineNode.cs" />
     <Compile Include="Configuration\CheckpointWriteOrder.cs" />
     <Compile Include="Configuration\DataPageEvictionMode.cs" />
     <Compile Include="Configuration\DataRegionConfiguration.cs" />
@@ -79,6 +80,7 @@
     <Compile Include="Impl\Binary\IBinaryRawWriteAware.cs" />
     <Compile Include="Impl\Binary\MultidimensionalArrayHolder.cs" />
     <Compile Include="Impl\Binary\MultidimensionalArraySerializer.cs" />
+    <Compile Include="Impl\Binary\OptimizedMarshallerObject.cs" />
     <Compile Include="Impl\Client\Cache\CacheFlags.cs" />
     <Compile Include="Impl\Client\Cache\ClientCacheConfigurationSerializer.cs" 
/>
     <Compile Include="Impl\Client\Cache\Query\ClientFieldsQueryCursor.cs" />
@@ -90,6 +92,7 @@
     <Compile Include="Impl\Client\Cache\Query\StatementType.cs" />
     <Compile Include="Client\ClientStatusCode.cs" />
     <Compile Include="Events\LocalEventListener.cs" />
+    <Compile Include="Impl\Cluster\BaselineNode.cs" />
     <Compile Include="Impl\DataStorageMetrics.cs" />
     <Compile Include="Impl\IIgniteInternal.cs" />
     <Compile Include="Impl\Client\Cache\CacheClient.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IBaselineNode.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IBaselineNode.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IBaselineNode.cs
new file mode 100644
index 0000000..d0c5f81
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IBaselineNode.cs
@@ -0,0 +1,37 @@
+/*
+ * 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.Cluster
+{
+    using System.Collections.Generic;
+
+    /// <summary>
+    /// Baseline topology node (see <see 
cref="ICluster.GetBaselineTopology"/>).
+    /// </summary>
+    public interface IBaselineNode
+    {
+        /// <summary>
+        /// Gets the consistent ID from <see 
cref="IgniteConfiguration.ConsistentId"/>.
+        /// </summary>
+        object ConsistentId { get; }
+
+        /// <summary>
+        /// Gets all node attributes. Attributes are assigned to nodes at 
startup.
+        /// </summary>
+        IDictionary<string, object> Attributes { get; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/ICluster.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/ICluster.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/ICluster.cs
index 812a644..f9bbdf7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/ICluster.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/ICluster.cs
@@ -88,6 +88,38 @@ namespace Apache.Ignite.Core.Cluster
         /// <value>
         /// The reconnect task.
         /// </value>
-        Task<bool> ClientReconnectTask { get; } 
+        Task<bool> ClientReconnectTask { get; }
+
+        /// <summary>
+        /// Changes Ignite grid state to active or inactive.
+        /// </summary>
+        void SetActive(bool isActive);
+
+        /// <summary>
+        /// Determines whether this grid is in active state.
+        /// </summary>
+        /// <returns>
+        ///   <c>true</c> if the grid is active; otherwise, <c>false</c>.
+        /// </returns>
+        bool IsActive();
+
+        /// <summary>
+        /// Sets the baseline topology from the cluster topology of the given 
version.
+        /// This method requires active cluster (<see cref="IsActive"/>).
+        /// </summary>
+        /// <param name="topologyVersion">The topology version.</param>
+        void SetBaselineTopology(long topologyVersion);
+
+        /// <summary>
+        /// Sets the baseline topology nodes.
+        /// </summary>
+        /// <param name="nodes">The nodes.</param>
+        void SetBaselineTopology(IEnumerable<IBaselineNode> nodes);
+
+        /// <summary>
+        /// Gets the baseline topology.
+        /// Returns null if <see cref="SetBaselineTopology(long)"/> has not 
been called.
+        /// </summary>
+        ICollection<IBaselineNode> GetBaselineTopology();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IClusterNode.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IClusterNode.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IClusterNode.cs
index 5f14116..ec22d18 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IClusterNode.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cluster/IClusterNode.cs
@@ -33,7 +33,7 @@ namespace Apache.Ignite.Core.Cluster
     /// <para/>
     /// All members are thread-safe and may be used concurrently from multiple 
threads.
     /// </summary>
-    public interface IClusterNode
+    public interface IClusterNode : IBaselineNode
     {
         /// <summary>
         /// Globally unique node ID. A new ID is generated every time a node 
restarts.
@@ -66,6 +66,7 @@ namespace Apache.Ignite.Core.Cluster
         /// </summary>
         /// <returns>All node attributes.</returns>
         [SuppressMessage("Microsoft.Design", 
"CA1024:UsePropertiesWhereAppropriate", Justification = "Semantics.")]
+        [Obsolete("Use Attributes property.")]
         IDictionary<string, object> GetAttributes();
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
index 035d4b5..52323c8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
@@ -357,6 +357,7 @@ namespace Apache.Ignite.Core
         /// <summary>
         /// Changes Ignite grid state to active or inactive.
         /// </summary>
+        [Obsolete("Use GetCluster().SetActive instead.")]
         void SetActive(bool isActive);
 
         /// <summary>
@@ -365,6 +366,7 @@ namespace Apache.Ignite.Core
         /// <returns>
         ///   <c>true</c> if the grid is active; otherwise, <c>false</c>.
         /// </returns>
+        [Obsolete("Use GetCluster().IsActive instead.")]
         bool IsActive();
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index f63d959..0ddf9a8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -1095,7 +1095,7 @@ namespace Apache.Ignite.Core
         /// <summary>
         /// Gets or sets the user attributes for this node.
         /// <para />
-        /// These attributes can be retrieved later via <see 
cref="IClusterNode.GetAttributes"/>.
+        /// These attributes can be retrieved later via <see 
cref="IBaselineNode.Attributes"/>.
         /// Environment variables are added to node attributes automatically.
         /// NOTE: attribute names starting with "org.apache.ignite" are 
reserved for internal use.
         /// </summary>
@@ -1377,7 +1377,7 @@ namespace Apache.Ignite.Core
 
         /// <summary>
         /// Gets or sets a value indicating whether grid should be active on 
start.
-        /// See also <see cref="IIgnite.IsActive"/> and <see 
cref="IIgnite.SetActive"/>.
+        /// See also <see cref="ICluster.IsActive"/> and <see 
cref="ICluster.SetActive"/>.
         /// <para />
         /// This property is ignored when <see 
cref="DataStorageConfiguration"/> is present:
         /// cluster is always inactive on start when Ignite Persistence is 
enabled.

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
index 430b426..cae0f5f 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
@@ -113,6 +113,9 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             // 14. Enum. Should be read as Array, see WriteEnumArray 
implementation.
             ReadHandlers[BinaryTypeId.ArrayEnum] = new 
BinarySystemReader(ReadArray);
+
+            // 15. Optimized marshaller objects.
+            ReadHandlers[BinaryTypeId.OptimizedMarshaller] = new 
BinarySystemReader(ReadOptimizedMarshallerObject);
         }
 
         /// <summary>
@@ -229,6 +232,11 @@ namespace Apache.Ignite.Core.Impl.Binary
                 return new BinarySystemWriteHandler<object>(WriteArray, true);
             }
 
+            if (type == typeof(OptimizedMarshallerObject))
+            {
+                return new 
BinarySystemWriteHandler<OptimizedMarshallerObject>((w, o) => 
o.Write(w.Stream), false);
+            }
+
             return null;
         }
 
@@ -533,6 +541,14 @@ namespace Apache.Ignite.Core.Impl.Binary
             ctx.Stream.WriteByte(BinaryUtils.HdrNull);
         }
 
+        /// <summary>
+        /// Reads the optimized marshaller object.
+        /// </summary>
+        private static object ReadOptimizedMarshallerObject(BinaryReader ctx, 
Type type)
+        {
+            return new OptimizedMarshallerObject(ctx.Stream);
+        }
+
         /**
          * <summary>Read delegate.</summary>
          * <param name="ctx">Read context.</param>

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryTypeId.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryTypeId.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryTypeId.cs
index 1d3d9c4..8067a39 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryTypeId.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryTypeId.cs
@@ -164,6 +164,9 @@ namespace Apache.Ignite.Core.Impl.Binary
         /** Type: platform object proxy. */
         public const byte PlatformJavaObjectFactoryProxy = 99;
 
+        /** Type: object written with Java OptimizedMarshaller. */
+        public const byte OptimizedMarshaller = 254;
+
         /** Type: platform object proxy. */
         public const int IgniteUuid = 2018070327;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/OptimizedMarshallerObject.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/OptimizedMarshallerObject.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/OptimizedMarshallerObject.cs
new file mode 100644
index 0000000..5d2ec05
--- /dev/null
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/OptimizedMarshallerObject.cs
@@ -0,0 +1,54 @@
+/*
+ * 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.Binary
+{
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+
+    /// <summary>
+    /// Object written with Java OptimizedMarshaller.
+    /// We just hold it as a byte array.
+    /// </summary>
+    internal class OptimizedMarshallerObject
+    {
+        /** */
+        private readonly byte[] _data;
+
+        /// <summary>
+        /// Initializes a new instance of the <see 
cref="OptimizedMarshallerObject"/> class.
+        /// </summary>
+        public OptimizedMarshallerObject(IBinaryStream stream)
+        {
+            Debug.Assert(stream != null);
+
+            _data = stream.ReadByteArray(stream.ReadInt());
+        }
+
+        /// <summary>
+        /// Writes to the specified writer.
+        /// </summary>
+        public void Write(IBinaryStream stream)
+        {
+            Debug.Assert(stream != null);
+
+            stream.WriteByte(BinaryTypeId.OptimizedMarshaller);
+            stream.WriteInt(_data.Length);
+            stream.WriteByteArray(_data);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/BaselineNode.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/BaselineNode.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/BaselineNode.cs
new file mode 100644
index 0000000..23ec724
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/BaselineNode.cs
@@ -0,0 +1,89 @@
+/*
+ * 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.Cluster
+{
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Impl.Binary;
+
+    /// <summary>
+    /// Baseline node.
+    /// </summary>
+    internal class BaselineNode : IBaselineNode
+    {
+        /** Attributes. */
+        private readonly IDictionary<string, object> _attributes;
+
+        /** Consistent ID. */
+        private readonly object _consistentId;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BaselineNode"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public BaselineNode(IBinaryRawReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            _consistentId = reader.ReadObject<object>();
+            _attributes = ClusterNodeImpl.ReadAttributes(reader);
+        }
+
+        /** <inheritdoc /> */
+        public object ConsistentId
+        {
+            get { return _consistentId; }
+        }
+
+        /** <inheritdoc /> */
+        public IDictionary<string, object> Attributes
+        {
+            get { return _attributes; }
+        }
+
+        /// <summary>
+        /// Writes this instance to specified writer.
+        /// </summary>
+        public static void Write(BinaryWriter writer, IBaselineNode node)
+        {
+            Debug.Assert(writer != null);
+            Debug.Assert(node != null);
+
+            writer.WriteObjectDetached(node.ConsistentId);
+            
+            var attrs = node.Attributes;
+
+            if (attrs != null)
+            {
+                writer.WriteInt(attrs.Count);
+
+                foreach (var attr in attrs)
+                {
+                    writer.WriteString(attr.Key);
+                    writer.WriteObjectDetached(attr.Value);
+                }
+            }
+            else
+            {
+                writer.WriteInt(0);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/ClusterNodeImpl.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/ClusterNodeImpl.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/ClusterNodeImpl.cs
index b658353..fbf4764 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/ClusterNodeImpl.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cluster/ClusterNodeImpl.cs
@@ -55,6 +55,9 @@ namespace Apache.Ignite.Core.Impl.Cluster
         /** Client flag. */
         private readonly bool _isClient;
 
+        /** Consistent id. */
+        private readonly object _consistentId;
+
         /** Metrics. */
         private volatile ClusterMetricsImpl _metrics;
         
@@ -73,13 +76,14 @@ namespace Apache.Ignite.Core.Impl.Cluster
 
             _id = id.Value;
 
-            _attrs = reader.ReadDictionaryAsGeneric<string, 
object>().AsReadOnly();
+            _attrs = ReadAttributes(reader);
             _addrs = reader.ReadCollectionAsList<string>().AsReadOnly();
             _hosts = reader.ReadCollectionAsList<string>().AsReadOnly();
             _order = reader.ReadLong();
             _isLocal = reader.ReadBoolean();
             _isDaemon = reader.ReadBoolean();
             _isClient = reader.ReadBoolean();
+            _consistentId = reader.ReadObject<object>();
 
             _metrics = reader.ReadBoolean() ? new ClusterMetricsImpl(reader) : 
null;
         }
@@ -119,7 +123,7 @@ namespace Apache.Ignite.Core.Impl.Cluster
         /** <inheritDoc /> */
         public IDictionary<string, object> GetAttributes()
         {
-            return _attrs.AsReadOnly();
+            return _attrs;
         }
 
         /** <inheritDoc /> */
@@ -181,6 +185,18 @@ namespace Apache.Ignite.Core.Impl.Cluster
         }
 
         /** <inheritDoc /> */
+        public object ConsistentId
+        {
+            get { return _consistentId; }
+        }
+
+        /** <inheritDoc /> */
+        public IDictionary<string, object> Attributes
+        {
+            get { return _attrs; }
+        }
+
+        /** <inheritDoc /> */
         public bool IsClient
         {
             get { return _isClient; }
@@ -218,5 +234,23 @@ namespace Apache.Ignite.Core.Impl.Cluster
         {
             _igniteRef = new WeakReference(grid);
         }
+
+        /// <summary>
+        /// Reads the attributes.
+        /// </summary>
+        internal static IDictionary<string, object> 
ReadAttributes(IBinaryRawReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            var count = reader.ReadInt();
+            var res = new Dictionary<string, object>(count);
+
+            for (var i = 0; i < count; i++)
+            {
+                res[reader.ReadString()] = reader.ReadObject<object>();
+            }
+
+            return res.AsReadOnly();
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
index eb7f627..10b083b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
@@ -84,7 +84,10 @@ namespace Apache.Ignite.Core.Impl
             LoggerLog = 20,
             GetBinaryProcessor = 21,
             ReleaseStart = 22,
-            AddCacheConfiguration = 23
+            AddCacheConfiguration = 23,
+            SetBaselineTopologyVersion = 24,
+            SetBaselineTopologyNodes = 25,
+            GetBaselineTopology = 26
         }
 
         /** */
@@ -781,6 +784,40 @@ namespace Apache.Ignite.Core.Impl
         }
 
         /** <inheritdoc /> */
+        public void SetBaselineTopology(long topologyVersion)
+        {
+            DoOutInOp((int) Op.SetBaselineTopologyVersion, topologyVersion);
+        }
+
+        /** <inheritdoc /> */
+        public void SetBaselineTopology(IEnumerable<IBaselineNode> nodes)
+        {
+            IgniteArgumentCheck.NotNull(nodes, "nodes");
+
+            DoOutOp((int) Op.SetBaselineTopologyNodes, w =>
+            {
+                var pos = w.Stream.Position;
+                w.WriteInt(0);
+                var cnt = 0;
+
+                foreach (var node in nodes)
+                {
+                    cnt++;
+                    BaselineNode.Write(w, node);
+                }
+
+                w.Stream.WriteInt(pos, cnt);
+            });
+        }
+
+        /** <inheritdoc /> */
+        public ICollection<IBaselineNode> GetBaselineTopology()
+        {
+            return DoInOp((int) Op.GetBaselineTopology,
+                s => Marshaller.StartUnmarshal(s).ReadCollectionRaw(r => 
(IBaselineNode) new BaselineNode(r)));
+        }
+
+        /** <inheritdoc /> */
 #pragma warning disable 618
         public IPersistentStoreMetrics GetPersistentStoreMetrics()
         {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e21e2756/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
index f3632ce..2f0a271 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
@@ -19,11 +19,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
 {
     using System;
     using System.Diagnostics;
-    using System.Reflection;
     using System.Runtime.InteropServices;
     using System.Security;
     using Apache.Ignite.Core.Common;
-    using Apache.Ignite.Core.Impl.Common;
 
     /// <summary>
     /// JNIEnv.

Reply via email to