You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2020/01/22 07:18:49 UTC
[ignite] branch master updated: IGNITE-12555 .NET: Fix
SerializableSerializer performance
This is an automated email from the ASF dual-hosted git repository.
ptupitsyn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 274c443 IGNITE-12555 .NET: Fix SerializableSerializer performance
274c443 is described below
commit 274c4432e365bed105d53f8a284532432da24d96
Author: Pavel Tupitsyn <pt...@apache.org>
AuthorDate: Wed Jan 22 10:18:35 2020 +0300
IGNITE-12555 .NET: Fix SerializableSerializer performance
Use cached binary metadata when possible: route all metadata through `Marshaller`, handle caching there.
Before the fix, we had a `IBinaryProcessor.GetBinaryType` call for every deserialized object that implements `ISerializable`, which caused huge performance drop, especially for thin client where every call is a network operation. The most common `ISerializable` type is `DateTime`.
Perf measurements:
* `GetAllEmployeesBenchmark` +56%
* `ThinClientGetAllEmployeesBenchmark` +2000%
* `GetBenchmark` +30%
* `ThinClientGetBenchmark` +20%
---
.../processors/platform/PlatformContext.java | 3 +-
.../processors/platform/PlatformContextImpl.java | 10 +-
.../platform/binary/PlatformBinaryProcessor.java | 15 +-
.../Apache.Ignite.Benchmarks.DotNetCore.csproj | 18 ++
.../Apache.Ignite.Benchmarks.csproj | 2 +
.../Apache.Ignite.Benchmarks/BenchmarkRunner.cs | 26 +-
...GetBenchmark.cs => GetAllEmployeesBenchmark.cs} | 38 +--
.../Interop/GetBenchmark.cs | 8 +
.../Apache.Ignite.Benchmarks/Model/Employee.cs | 18 ++
...rk.cs => ThinClientGetAllEmployeesBenchmark.cs} | 39 +--
.../ThinClient/ThinClientGetBenchmark.cs | 8 +
.../Apache.Ignite.Core.Tests.DotNetCore.csproj | 26 +-
.../Apache.Ignite.Core.Tests.csproj | 6 +
.../Serializable/DynamicFieldSetSerializable.cs | 81 ++++++
.../Binary/Serializable/DynamicFieldSetTest.cs | 120 ++++++++
.../Client/Cache/CacheTest.cs | 21 +-
.../Client/Cache/CacheTestNoMeta.cs | 6 -
.../Client/Cache/DynamicFieldSetTest.cs | 141 ++++++++++
.../Client/Cache/PartitionAwarenessTest.cs | 65 +----
.../Client/Cache/SerializableObjectsTest.cs | 136 ++++++++++
.../Client/ClientServerCacheAdapter.cs | 302 +++++++++++++++++++++
.../Client/ClientServerCacheAdapterExtensions.cs | 36 +++
.../Client/ClientTestBase.cs | 80 +++++-
.../Client/IgniteClientConfigurationTest.cs | 2 +-
.../platforms/dotnet/Apache.Ignite.Core/IIgnite.cs | 2 +-
.../Impl/Binary/BinaryObjectSchemaSerializer.cs | 61 +++--
.../Impl/Binary/BinaryProcessor.cs | 21 +-
.../Impl/Binary/BinaryProcessorClient.cs | 6 -
.../Apache.Ignite.Core/Impl/Binary/BinaryReader.cs | 10 +-
.../Impl/Binary/IBinaryProcessor.cs | 5 -
.../Apache.Ignite.Core/Impl/Binary/Marshaller.cs | 97 +++++--
.../Impl/Binary/Metadata/BinaryType.cs | 9 +-
.../Impl/Binary/Metadata/BinaryTypeHolder.cs | 69 +++--
.../Impl/Binary/SerializableSerializer.cs | 35 ++-
.../platforms/dotnet/Apache.Ignite.DotNetCore.sln | 6 +
modules/platforms/dotnet/README.md | 6 +-
36 files changed, 1298 insertions(+), 236 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java
index da92c6c..6de8c51 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java
@@ -132,8 +132,9 @@ public interface PlatformContext {
*
* @param writer Writer.
* @param typeId Type ID.
+ * @param includeSchemas Whether to include binary object schemas into the result.
*/
- public void writeMetadata(BinaryRawWriterEx writer, int typeId);
+ public void writeMetadata(BinaryRawWriterEx writer, int typeId, boolean includeSchemas);
/**
* Write all available metadata.
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 0f6f252..55145aa 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
@@ -338,8 +338,8 @@ public class PlatformContextImpl implements PlatformContext {
}
/** {@inheritDoc} */
- @Override public void writeMetadata(BinaryRawWriterEx writer, int typeId) {
- writeMetadata0(writer, cacheObjProc.metadata(typeId));
+ @Override public void writeMetadata(BinaryRawWriterEx writer, int typeId, boolean includeSchemas) {
+ writeMetadata0(writer, cacheObjProc.metadata(typeId), includeSchemas);
}
/** {@inheritDoc} */
@@ -349,7 +349,7 @@ public class PlatformContextImpl implements PlatformContext {
writer.writeInt(metas.size());
for (BinaryType m : metas)
- writeMetadata0(writer, m);
+ writeMetadata0(writer, m, false);
}
/** {@inheritDoc} */
@@ -363,7 +363,7 @@ public class PlatformContextImpl implements PlatformContext {
* @param writer Writer.
* @param meta Metadata.
*/
- private void writeMetadata0(BinaryRawWriterEx writer, BinaryType meta) {
+ private void writeMetadata0(BinaryRawWriterEx writer, BinaryType meta, boolean includeSchemas) {
if (meta == null)
writer.writeBoolean(false);
else {
@@ -371,7 +371,7 @@ public class PlatformContextImpl implements PlatformContext {
BinaryMetadata meta0 = ((BinaryTypeImpl) meta).metadata();
- PlatformUtils.writeBinaryMetadata(writer, meta0, false);
+ PlatformUtils.writeBinaryMetadata(writer, meta0, includeSchemas);
}
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
index 76df6a2..23d2cb5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
@@ -54,6 +54,9 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
/** */
private static final int OP_REGISTER_ENUM = 7;
+ /** */
+ private static final int OP_GET_META_WITH_SCHEMAS = 8;
+
/**
* Constructor.
*
@@ -99,7 +102,15 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
case OP_GET_META: {
int typeId = reader.readInt();
- platformCtx.writeMetadata(writer, typeId);
+ platformCtx.writeMetadata(writer, typeId, false);
+
+ break;
+ }
+
+ case OP_GET_META_WITH_SCHEMAS: {
+ int typeId = reader.readInt();
+
+ platformCtx.writeMetadata(writer, typeId, true);
break;
}
@@ -142,7 +153,7 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
BinaryType binaryType = platformCtx.kernalContext().grid().binary().registerEnum(name, vals);
- platformCtx.writeMetadata(writer, binaryType.typeId());
+ platformCtx.writeMetadata(writer, binaryType.typeId(), false);
break;
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.DotNetCore.csproj b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.DotNetCore.csproj
new file mode 100644
index 0000000..b4123b6
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.DotNetCore.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>netcoreapp2.0</TargetFramework>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <AssemblyName>Apache.Ignite.Benchmarks</AssemblyName>
+ <RootNamespace>Apache.Ignite.Benchmarks</RootNamespace>
+ <AssemblyOriginatorKeyFile>Apache.Ignite.Benchmarks.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly>true</SignAssembly>
+ <DelaySign>false</DelaySign>
+ <OutputType>Exe</OutputType>
+ <ServerGarbageCollection>true</ServerGarbageCollection>
+ <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
+ </PropertyGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Apache.Ignite.Core\Apache.Ignite.Core.DotNetCore.csproj" />
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj
index 1c200e6..ea9b88e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj
@@ -51,6 +51,7 @@
<Compile Include="BenchmarkUtils.cs" />
<Compile Include="Interop\GetAllBinaryBenchmark.cs" />
<Compile Include="Interop\GetAllBenchmark.cs" />
+ <Compile Include="Interop\GetAllEmployeesBenchmark.cs" />
<Compile Include="Interop\PlatformBenchmarkBase.cs" />
<Compile Include="Interop\ClosureBenchmark.cs" />
<Compile Include="Interop\GetAsyncBenchmark.cs" />
@@ -73,6 +74,7 @@
<Compile Include="Result\BenchmarkFileResultWriter.cs" />
<Compile Include="Result\IBenchmarkResultWriter.cs" />
<Compile Include="ThinClient\ThinClientGetAllBinaryBenchmark.cs" />
+ <Compile Include="ThinClient\ThinClientGetAllEmployeesBenchmark.cs" />
<Compile Include="ThinClient\ThinClientGetAsyncBenchmark.cs" />
<Compile Include="ThinClient\ThinClientGetAllBenchmark.cs" />
<Compile Include="ThinClient\ThinClientGetBenchmark.cs" />
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs
index fb2fbd2..6d34bb5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Benchmarks
using System;
using System.Diagnostics;
using System.IO;
+ using System.Reflection;
using System.Text;
using Apache.Ignite.Benchmarks.Interop;
@@ -40,7 +41,7 @@ namespace Apache.Ignite.Benchmarks
typeof(GetAllBinaryBenchmark).FullName,
//typeof(ThinClientGetAllBenchmark).FullName,
//typeof(ThinClientGetAllBinaryBenchmark).FullName,
- "-ConfigPath", Directory.GetCurrentDirectory() + @"\..\..\Config\benchmark.xml",
+ "-ConfigPath", GetConfigPath(),
"-Threads", "1",
"-Warmup", "0",
"-Duration", "60",
@@ -52,7 +53,7 @@ namespace Apache.Ignite.Benchmarks
Console.WriteLine("GC Server: " + gcSrv);
if (!gcSrv)
- Console.WriteLine("WARNING! GC server mode is disabled. This could yield in bad preformance.");
+ Console.WriteLine("WARNING! GC server mode is disabled. This could yield in bad performance.");
Console.WriteLine("DotNet benchmark process started: " + Process.GetCurrentProcess().Id);
@@ -94,5 +95,26 @@ namespace Apache.Ignite.Benchmarks
Console.ReadLine();
#endif
}
+
+ /// <summary>
+ /// Gets the config path.
+ /// </summary>
+ private static string GetConfigPath()
+ {
+ var dir = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
+
+ while (dir != null)
+ {
+ var configPath = Path.Combine(dir.FullName, "Config", "benchmark.xml");
+ if (File.Exists(configPath))
+ {
+ return configPath;
+ }
+
+ dir = dir.Parent;
+ }
+
+ throw new InvalidOperationException("Could not locate benchmark config.");
+ }
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetAllEmployeesBenchmark.cs
similarity index 57%
copy from modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
copy to modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetAllEmployeesBenchmark.cs
index 5d69669..3f4d6a9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetAllEmployeesBenchmark.cs
@@ -18,45 +18,29 @@
namespace Apache.Ignite.Benchmarks.Interop
{
using System.Collections.Generic;
- using Apache.Ignite.Benchmarks.Model;
- using Apache.Ignite.Core.Cache;
+ using System.Linq;
/// <summary>
- /// Cache Get benchmark.
+ /// Cache GetAll benchmark.
/// </summary>
- internal class GetBenchmark : PlatformBenchmarkBase
+ internal class GetAllEmployeesBenchmark : GetBenchmark
{
- /** Cache name. */
- private const string CacheName = "cache";
-
- /** Native cache wrapper. */
- private ICache<int, Employee> _cache;
-
- /** <inheritDoc /> */
- protected override void OnStarted()
- {
- base.OnStarted();
-
- _cache = Node.GetCache<int, Employee>(CacheName);
-
- for (int i = 0; i < Emps.Length; i++)
- _cache.Put(i, Emps[i]);
- }
-
/** <inheritDoc /> */
protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
{
- descs.Add(BenchmarkOperationDescriptor.Create("Get", Get, 1));
+ descs.Add(BenchmarkOperationDescriptor.Create("GetAllEmployees", GetAll, 1));
}
-
+
/// <summary>
- /// Cache get.
+ /// Cache GetAll.
/// </summary>
- private void Get(BenchmarkState state)
+ private void GetAll(BenchmarkState state)
{
- var idx = BenchmarkUtils.GetRandomInt(Dataset);
+ var batchSize = Dataset / 10;
+ var idx = BenchmarkUtils.GetRandomInt(Dataset - batchSize);
+ var keys = Enumerable.Range(idx, batchSize);
- _cache.Get(idx);
+ Cache.GetAll(keys);
}
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
index 5d69669..cb52808 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
@@ -32,6 +32,14 @@ namespace Apache.Ignite.Benchmarks.Interop
/** Native cache wrapper. */
private ICache<int, Employee> _cache;
+ /// <summary>
+ /// Gets the cache.
+ /// </summary>
+ protected ICache<int, Employee> Cache
+ {
+ get { return _cache; }
+ }
+
/** <inheritDoc /> */
protected override void OnStarted()
{
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Employee.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Employee.cs
index 7f082f3..95de9bb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Employee.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Employee.cs
@@ -17,6 +17,7 @@
namespace Apache.Ignite.Benchmarks.Model
{
+ using System;
using Apache.Ignite.Core.Binary;
/// <summary>
@@ -73,6 +74,16 @@ namespace Apache.Ignite.Benchmarks.Model
/// Points.
/// </summary>
public int Points { get; set; }
+
+ /// <summary>
+ /// Birthday.
+ /// </summary>
+ public DateTime Birthday { get; set; }
+
+ /// <summary>
+ /// Timespan.
+ /// </summary>
+ public DateTime Timestamp { get; set; }
/// <summary>
/// Constructor.
@@ -101,6 +112,9 @@ namespace Apache.Ignite.Benchmarks.Model
Payload = new byte[payloadSize];
Points = 100;
+
+ Birthday = new DateTime(2005, 5, 5, 1, 1, 1, DateTimeKind.Local).AddHours(id);
+ Timestamp = new DateTime(2005, 5, 5, 1, 1, 1, DateTimeKind.Utc).AddMinutes(id);
}
/** <inheritDoc /> */
@@ -116,6 +130,8 @@ namespace Apache.Ignite.Benchmarks.Model
writer.WriteByteArray("payload", Payload);
writer.WriteString("name", Name);
writer.WriteObject("address", Address);
+ writer.WriteObject("birthday", Birthday);
+ writer.WriteTimestamp("timestamp", Timestamp);
}
/** <inheritDoc /> */
@@ -131,6 +147,8 @@ namespace Apache.Ignite.Benchmarks.Model
Payload = reader.ReadByteArray("payload");
Name = reader.ReadString("name");
Address = reader.ReadObject<Address>("address");
+ Birthday = reader.ReadObject<DateTime>("birthday");
+ Timestamp = reader.ReadTimestamp("timestamp").GetValueOrDefault();
}
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetAllEmployeesBenchmark.cs
similarity index 55%
copy from modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetBenchmark.cs
copy to modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetAllEmployeesBenchmark.cs
index 4af5f1f..006d631 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetBenchmark.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetAllEmployeesBenchmark.cs
@@ -18,46 +18,29 @@
namespace Apache.Ignite.Benchmarks.ThinClient
{
using System.Collections.Generic;
- using Apache.Ignite.Benchmarks.Interop;
- using Apache.Ignite.Benchmarks.Model;
- using Apache.Ignite.Core.Client.Cache;
+ using System.Linq;
/// <summary>
- /// Cache get benchmark.
+ /// Cache GetAll benchmark.
/// </summary>
- internal class ThinClientGetBenchmark : PlatformBenchmarkBase
+ internal class ThinClientGetAllEmployeesBenchmark : ThinClientGetBenchmark
{
- /** Cache name. */
- private const string CacheName = "cache";
-
- /** Native cache wrapper. */
- private ICacheClient<int, Employee> _cache;
-
- /** <inheritDoc /> */
- protected override void OnStarted()
- {
- base.OnStarted();
-
- _cache = GetClient().GetCache<int, Employee>(CacheName);
-
- for (int i = 0; i < Emps.Length; i++)
- _cache.Put(i, Emps[i]);
- }
-
/** <inheritDoc /> */
protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
{
- descs.Add(BenchmarkOperationDescriptor.Create("ThinClientGet", Get, 1));
+ descs.Add(BenchmarkOperationDescriptor.Create("GetAllEmployees", GetAll, 1));
}
/// <summary>
- /// Cache get.
+ /// Cache GetAll.
/// </summary>
- private void Get(BenchmarkState state)
+ private void GetAll(BenchmarkState state)
{
- var idx = BenchmarkUtils.GetRandomInt(Dataset);
+ var batchSize = Dataset / 10;
+ var idx = BenchmarkUtils.GetRandomInt(Dataset - batchSize);
+ var keys = Enumerable.Range(idx, batchSize);
- _cache.Get(idx);
+ Cache.GetAll(keys);
}
}
-}
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetBenchmark.cs
index 4af5f1f..3c2329e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetBenchmark.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/ThinClient/ThinClientGetBenchmark.cs
@@ -33,6 +33,14 @@ namespace Apache.Ignite.Benchmarks.ThinClient
/** Native cache wrapper. */
private ICacheClient<int, Employee> _cache;
+ /// <summary>
+ /// Gets the cache.
+ /// </summary>
+ public ICacheClient<int, Employee> Cache
+ {
+ get { return _cache; }
+ }
+
/** <inheritDoc /> */
protected override void OnStarted()
{
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj
index d9bcd17..ca23c78 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj
@@ -19,7 +19,7 @@
<DelaySign>false</DelaySign>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@@ -59,7 +59,19 @@
<Compile Include="..\Apache.Ignite.Core.Tests\Binary\JavaBinaryInteropTest.cs" Link="Binary\JavaBinaryInteropTest.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\AdvancedSerializationTest.cs" Link="Binary\Serializable\AdvancedSerializationTest.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\CallbacksTest.cs" Link="Binary\Serializable\CallbacksTest.cs" />
+ <Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\DynamicFieldSetSerializable.cs">
+ <Link>Binary\Serializable\DynamicFieldSetSerializable.cs</Link>
+ </Compile>
+ <Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\DynamicFieldSetTest.cs">
+ <Link>Binary\Serializable\DynamicFieldSetTest.cs</Link>
+ </Compile>
<Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\GenericCollectionsTest.cs" Link="Binary\Serializable\GenericCollectionsTest.cs" />
+ <Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\ObjectReferenceTests.cs">
+ <Link>Binary\Serializable\ObjectReferenceTests.cs</Link>
+ </Compile>
+ <Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\PrimitivesTest.cs">
+ <Link>Binary\Serializable\PrimitivesTest.cs</Link>
+ </Compile>
<Compile Include="..\Apache.Ignite.Core.Tests\Binary\Serializable\SqlDmlTest.cs" Link="Binary\Serializable\SqlDmlTest.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Cache\AddArgCacheEntryProcessor.cs" Link="Cache\AddArgCacheEntryProcessor.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Cache\BinarizableAddArgCacheEntryProcessor.cs" Link="Cache\BinarizableAddArgCacheEntryProcessor.cs" />
@@ -96,6 +108,12 @@
<Compile Include="..\Apache.Ignite.Core.Tests\Cache\Query\Linq\CacheLinqTestSimpleName.cs" Link="Cache\Query\Linq\CacheLinqTestSimpleName.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Cache\Query\Linq\CacheLinqTestSqlEscapeAll.cs" Link="Cache\Query\Linq\CacheLinqTestSqlEscapeAll.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Cache\TestReferenceObject.cs" Link="Cache\TestReferenceObject.cs" />
+ <Compile Include="..\Apache.Ignite.Core.Tests\Client\Cache\DynamicFieldSetTest.cs">
+ <Link>ThinClient\Cache\DynamicFieldSetTest.cs</Link>
+ </Compile>
+ <Compile Include="..\Apache.Ignite.Core.Tests\Client\Cache\SerializableObjectsTest.cs">
+ <Link>ThinClient\Cache\SerializableObjectsTest.cs</Link>
+ </Compile>
<Compile Include="..\Apache.Ignite.Core.Tests\Client\Cache\PartitionAwarenessTest.cs">
<Link>ThinClient\Cache\PartitionAwarenessTest.cs</Link>
</Compile>
@@ -137,6 +155,12 @@
<Compile Include="..\Apache.Ignite.Core.Tests\Client\ClientProtocolVersionTest.cs">
<Link>ThinClient\ClientProtocolVersionTest.cs</Link>
</Compile>
+ <Compile Include="..\Apache.Ignite.Core.Tests\Client\ClientServerCacheAdapter.cs">
+ <Link>ThinClient\ClientServerCacheAdapter.cs</Link>
+ </Compile>
+ <Compile Include="..\Apache.Ignite.Core.Tests\Client\ClientServerCacheAdapterExtensions.cs">
+ <Link>ThinClient\ClientServerCacheAdapterExtensions.cs</Link>
+ </Compile>
<Compile Include="..\Apache.Ignite.Core.Tests\Client\ClientTestBase.cs" Link="ThinClient\ClientTestBase.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Client\Cluster\ClientClusterGroupTests.cs" Link="ThinClient\Cluster\ClientClusterGroupTests.cs" />
<Compile Include="..\Apache.Ignite.Core.Tests\Client\Cluster\ClientClusterTests.cs" Link="ThinClient\Cluster\ClientClusterTests.cs" />
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 49d94f7..a824a18 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
@@ -107,7 +107,9 @@
<Compile Include="Binary\BinaryReaderWriterTest.cs" />
<Compile Include="Binary\BinarySelfTestSimpleName.cs" />
<Compile Include="Binary\EnumsTestOnline.cs" />
+ <Compile Include="Binary\Serializable\DynamicFieldSetSerializable.cs" />
<Compile Include="Binary\Serializable\GenericCollectionsTest.cs" />
+ <Compile Include="Binary\Serializable\DynamicFieldSetTest.cs" />
<Compile Include="Cache\Affinity\AffinityAttributeTest.cs" />
<Compile Include="Cache\CacheCreateTest.cs" />
<Compile Include="Cache\CacheQueryMetricsTest.cs" />
@@ -132,6 +134,8 @@
<Compile Include="Cache\Query\Linq\CacheLinqTest.Contains.cs" />
<Compile Include="Cache\Store\CacheStoreSessionTestCodeConfig.cs" />
<Compile Include="Cache\Store\CacheStoreSessionTestSharedFactory.cs" />
+ <Compile Include="Client\Cache\DynamicFieldSetTest.cs" />
+ <Compile Include="Client\Cache\SerializableObjectsTest.cs" />
<Compile Include="Client\Cache\PartitionAwarenessTest.cs" />
<Compile Include="Client\Cache\BinaryBuilderTest.cs" />
<Compile Include="Client\Cache\CacheClientAsyncWrapper.cs" />
@@ -155,6 +159,8 @@
<Compile Include="Client\ClientOpExtensionsTest.cs" />
<Compile Include="Client\ClientProtocolVersionTest.cs" />
<Compile Include="Client\ClientReconnectCompatibilityTest.cs" />
+ <Compile Include="Client\ClientServerCacheAdapter.cs" />
+ <Compile Include="Client\ClientServerCacheAdapterExtensions.cs" />
<Compile Include="Client\ClientServerCompatibilityTest.cs" />
<Compile Include="Client\ClientTestBase.cs" />
<Compile Include="Client\Cluster\ClientClusterGroupTests.cs" />
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DynamicFieldSetSerializable.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DynamicFieldSetSerializable.cs
new file mode 100644
index 0000000..6d127d2
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DynamicFieldSetSerializable.cs
@@ -0,0 +1,81 @@
+/*
+ * 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.Binary.Serializable
+{
+ using System.Runtime.Serialization;
+ using Apache.Ignite.Core.Tests.Client.Cache;
+
+ /// <summary>
+ /// Serializable class with dynamic field set: some fields are serialized based on a condition.
+ /// </summary>
+ public class DynamicFieldSetSerializable : ISerializable
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EmptyObject"/> class.
+ /// </summary>
+ public DynamicFieldSetSerializable()
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EmptyObject"/> class.
+ /// </summary>
+ // ReSharper disable once UnusedMember.Global
+ // ReSharper disable once UnusedParameter.Local
+ public DynamicFieldSetSerializable(SerializationInfo info, StreamingContext context)
+ {
+ WriteFoo = info.GetBoolean("WriteFoo");
+ if (WriteFoo)
+ {
+ Foo = info.GetInt32("Foo");
+ }
+
+ WriteBar = info.GetBoolean("WriteBar");
+ if (WriteBar)
+ {
+ Bar = info.GetString("Bar");
+ }
+ }
+
+ /** <inheritdoc /> */
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("WriteFoo", WriteFoo);
+ info.AddValue("WriteBar", WriteBar);
+
+ if (WriteFoo)
+ {
+ info.AddValue("Foo", Foo);
+ }
+
+ if (WriteBar)
+ {
+ info.AddValue("Bar", Bar);
+ }
+ }
+
+ public int Foo { get; set; }
+
+ public string Bar { get; set; }
+
+ public bool WriteFoo { get; set; }
+
+ public bool WriteBar { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DynamicFieldSetTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DynamicFieldSetTest.cs
new file mode 100644
index 0000000..9a6d156
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DynamicFieldSetTest.cs
@@ -0,0 +1,120 @@
+/*
+ * 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.Binary.Serializable
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests <see cref="DynamicFieldSetSerializable"/> serialization.
+ /// </summary>
+ public class DynamicFieldSetTest
+ {
+ /** */
+ private IIgnite _node1;
+
+ /** */
+ private IIgnite _node2;
+
+ /// <summary>
+ /// Sets up the test.
+ /// </summary>
+ [SetUp]
+ public void SetUp()
+ {
+ _node1 = Ignition.Start(TestUtils.GetTestConfiguration());
+
+ _node2 = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ AutoGenerateIgniteInstanceName = true
+ });
+ }
+
+ /// <summary>
+ /// Tears down the test.
+ /// </summary>
+ [TearDown]
+ public void TearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Tests that dynamically added and removed fields are deserialized correctly.
+ /// This verifies proper metadata and schema handling.
+ /// </summary>
+ [Test]
+ public void TestAddRemoveFieldsDynamically()
+ {
+ var cache1 = _node1.CreateCache<int, DynamicFieldSetSerializable>("c");
+ var cache2 = _node2.GetCache<int, DynamicFieldSetSerializable>("c");
+
+ // Put/get without optional fields.
+ var noFields = new DynamicFieldSetSerializable();
+ cache1[1] = noFields;
+
+ AssertExtensions.ReflectionEqual(noFields, cache1[1]);
+ AssertExtensions.ReflectionEqual(noFields, cache2[1]);
+
+ Assert.AreEqual(new[] {"WriteBar", "WriteFoo"}, GetFields(0));
+ Assert.AreEqual(new[] {"WriteBar", "WriteFoo"}, GetFields(1));
+
+ // Put/get with one optional field.
+ var oneField = new DynamicFieldSetSerializable
+ {
+ Bar = "abc",
+ WriteBar = true
+ };
+ cache1[2] = oneField;
+
+ AssertExtensions.ReflectionEqual(oneField, cache1[2]);
+ AssertExtensions.ReflectionEqual(oneField, cache2[2]);
+ Assert.AreEqual(new[] {"Bar", "WriteBar", "WriteFoo"}, GetFields(0));
+ Assert.AreEqual(new[] {"Bar", "WriteBar", "WriteFoo"}, GetFields(1));
+
+ // Put/get with another optional field.
+ var oneField2 = new DynamicFieldSetSerializable
+ {
+ Foo = 25,
+ WriteFoo = true
+ };
+ cache1[3] = oneField2;
+
+ AssertExtensions.ReflectionEqual(oneField2, cache1[3]);
+ AssertExtensions.ReflectionEqual(oneField2, cache2[3]);
+
+ Assert.AreEqual(new[] {"Bar", "Foo", "WriteBar", "WriteFoo"}, GetFields(0));
+ Assert.AreEqual(new[] {"Bar", "Foo", "WriteBar", "WriteFoo"}, GetFields(1));
+ }
+
+ /// <summary>
+ /// Gets the fields.
+ /// </summary>
+ private IEnumerable<string> GetFields(int nodeIndex)
+ {
+ var node = nodeIndex == 0 ? _node1 : _node2;
+
+ return node
+ .GetBinary()
+ .GetBinaryType(typeof(DynamicFieldSetSerializable))
+ .Fields
+ .OrderBy(f => f);
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs
index f61850c..eb8c985 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs
@@ -846,17 +846,22 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
[Test]
public void TestAsyncCompletionOrder()
{
- var cache = GetClientCache<int>();
- var cache2 = Client.GetOrCreateCache<int, int>("TestAsyncCompletionOrder");
+ var config = GetClientConfiguration();
+ config.SocketTimeout = TimeSpan.FromMinutes(2);
+ using (var client = Ignition.StartClient(config))
+ {
+ var cache = client.GetCache<int, int>(CacheName);
+ var cache2 = Client.GetOrCreateCache<int, int>("TestAsyncCompletionOrder");
- cache.PutAll(Enumerable.Range(1, 500000).Select(x => new KeyValuePair<int, int>(x, x)));
- var t1 = cache.RemoveAllAsync();
- var t2 = cache2.PutAsync(1, 1);
+ cache.PutAll(Enumerable.Range(1, 50000).Select(x => new KeyValuePair<int, int>(x, x)));
+ var t1 = cache.RemoveAllAsync();
+ var t2 = cache2.PutAsync(1, 1);
- t2.Wait();
- Assert.IsFalse(t1.IsCompleted);
+ t2.Wait();
+ Assert.IsFalse(t1.IsCompleted);
- t1.Wait();
+ t1.Wait();
+ }
}
/// <summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
index 0c72010..98c69f6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
@@ -98,12 +98,6 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
}
/** <inheritdoc /> */
- public int[] GetSchema(int typeId, int schemaId)
- {
- return null;
- }
-
- /** <inheritdoc /> */
public void PutBinaryTypes(ICollection<BinaryType> types)
{
// No-op.
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/DynamicFieldSetTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/DynamicFieldSetTest.cs
new file mode 100644
index 0000000..a781434
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/DynamicFieldSetTest.cs
@@ -0,0 +1,141 @@
+/*
+ * 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.Client.Cache
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using Apache.Ignite.Core.Tests.Binary.Serializable;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests <see cref="DynamicFieldSetSerializable"/> serialization in thin client.
+ /// </summary>
+ [TestFixture(true)]
+ [TestFixture(false)]
+ public class DynamicFieldSetTest : ClientTestBase
+ {
+ /** */
+ private readonly bool _clientToServer;
+
+ /// <summary>
+ /// Initializes a new instance of <see cref="DynamicFieldSetTest"/>.
+ /// </summary>
+ public DynamicFieldSetTest(bool clientToServer)
+ {
+ _clientToServer = clientToServer;
+ }
+
+ /// <summary>
+ /// Tests that dynamically added and removed fields are deserialized correctly.
+ /// This verifies proper metadata and schema handling.
+ /// </summary>
+ [Test]
+ public void TestAddRemoveFieldsDynamically()
+ {
+ var cache1 = Ignition.GetIgnite().GetOrCreateCache<int, DynamicFieldSetSerializable>("c").AsCacheClient();
+ var cache2 = Client.GetCache<int, DynamicFieldSetSerializable>("c");
+
+ if (_clientToServer)
+ {
+ // Swap caches to verify that metadata propagates both ways.
+ var tmp = cache1;
+ cache1 = cache2;
+ cache2 = tmp;
+ }
+
+ // Put/get without optional fields.
+ var noFields = new DynamicFieldSetSerializable();
+ cache1[1] = noFields;
+
+ AssertExtensions.ReflectionEqual(noFields, cache1[1]);
+ AssertExtensions.ReflectionEqual(noFields, cache2[1]);
+
+ Assert.AreEqual(new[] {"WriteBar", "WriteFoo"}, GetFieldsServer());
+ Assert.AreEqual(new[] {"WriteBar", "WriteFoo"}, GetFieldsClient());
+
+ // Put/get with one optional field.
+ var oneField = new DynamicFieldSetSerializable
+ {
+ Bar = "abc",
+ WriteBar = true
+ };
+ cache1[2] = oneField;
+
+ AssertExtensions.ReflectionEqual(oneField, cache1[2]);
+ AssertExtensions.ReflectionEqual(oneField, cache2[2]);
+ Assert.AreEqual(new[] {"Bar", "WriteBar", "WriteFoo"}, GetFieldsServer());
+ Assert.AreEqual(new[] {"Bar", "WriteBar", "WriteFoo"}, GetFieldsClient());
+
+ // Put/get with another optional field.
+ var oneField2 = new DynamicFieldSetSerializable
+ {
+ Foo = 25,
+ WriteFoo = true
+ };
+ cache1[3] = oneField2;
+
+ AssertExtensions.ReflectionEqual(oneField2, cache1[3]);
+ AssertExtensions.ReflectionEqual(oneField2, cache2[3]);
+
+ Assert.AreEqual(new[] {"Bar", "Foo", "WriteBar", "WriteFoo"}, GetFieldsServer());
+ Assert.AreEqual(new[] {"Bar", "Foo", "WriteBar", "WriteFoo"}, GetFieldsClient());
+
+ // Put/get with both optional fields.
+ var twoField = new DynamicFieldSetSerializable
+ {
+ Bar = "x",
+ Foo = 42,
+ WriteBar = true,
+ WriteFoo = true
+ };
+ cache1[4] = twoField;
+
+ AssertExtensions.ReflectionEqual(twoField, cache1[4]);
+ AssertExtensions.ReflectionEqual(twoField, cache2[4]);
+
+ // Re-check initial object without optional fields.
+ AssertExtensions.ReflectionEqual(noFields, cache1[1]);
+ AssertExtensions.ReflectionEqual(noFields, cache2[1]);
+ }
+
+ /// <summary>
+ /// Gets the fields.
+ /// </summary>
+ private IEnumerable<string> GetFieldsServer()
+ {
+ return Ignition
+ .GetIgnite()
+ .GetBinary()
+ .GetBinaryType(typeof(DynamicFieldSetSerializable))
+ .Fields
+ .OrderBy(f => f);
+ }
+
+ /// <summary>
+ /// Gets the fields.
+ /// </summary>
+ private IEnumerable<string> GetFieldsClient()
+ {
+ return Client
+ .GetBinary()
+ .GetBinaryType(typeof(DynamicFieldSetSerializable))
+ .Fields
+ .OrderBy(f => f);
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/PartitionAwarenessTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/PartitionAwarenessTest.cs
index f48afe3..6ffb473 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/PartitionAwarenessTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/PartitionAwarenessTest.cs
@@ -23,7 +23,6 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
using System.Globalization;
using System.Linq;
using System.Net;
- using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Client;
@@ -38,18 +37,16 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
public class PartitionAwarenessTest : ClientTestBase
{
/** */
- private const string NodeIndexAttr = "test-node-idx";
-
- /** */
- private readonly List<ListLogger> _loggers = new List<ListLogger>();
-
+ private const int ServerCount = 3;
+
/** */
private ICacheClient<int, int> _cache;
/// <summary>
/// Initializes a new instance of the <see cref="PartitionAwarenessTest"/> class.
/// </summary>
- public PartitionAwarenessTest() : base(3)
+ public PartitionAwarenessTest()
+ : base(ServerCount)
{
// No-op.
}
@@ -262,7 +259,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
_cache.Get(1);
_cache.Get(1);
- var requests = _loggers.SelectMany(GetCacheRequestNames).ToArray();
+ var requests = GetAllServerRequestNames(RequestNamePrefixCache);
var expectedRequests = new[]
{
@@ -291,11 +288,11 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
cache.Get(2);
cache.Get(3);
- var reqs = _loggers
- .Select(l => new {Logger = l, Requests = GetCacheRequestNames(l).ToArray()})
- .Where(r => r.Requests.Length > 0)
+ var reqs = GetLoggers()
+ .Select(l => GetServerRequestNames(l, RequestNamePrefixCache).ToArray())
+ .Where(x => x.Length > 0)
.ToArray();
-
+
// All requests should go to a single (default) node, because partition awareness is not applicable.
Assert.AreEqual(1, reqs.Length);
@@ -308,7 +305,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
"Get"
};
- Assert.AreEqual(expectedRequests, reqs[0].Requests);
+ Assert.AreEqual(expectedRequests, reqs[0]);
}
[Test]
@@ -432,20 +429,6 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
Assert.AreEqual(gridIdx, GetPrimaryNodeIdx(key));
}
- protected override IgniteConfiguration GetIgniteConfiguration()
- {
- var cfg = base.GetIgniteConfiguration();
-
- var index = _loggers.Count;
- cfg.UserAttributes = new Dictionary<string, object> {{NodeIndexAttr, index}};
-
- var logger = new ListLogger();
- cfg.Logger = logger;
- _loggers.Add(logger);
-
- return cfg;
- }
-
protected override IgniteClientConfiguration GetClientConfiguration()
{
var cfg = base.GetClientConfiguration();
@@ -463,9 +446,9 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
try
{
- for (var i = 0; i < _loggers.Count; i++)
+ for (var i = 0; i < ServerCount; i++)
{
- var requests = GetCacheRequestNames(_loggers[i]);
+ var requests = GetServerRequestNames(i, RequestNamePrefixCache);
if (requests.Contains(message))
{
@@ -481,27 +464,6 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
}
}
- private static IEnumerable<string> GetCacheRequestNames(ListLogger logger)
- {
- var messageRegex = new Regex(
- @"Client request received \[reqId=\d+, addr=/127.0.0.1:\d+, " +
- @"req=org.apache.ignite.internal.processors.platform.client.cache.ClientCache(\w+)Request@");
-
- return logger.Entries
- .Select(m => messageRegex.Match(m.Message))
- .Where(m => m.Success)
- .Select(m => m.Groups[1].Value);
- }
-
-
- private void ClearLoggers()
- {
- foreach (var logger in _loggers)
- {
- logger.Clear();
- }
- }
-
private void TestOperation(Action action, int expectedGridIdx, string message = null)
{
InitTestData();
@@ -528,8 +490,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
var idx = 0;
// GetAll is not ordered - sort the same way as _loggers.
- var ignites = Ignition.GetAll()
- .OrderBy(n => n.GetCluster().GetLocalNode().GetAttribute<int>(NodeIndexAttr));
+ var ignites = Ignition.GetAll().OrderBy(i => i.Name);
foreach (var ignite in ignites)
{
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/SerializableObjectsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/SerializableObjectsTest.cs
new file mode 100644
index 0000000..c3782a4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/SerializableObjectsTest.cs
@@ -0,0 +1,136 @@
+/*
+ * 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.Client.Cache
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Runtime.Serialization;
+ using Apache.Ignite.Core.Cache.Query;
+ using Apache.Ignite.Core.Client.Cache;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests <see cref="ISerializable"/> object handling in Thin Client.
+ /// </summary>
+ public class SerializableObjectsTest : ClientTestBase
+ {
+ /** */
+ private const int EntryCount = 50;
+
+ /** */
+ private static readonly int[] Keys = Enumerable.Range(0, EntryCount).ToArray();
+
+ /// <summary>
+ /// Tests DateTime metadata caching.
+ /// </summary>
+ [Test]
+ public void TestDateTimeMetaCachingOnPut([Values(true, false)] bool scanQuery)
+ {
+ var requestName = scanQuery ? "ClientCacheScanQuery" : "ClientCacheGetAll";
+ var cache = GetPopulatedCache();
+
+ var res = scanQuery
+ ? cache.Query(new ScanQuery<int, DateTimeTest>()).GetAll()
+ : cache.GetAll(Keys);
+
+ var requests = GetAllServerRequestNames().ToArray();
+
+ // Verify that only one request is sent to the server:
+ // metadata is already cached and should not be requested.
+ Assert.AreEqual(new[] {requestName}, requests);
+
+ // Verify results.
+ Assert.AreEqual(EntryCount, res.Count);
+ Assert.AreEqual(DateTimeTest.DefaultDateTime, res.Min(x => x.Value.Date));
+ }
+
+ /// <summary>
+ /// Tests DateTime metadata caching.
+ /// </summary>
+ [Test]
+ public void TestDateTimeMetaCachingOnGet([Values(true, false)] bool scanQuery)
+ {
+ // Retrieve data from a different client which does not yet have cached meta.
+ var requestName = scanQuery ? "ClientCacheScanQuery" : "ClientCacheGetAll";
+ var cache = GetClient().GetCache<int, DateTimeTest>(GetPopulatedCache().Name);
+
+ var res = scanQuery
+ ? cache.Query(new ScanQuery<int, DateTimeTest>()).GetAll()
+ : cache.GetAll(Keys);
+
+ var requests = GetAllServerRequestNames().ToArray();
+
+ // Verify that only one BinaryTypeGet request per type is sent to the server.
+ var expectedRequests = new[]
+ {
+ requestName,
+ "ClientBinaryTypeNameGet",
+ "ClientBinaryTypeGet",
+ "ClientBinaryTypeNameGet",
+ "ClientBinaryTypeGet"
+ };
+ Assert.AreEqual(expectedRequests, requests);
+
+ // Verify results.
+ Assert.AreEqual(EntryCount, res.Count);
+ Assert.AreEqual(DateTimeTest.DefaultDateTime, res.Min(x => x.Value.Date));
+ }
+
+ /// <summary>
+ /// Gets the populated cache.
+ /// </summary>
+ private ICacheClient<int, DateTimeTest> GetPopulatedCache()
+ {
+ var cacheName = TestContext.CurrentContext.Test.Name;
+ var cache = Client.GetOrCreateCache<int, DateTimeTest>(cacheName);
+ cache.PutAll(GetData().Select(x => new KeyValuePair<int, DateTimeTest>(x.Id, x)));
+
+ ClearLoggers();
+ return cache;
+ }
+
+ /// <summary>
+ /// Gets the data.
+ /// </summary>
+ private static IEnumerable<DateTimeTest> GetData()
+ {
+ return Keys
+ .Select(x => new DateTimeTest
+ {
+ Id = x,
+ Date = DateTimeTest.DefaultDateTime.AddHours(x),
+ });
+ }
+
+ /// <summary>
+ /// Test class with DateTime field.
+ /// </summary>
+ private class DateTimeTest
+ {
+ /** */
+ public static readonly DateTime DefaultDateTime = new DateTime(2002, 2, 2);
+
+ /** */
+ public int Id { get; set; }
+
+ /** */
+ public DateTime Date { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientServerCacheAdapter.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientServerCacheAdapter.cs
new file mode 100644
index 0000000..7e101dd
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientServerCacheAdapter.cs
@@ -0,0 +1,302 @@
+/*
+ * 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.
+ */
+
+#pragma warning disable 618
+namespace Apache.Ignite.Core.Tests.Client
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Expiry;
+ using Apache.Ignite.Core.Cache.Query;
+ using Apache.Ignite.Core.Client.Cache;
+
+ /// <summary>
+ /// Adapts <see cref="ICache{TK,TV}"/> to <see cref="ICacheClient{TK,TV}"/>
+ /// </summary>
+ public class ClientServerCacheAdapter<TK, TV> : ICacheClient<TK, TV>
+ {
+ private readonly ICache<TK, TV> _cache;
+
+ public ClientServerCacheAdapter(ICache<TK, TV> cache)
+ {
+ _cache = cache;
+ }
+
+ public string Name
+ {
+ get { return _cache.Name; }
+ }
+
+ public void Put(TK key, TV val)
+ {
+ _cache.Put(key, val);
+ }
+
+ public Task PutAsync(TK key, TV val)
+ {
+ return _cache.PutAsync(key, val);
+ }
+
+ public TV Get(TK key)
+ {
+ return _cache.Get(key);
+ }
+
+ public Task<TV> GetAsync(TK key)
+ {
+ return _cache.GetAsync(key);
+ }
+
+ public bool TryGet(TK key, out TV value)
+ {
+ return _cache.TryGet(key, out value);
+ }
+
+ public Task<CacheResult<TV>> TryGetAsync(TK key)
+ {
+ return _cache.TryGetAsync(key);
+ }
+
+ public ICollection<ICacheEntry<TK, TV>> GetAll(IEnumerable<TK> keys)
+ {
+ return _cache.GetAll(keys);
+ }
+
+ public Task<ICollection<ICacheEntry<TK, TV>>> GetAllAsync(IEnumerable<TK> keys)
+ {
+ return _cache.GetAllAsync(keys);
+ }
+
+ public TV this[TK key]
+ {
+ get { return _cache[key]; }
+ set { _cache[key] = value; }
+ }
+
+ public bool ContainsKey(TK key)
+ {
+ return _cache.ContainsKey(key);
+ }
+
+ public Task<bool> ContainsKeyAsync(TK key)
+ {
+ return _cache.ContainsKeyAsync(key);
+ }
+
+ public bool ContainsKeys(IEnumerable<TK> keys)
+ {
+ return _cache.ContainsKeys(keys);
+ }
+
+ public Task<bool> ContainsKeysAsync(IEnumerable<TK> keys)
+ {
+ return _cache.ContainsKeysAsync(keys);
+ }
+
+ public IQueryCursor<ICacheEntry<TK, TV>> Query(ScanQuery<TK, TV> scanQuery)
+ {
+ return _cache.Query(scanQuery);
+ }
+
+ public IQueryCursor<ICacheEntry<TK, TV>> Query(SqlQuery sqlQuery)
+ {
+ return _cache.Query(sqlQuery);
+ }
+
+ public IFieldsQueryCursor Query(SqlFieldsQuery sqlFieldsQuery)
+ {
+ return _cache.Query(sqlFieldsQuery);
+ }
+
+ public CacheResult<TV> GetAndPut(TK key, TV val)
+ {
+ return _cache.GetAndPut(key, val);
+ }
+
+ public Task<CacheResult<TV>> GetAndPutAsync(TK key, TV val)
+ {
+ return _cache.GetAndPutAsync(key, val);
+ }
+
+ public CacheResult<TV> GetAndReplace(TK key, TV val)
+ {
+ return _cache.GetAndReplace(key, val);
+ }
+
+ public Task<CacheResult<TV>> GetAndReplaceAsync(TK key, TV val)
+ {
+ return _cache.GetAndReplaceAsync(key, val);
+ }
+
+ public CacheResult<TV> GetAndRemove(TK key)
+ {
+ return _cache.GetAndRemove(key);
+ }
+
+ public Task<CacheResult<TV>> GetAndRemoveAsync(TK key)
+ {
+ return _cache.GetAndRemoveAsync(key);
+ }
+
+ public bool PutIfAbsent(TK key, TV val)
+ {
+ return _cache.PutIfAbsent(key, val);
+ }
+
+ public Task<bool> PutIfAbsentAsync(TK key, TV val)
+ {
+ return _cache.PutIfAbsentAsync(key, val);
+ }
+
+ public CacheResult<TV> GetAndPutIfAbsent(TK key, TV val)
+ {
+ return _cache.GetAndPutIfAbsent(key, val);
+ }
+
+ public Task<CacheResult<TV>> GetAndPutIfAbsentAsync(TK key, TV val)
+ {
+ return _cache.GetAndPutIfAbsentAsync(key, val);
+ }
+
+ public bool Replace(TK key, TV val)
+ {
+ return _cache.Replace(key, val);
+ }
+
+ public Task<bool> ReplaceAsync(TK key, TV val)
+ {
+ return _cache.ReplaceAsync(key, val);
+ }
+
+ public bool Replace(TK key, TV oldVal, TV newVal)
+ {
+ return _cache.Replace(key, oldVal, newVal);
+ }
+
+ public Task<bool> ReplaceAsync(TK key, TV oldVal, TV newVal)
+ {
+ return _cache.ReplaceAsync(key, oldVal, newVal);
+ }
+
+ public void PutAll(IEnumerable<KeyValuePair<TK, TV>> vals)
+ {
+ _cache.PutAll(vals);
+ }
+
+ public Task PutAllAsync(IEnumerable<KeyValuePair<TK, TV>> vals)
+ {
+ return _cache.PutAllAsync(vals);
+ }
+
+ public void Clear()
+ {
+ _cache.Clear();
+ }
+
+ public Task ClearAsync()
+ {
+ return _cache.ClearAsync();
+ }
+
+ public void Clear(TK key)
+ {
+ _cache.Clear(key);
+ }
+
+ public Task ClearAsync(TK key)
+ {
+ return _cache.ClearAsync(key);
+ }
+
+ public void ClearAll(IEnumerable<TK> keys)
+ {
+ _cache.ClearAll(keys);
+ }
+
+ public Task ClearAllAsync(IEnumerable<TK> keys)
+ {
+ return _cache.ClearAllAsync(keys);
+ }
+
+ public bool Remove(TK key)
+ {
+ return _cache.Remove(key);
+ }
+
+ public Task<bool> RemoveAsync(TK key)
+ {
+ return _cache.RemoveAsync(key);
+ }
+
+ public bool Remove(TK key, TV val)
+ {
+ return _cache.Remove(key, val);
+ }
+
+ public Task<bool> RemoveAsync(TK key, TV val)
+ {
+ return _cache.RemoveAsync(key, val);
+ }
+
+ public void RemoveAll(IEnumerable<TK> keys)
+ {
+ _cache.RemoveAll(keys);
+ }
+
+ public Task RemoveAllAsync(IEnumerable<TK> keys)
+ {
+ return _cache.RemoveAllAsync(keys);
+ }
+
+ public void RemoveAll()
+ {
+ _cache.RemoveAll();
+ }
+
+ public Task RemoveAllAsync()
+ {
+ return _cache.RemoveAllAsync();
+ }
+
+ public long GetSize(params CachePeekMode[] modes)
+ {
+ return _cache.GetSize(modes);
+ }
+
+ public Task<long> GetSizeAsync(params CachePeekMode[] modes)
+ {
+ throw new NotSupportedException();
+ }
+
+ public CacheClientConfiguration GetConfiguration()
+ {
+ throw new NotSupportedException();
+ }
+
+ public ICacheClient<TK1, TV1> WithKeepBinary<TK1, TV1>()
+ {
+ throw new NotSupportedException();
+ }
+
+ public ICacheClient<TK, TV> WithExpiryPolicy(IExpiryPolicy plc)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientServerCacheAdapterExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientServerCacheAdapterExtensions.cs
new file mode 100644
index 0000000..3cf52de
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientServerCacheAdapterExtensions.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.Tests.Client
+{
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Client.Cache;
+
+ /// <summary>
+ /// Extension methods related to <see cref="ClientServerCacheAdapter{TK, TV}"/>.
+ /// </summary>
+ public static class ClientServerCacheAdapterExtensions
+ {
+ /// <summary>
+ /// Returns given <see cref="ICache{TK,TV}"/> wrapped as <see cref="ICacheClient{TK,TV}"/>.
+ /// </summary>
+ public static ICacheClient<TK, TV> AsCacheClient<TK, TV>(this ICache<TK, TV> cache)
+ {
+ return new ClientServerCacheAdapter<TK, TV>(cache);
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
index d5d3ea3..c94eb54 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
@@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Tests.Client
using System.Collections.Generic;
using System.Linq;
using System.Net;
+ using System.Text.RegularExpressions;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache;
using Apache.Ignite.Core.Client;
@@ -38,6 +39,12 @@ namespace Apache.Ignite.Core.Tests.Client
/** Cache name. */
protected const string CacheName = "cache";
+ /** */
+ protected const string RequestNamePrefixCache = "cache.ClientCache";
+
+ /** */
+ protected const string RequestNamePrefixBinary = "binary.ClientBinary";
+
/** Grid count. */
private readonly int _gridCount = 1;
@@ -69,7 +76,7 @@ namespace Apache.Ignite.Core.Tests.Client
for (var i = 1; i < _gridCount; i++)
{
cfg = GetIgniteConfiguration();
- cfg.AutoGenerateIgniteInstanceName = true;
+ cfg.IgniteInstanceName = i.ToString();
Ignition.Start(cfg);
}
@@ -99,6 +106,8 @@ namespace Apache.Ignite.Core.Tests.Client
Assert.AreEqual(0, cache.GetSize(CachePeekMode.All));
Assert.AreEqual(0, GetClientCache<int>().GetSize(CachePeekMode.All));
+
+ ClearLoggers();
}
/// <summary>
@@ -156,7 +165,10 @@ namespace Apache.Ignite.Core.Tests.Client
/// </summary>
protected virtual IgniteConfiguration GetIgniteConfiguration()
{
- return TestUtils.GetTestConfiguration();
+ return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ Logger = new ListLogger()
+ };
}
/// <summary>
@@ -202,7 +214,7 @@ namespace Apache.Ignite.Core.Tests.Client
/// <summary>
/// Gets the logs.
/// </summary>
- protected List<ListLogger.Entry> GetLogs(IIgniteClient client)
+ protected static List<ListLogger.Entry> GetLogs(IIgniteClient client)
{
var igniteClient = (IgniteClient) client;
var logger = igniteClient.GetConfiguration().Logger;
@@ -211,6 +223,68 @@ namespace Apache.Ignite.Core.Tests.Client
}
/// <summary>
+ /// Gets client request names for a given server node.
+ /// </summary>
+ protected static IEnumerable<string> GetServerRequestNames(int serverIndex = 0, string prefix = null)
+ {
+ var instanceName = serverIndex == 0 ? null : serverIndex.ToString();
+ var grid = Ignition.GetIgnite(instanceName);
+ var logger = (ListLogger) grid.Logger;
+
+ return GetServerRequestNames(logger, prefix);
+ }
+
+ /// <summary>
+ /// Gets client request names from a given logger.
+ /// </summary>
+ protected static IEnumerable<string> GetServerRequestNames(ListLogger logger, string prefix = null)
+ {
+ // Full request class name examples:
+ // org.apache.ignite.internal.processors.platform.client.binary.ClientBinaryTypeGetRequest
+ // org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetRequest
+ var messageRegex = new Regex(
+ @"Client request received \[reqId=\d+, addr=/127.0.0.1:\d+, " +
+ @"req=org\.apache\.ignite\.internal\.processors\.platform\.client\..*?" +
+ prefix +
+ @"(\w+)Request@");
+
+ return logger.Entries
+ .Select(m => messageRegex.Match(m.Message))
+ .Where(m => m.Success)
+ .Select(m => m.Groups[1].Value);
+ }
+
+ /// <summary>
+ /// Gets client request names from all server nodes.
+ /// </summary>
+ protected static IEnumerable<string> GetAllServerRequestNames(string prefix = null)
+ {
+ return GetLoggers().SelectMany(l => GetServerRequestNames(l, prefix));
+ }
+
+ /// <summary>
+ /// Gets loggers from all server nodes.
+ /// </summary>
+ protected static IEnumerable<ListLogger> GetLoggers()
+ {
+ return Ignition.GetAll()
+ .OrderBy(i => i.Name)
+ .Select(i => i.Logger)
+ .Cast<ListLogger>();
+ }
+
+ /// <summary>
+ /// Clears loggers of all server nodes.
+ /// </summary>
+ protected static void ClearLoggers()
+ {
+ foreach (var logger in GetLoggers())
+ {
+ logger.Clear();
+ }
+ }
+
+ /// <summary>
/// Asserts the client configs are equal.
/// </summary>
public static void AssertClientConfigsAreEqual(CacheClientConfiguration cfg, CacheClientConfiguration cfg2)
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs
index 9802489..17830d8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs
@@ -298,7 +298,7 @@ namespace Apache.Ignite.Core.Tests.Client
[Test]
public void TestSchemaValidation()
{
- var xml = File.ReadAllText("Config\\Client\\IgniteClientConfiguration.xml");
+ var xml = File.ReadAllText(Path.Combine("Config", "Client", "IgniteClientConfiguration.xml"));
var xmlns = "http://ignite.apache.org/schema/dotnet/IgniteClientConfigurationSection";
var schemaFile = "IgniteClientConfigurationSection.xsd";
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
index b1930cf..1b4deb2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
@@ -411,7 +411,7 @@ namespace Apache.Ignite.Core
/// <summary>
/// Adds cache configuration template. Name should contain *.
- /// Template settins are applied to a cache created with <see cref="CreateCache{K,V}(string)"/> if specified
+ /// Template settings are applied to a cache created with <see cref="CreateCache{K,V}(string)"/> if specified
/// name matches the template name.
/// </summary>
/// <param name="configuration">Configuration.</param>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs
index 0a1b2d1..1a767be 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs
@@ -248,30 +248,6 @@ namespace Apache.Ignite.Core.Impl.Binary
return BinaryObjectHeader.Flag.None;
}
}
-
- /// <summary>
- /// Gets the field ids.
- /// </summary>
- private static int[] GetFieldIds(BinaryObjectHeader hdr, IIgniteInternal ignite)
- {
- Debug.Assert(hdr.TypeId != BinaryTypeId.Unregistered);
-
- int[] fieldIds = null;
-
- if (ignite != null)
- {
- fieldIds = ignite.BinaryProcessor.GetSchema(hdr.TypeId, hdr.SchemaId);
- }
-
- if (fieldIds == null)
- {
- throw new BinaryObjectException("Cannot find schema for object with compact footer [" +
- "typeId=" + hdr.TypeId + ", schemaId=" + hdr.SchemaId + ']');
- }
-
- return fieldIds;
- }
-
/// <summary>
/// Reads the schema, maintains stream position.
/// </summary>
@@ -307,6 +283,29 @@ namespace Apache.Ignite.Core.Impl.Binary
return res;
}
+ /// <summary>
+ /// Gets the field ids.
+ /// </summary>
+ private static int[] GetFieldIds(BinaryObjectHeader hdr, IIgniteInternal ignite)
+ {
+ Debug.Assert(hdr.TypeId != BinaryTypeId.Unregistered);
+
+ int[] fieldIds = null;
+
+ if (ignite != null)
+ {
+ fieldIds = GetCachedSchema(hdr, ignite) ??
+ ignite.Marshaller.GetBinaryType(hdr.TypeId).Schema.Get(hdr.SchemaId);
+ }
+
+ if (fieldIds == null)
+ {
+ throw new BinaryObjectException("Cannot find schema for object with compact footer [" +
+ "typeId=" + hdr.TypeId + ", schemaId=" + hdr.SchemaId + ']');
+ }
+
+ return fieldIds;
+ }
/// <summary>
/// Gets the field ids.
@@ -315,5 +314,19 @@ namespace Apache.Ignite.Core.Impl.Binary
{
return schema.Get(hdr.SchemaId) ?? GetFieldIds(hdr, ignite);
}
+
+ /// <summary>
+ /// Gets the cached schema.
+ /// </summary>
+ private static int[] GetCachedSchema(BinaryObjectHeader hdr, IIgniteInternal ignite)
+ {
+ var cachedHolder = ignite.Marshaller.GetCachedBinaryTypeHolder(hdr.TypeId);
+ if (cachedHolder == null || cachedHolder.BinaryType == null || cachedHolder.BinaryType.Schema == null)
+ {
+ return null;
+ }
+
+ return cachedHolder.BinaryType.Schema.Get(hdr.SchemaId);
+ }
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
index 318fd07..b62977a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
@@ -32,13 +32,16 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
private enum Op
{
+ // ReSharper disable UnusedMember.Local
GetMeta = 1,
GetAllMeta = 2,
PutMeta = 3,
GetSchema = 4,
RegisterType = 5,
GetType = 6,
- RegisterEnum = 7
+ RegisterEnum = 7,
+ GetMetaWithSchemas = 8
+ // ReSharper restore UnusedMember.Local
}
/// <summary>
@@ -55,13 +58,13 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
public BinaryType GetBinaryType(int typeId)
{
- return DoOutInOp((int) Op.GetMeta,
+ return DoOutInOp((int) Op.GetMetaWithSchemas,
writer => writer.WriteInt(typeId),
stream =>
{
var reader = Marshaller.StartUnmarshal(stream, false);
- return reader.ReadBoolean() ? new BinaryType(reader) : null;
+ return reader.ReadBoolean() ? new BinaryType(reader, true) : null;
}
);
}
@@ -87,18 +90,6 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Gets the schema.
- /// </summary>
- public int[] GetSchema(int typeId, int schemaId)
- {
- return DoOutInOp<int[]>((int) Op.GetSchema, writer =>
- {
- writer.WriteInt(typeId);
- writer.WriteInt(schemaId);
- });
- }
-
- /// <summary>
/// Put binary types to Grid.
/// </summary>
/// <param name="types">Binary types.</param>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs
index 9e0ce75..8ef84c1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs
@@ -59,12 +59,6 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- public int[] GetSchema(int typeId, int schemaId)
- {
- return GetBinaryType(typeId).Schema.Get(schemaId);
- }
-
- /** <inheritdoc /> */
public void PutBinaryTypes(ICollection<BinaryType> types)
{
Debug.Assert(types != null);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
index 2d8604a..9e7d8ef 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
@@ -732,7 +732,7 @@ namespace Apache.Ignite.Core.Impl.Binary
"No matching type found for object [typeId={0}, typeName={1}]. " +
"This usually indicates that assembly with specified type is not loaded on a node. " +
"When using Apache.Ignite.exe, make sure to load assemblies with -assembly parameter. " +
- "Alternatively, set IgniteConfiguration.PeerAssemblyLoadingEnabled to true.",
+ "Alternatively, set IgniteConfiguration.PeerAssemblyLoadingMode to CurrentAppDomain.",
desc.TypeId, desc.TypeName));
}
@@ -867,6 +867,14 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Gets the schema for the current object, if any.
+ /// </summary>
+ public int[] Schema
+ {
+ get { return _frame.Schema; }
+ }
+
+ /// <summary>
/// Seeks to raw data.
/// </summary>
internal void SeekToRaw()
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs
index c626c76..fed78c3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryProcessor.cs
@@ -37,11 +37,6 @@ namespace Apache.Ignite.Core.Impl.Binary
List<IBinaryType> GetBinaryTypes();
/// <summary>
- /// Gets the schema.
- /// </summary>
- int[] GetSchema(int typeId, int schemaId);
-
- /// <summary>
/// Put binary types to Grid.
/// </summary>
/// <param name="types">Binary types.</param>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
index e1cc98f..be7d61b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -276,12 +276,16 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <returns>Metadata or null.</returns>
public BinaryType GetBinaryType(int typeId)
{
+ // NOTE: This method results can't (easily) be cached because binary metadata is changing on the fly:
+ // New fields and enum values can be added.
if (Ignite != null)
{
var meta = Ignite.BinaryProcessor.GetBinaryType(typeId);
if (meta != null)
{
+ UpdateOrCreateBinaryTypeHolder(meta);
+
return meta;
}
}
@@ -290,6 +294,20 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Gets cached metadata for the given type ID.
+ /// NOTE: Returned value is potentially stale.
+ /// Caller is responsible for refreshing the value as needed by invoking <see cref="GetBinaryType"/>.
+ /// </summary>
+ /// <param name="typeId">Type ID.</param>
+ /// <returns>Metadata or null.</returns>
+ public BinaryTypeHolder GetCachedBinaryTypeHolder(int typeId)
+ {
+ BinaryTypeHolder holder;
+ _metas.TryGetValue(typeId, out holder);
+ return holder;
+ }
+
+ /// <summary>
/// Puts the binary type metadata to Ignite.
/// </summary>
/// <param name="desc">Descriptor.</param>
@@ -314,37 +332,80 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <returns>Binary type handler.</returns>
public IBinaryTypeHandler GetBinaryTypeHandler(IBinaryTypeDescriptor desc)
{
- BinaryTypeHolder holder;
+ var holder = GetBinaryTypeHolder(desc);
+
+ if (holder != null)
+ {
+ ICollection<int> ids = holder.GetFieldIds();
+
+ bool newType = ids.Count == 0 && !holder.IsSaved;
+
+ return new BinaryTypeHashsetHandler(ids, newType);
+ }
- if (!_metas.TryGetValue(desc.TypeId, out holder))
+ return null;
+ }
+
+ /// <summary>
+ /// Gets the binary type holder.
+ /// </summary>
+ /// <param name="desc">Descriptor.</param>
+ /// <returns>Holder</returns>
+ private BinaryTypeHolder GetBinaryTypeHolder(IBinaryTypeDescriptor desc)
+ {
+ BinaryTypeHolder holder;
+ if (_metas.TryGetValue(desc.TypeId, out holder))
+ {
+ return holder;
+ }
+
+ lock (this)
{
- lock (this)
+ if (!_metas.TryGetValue(desc.TypeId, out holder))
{
- if (!_metas.TryGetValue(desc.TypeId, out holder))
- {
- IDictionary<int, BinaryTypeHolder> metas0 =
- new Dictionary<int, BinaryTypeHolder>(_metas);
+ var metas0 = new Dictionary<int, BinaryTypeHolder>(_metas);
- holder = new BinaryTypeHolder(desc.TypeId, desc.TypeName, desc.AffinityKeyFieldName,
- desc.IsEnum, this);
+ holder = new BinaryTypeHolder(desc.TypeId, desc.TypeName, desc.AffinityKeyFieldName,
+ desc.IsEnum, this);
- metas0[desc.TypeId] = holder;
+ metas0[desc.TypeId] = holder;
- _metas = metas0;
- }
+ _metas = metas0;
}
}
- if (holder != null)
+ return holder;
+ }
+
+ /// <summary>
+ /// Updates or creates cached binary type holder.
+ /// </summary>
+ private void UpdateOrCreateBinaryTypeHolder(BinaryType meta)
+ {
+ BinaryTypeHolder holder;
+ if (_metas.TryGetValue(meta.TypeId, out holder))
{
- ICollection<int> ids = holder.GetFieldIds();
+ holder.Merge(meta);
+ return;
+ }
+
+ lock (this)
+ {
+ if (_metas.TryGetValue(meta.TypeId, out holder))
+ {
+ holder.Merge(meta);
+ return;
+ }
+
+ var metas0 = new Dictionary<int, BinaryTypeHolder>(_metas);
- bool newType = ids.Count == 0 && !holder.Saved();
+ holder = new BinaryTypeHolder(meta.TypeId, meta.TypeName, meta.AffinityKeyFieldName, meta.IsEnum, this);
+ holder.Merge(meta);
- return new BinaryTypeHashsetHandler(ids, newType);
- }
+ metas0[meta.TypeId] = holder;
- return null;
+ _metas = metas0;
+ }
}
/// <summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs
index 06794b5..dae0171 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs
@@ -32,7 +32,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
{
/** Empty metadata. */
public static readonly BinaryType Empty =
- new BinaryType(BinaryTypeId.Object, BinaryTypeNames.TypeNameObject, null, null, false, null, null);
+ new BinaryType(BinaryTypeId.Object, BinaryTypeNames.TypeNameObject, null, null, false, null, null, null);
/** Empty dictionary. */
private static readonly IDictionary<string, BinaryField> EmptyDict = new Dictionary<string, BinaryField>();
@@ -196,7 +196,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
public BinaryType(IBinaryTypeDescriptor desc, Marshaller marshaller,
IDictionary<string, BinaryField> fields = null)
: this (desc.TypeId, desc.TypeName, fields, desc.AffinityKeyFieldName, desc.IsEnum,
- GetEnumValues(desc), marshaller)
+ GetEnumValues(desc), marshaller, null)
{
_descriptor = desc;
}
@@ -211,8 +211,10 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
/// <param name="isEnum">Enum flag.</param>
/// <param name="enumValues">Enum values.</param>
/// <param name="marshaller">Marshaller.</param>
+ /// <param name="schema"></param>
public BinaryType(int typeId, string typeName, IDictionary<string, BinaryField> fields,
- string affKeyFieldName, bool isEnum, IDictionary<string, int> enumValues, Marshaller marshaller)
+ string affKeyFieldName, bool isEnum, IDictionary<string, int> enumValues, Marshaller marshaller,
+ BinaryObjectSchema schema)
{
_typeId = typeId;
_typeName = typeName;
@@ -227,6 +229,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
}
_marshaller = marshaller;
+ _schema = schema;
}
/// <summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs
index 7e1e970..d9426b9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs
@@ -68,19 +68,27 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
}
/// <summary>
- /// Get saved flag.
+ /// Gets saved flag.
/// </summary>
- /// <returns>True if type metadata was saved at least once.</returns>
- public bool Saved()
+ /// <value>True if type metadata was saved at least once.</value>
+ public bool IsSaved
{
- return _saved;
+ get { return _saved; }
+ }
+
+ /// <summary>
+ /// Gets the cached binary type metadata.
+ /// </summary>
+ public BinaryType BinaryType
+ {
+ get { return _meta; }
}
/// <summary>
/// Currently cached field IDs.
/// </summary>
/// <returns>Cached field IDs.</returns>
- public ICollection<int> GetFieldIds()
+ public HashSet<int> GetFieldIds()
{
var ids0 = _ids;
@@ -134,24 +142,51 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
// 2. Add new fields.
foreach (var fieldMeta in fieldsMap)
{
- int fieldId = BinaryUtils.FieldId(meta.TypeId, fieldMeta.Key, null, null);
-
- if (!newIds.Contains(fieldId))
- {
- newIds.Add(fieldId);
- }
+ var fieldId = fieldMeta.Value.FieldId;
- if (!newFields.ContainsKey(fieldMeta.Key))
- {
- newFields[fieldMeta.Key] = fieldMeta.Value;
- }
+ newIds.Add(fieldId);
+ newFields[fieldMeta.Key] = fieldMeta.Value;
}
+
+ // 3. Merge schema.
+ var schema = MergeSchemas(meta0, meta);
- // 3. Assign new meta. Order is important here: meta must be assigned before field IDs.
+ // 4. Assign new meta. Order is important here: meta must be assigned before field IDs.
_meta = new BinaryType(_typeId, _typeName, newFields, _affKeyFieldName, _isEnum,
- meta.EnumValuesMap, _marshaller);
+ meta.EnumValuesMap, _marshaller, schema);
+
_ids = newIds;
}
}
+
+ /// <summary>
+ /// Merges schemas from two binary types.
+ /// </summary>
+ private static BinaryObjectSchema MergeSchemas(BinaryType a, BinaryType b)
+ {
+ if (a == null || a.Schema == null)
+ {
+ return b.Schema;
+ }
+
+ if (b == null || b.Schema == null)
+ {
+ return a.Schema;
+ }
+
+ var res = new BinaryObjectSchema();
+
+ foreach (var schema in a.Schema.GetAll())
+ {
+ res.Add(schema.Key, schema.Value);
+ }
+
+ foreach (var schema in b.Schema.GetAll())
+ {
+ res.Add(schema.Key, schema.Value);
+ }
+
+ return res;
+ }
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
index e597382..2d87a1f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
@@ -251,15 +251,40 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
private static IEnumerable<string> GetBinaryTypeFields(BinaryReader reader, IBinaryTypeDescriptor desc)
{
- var binaryType = reader.Marshaller.GetBinaryType(desc.TypeId);
-
- if (binaryType == BinaryType.Empty)
+ var schema = reader.Schema;
+ if (schema == null || schema.Length == 0)
{
- // Object without fields.
return Enumerable.Empty<string>();
}
- return binaryType.Fields;
+ // Try using cached metadata: if all fields from current schema are present there, we are good.
+ // Any extra fields that may have been added to the binary type are not present in the current object.
+ var binaryTypeHolder = reader.Marshaller.GetCachedBinaryTypeHolder(desc.TypeId);
+ if (binaryTypeHolder != null && HasAllFields(binaryTypeHolder, schema))
+ {
+ return binaryTypeHolder.BinaryType.Fields ?? Enumerable.Empty<string>();
+ }
+
+ // Cached metadata is not present or out of date: request latest (expensive operation).
+ return reader.Marshaller.GetBinaryType(desc.TypeId).Fields ?? Enumerable.Empty<string>();
+ }
+
+ /// <summary>
+ /// Checks whether all field ids from provided schema are present in the given binary type.
+ /// </summary>
+ private static bool HasAllFields(BinaryTypeHolder binaryTypeHolder, int[] schema)
+ {
+ var fieldIds = binaryTypeHolder.GetFieldIds();
+
+ foreach (var fieldId in schema)
+ {
+ if (!fieldIds.Contains(fieldId))
+ {
+ return false;
+ }
+ }
+
+ return true;
}
/// <summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite.DotNetCore.sln b/modules/platforms/dotnet/Apache.Ignite.DotNetCore.sln
index 3724eab..9f3e788 100644
--- a/modules/platforms/dotnet/Apache.Ignite.DotNetCore.sln
+++ b/modules/platforms/dotnet/Apache.Ignite.DotNetCore.sln
@@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apache.Ignite.Core.Tests.Do
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.DotNetCore", "Apache.Ignite\Apache.Ignite.DotNetCore.csproj", "{A28AA3F7-BA2B-49C2-B5DA-02707D4470B1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Benchmarks.DotNetCore", "Apache.Ignite.Benchmarks\Apache.Ignite.Benchmarks.DotNetCore.csproj", "{4344AEB8-6772-4625-9445-2C4A224B7716}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -33,6 +35,10 @@ Global
{A28AA3F7-BA2B-49C2-B5DA-02707D4470B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A28AA3F7-BA2B-49C2-B5DA-02707D4470B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A28AA3F7-BA2B-49C2-B5DA-02707D4470B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4344AEB8-6772-4625-9445-2C4A224B7716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4344AEB8-6772-4625-9445-2C4A224B7716}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4344AEB8-6772-4625-9445-2C4A224B7716}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4344AEB8-6772-4625-9445-2C4A224B7716}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/modules/platforms/dotnet/README.md b/modules/platforms/dotnet/README.md
index 4830940..319ccb5 100644
--- a/modules/platforms/dotnet/README.md
+++ b/modules/platforms/dotnet/README.md
@@ -2,11 +2,7 @@
<a href="https://ignite.apache.org/"><img src="https://ignite.apache.org/images/logo3.png" hspace="20"/></a><img src="https://ptupitsyn.github.io/images/net-framework.png" hspace="20" />
-<a href="https://www.nuget.org/packages?q=Apache.Ignite"><img src="https://img.shields.io/nuget/v/Apache.Ignite.svg" /></a>
-
-<a href="https://www.myget.org/gallery/apache-ignite-net-nightly"><img src="https://img.shields.io/myget/apache-ignite-net-nightly/vpre/Apache.Ignite.svg" /></a>
-
-<a href="https://ci.ignite.apache.org/viewType.html?buildTypeId=IgniteTests24Java8_IgnitePlatformNet&branch_IgniteTests24Java8=<default>"><img src="http://ci.ignite.apache.org/app/rest/builds/buildType:(id:IgniteTests24Java8_IgnitePlatformNet)/statusIcon" /></a>
+<a href="https://www.nuget.org/packages?q=GridGain.Ignite"><img src="https://img.shields.io/nuget/v/GridGain.Ignite.svg" /></a>
## Getting Started