You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/11/21 12:10:10 UTC
[16/47] ignite git commit: IGNITE-6896 .NET: support Multidimensional
Arrays in binary serializer
IGNITE-6896 .NET: support Multidimensional Arrays in binary serializer
This closes #3031
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fa52789d
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fa52789d
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fa52789d
Branch: refs/heads/ignite-zk
Commit: fa52789d7679d4c4b65efcdfb86cf146abb920fe
Parents: f992386
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Nov 15 15:47:58 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Nov 15 15:47:58 2017 +0300
----------------------------------------------------------------------
.../Binary/BinarySelfTest.cs | 88 +++++++++++++
.../Apache.Ignite.Core.csproj | 2 +
.../Impl/Binary/BinaryReflectiveActions.cs | 16 +++
.../Impl/Binary/BinarySystemHandlers.cs | 13 +-
.../Impl/Binary/BinaryUtils.cs | 41 +++++-
.../Impl/Binary/Marshaller.cs | 1 +
.../Impl/Binary/MultidimensionalArrayHolder.cs | 132 +++++++++++++++++++
.../Binary/MultidimensionalArraySerializer.cs | 48 +++++++
8 files changed, 330 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
index 3ec1e8c..6ffce38 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
@@ -1532,6 +1532,58 @@ namespace Apache.Ignite.Core.Tests.Binary
}
/// <summary>
+ /// Tests the jagged arrays.
+ /// </summary>
+ [Test]
+ public void TestJaggedArrays()
+ {
+ int[][] ints = {new[] {1, 2, 3}, new[] {4, 5, 6}};
+ Assert.AreEqual(ints, TestUtils.SerializeDeserialize(ints));
+
+ uint[][][] uints = {new[] {new uint[] {1, 2, 3}, new uint[] {4, 5}}};
+ Assert.AreEqual(uints, TestUtils.SerializeDeserialize(uints));
+
+ PropertyType[][][] objs = {new[] {new[] {new PropertyType {Field1 = 42}}}};
+ Assert.AreEqual(42, TestUtils.SerializeDeserialize(objs)[0][0][0].Field1);
+
+ var obj = new MultidimArrays { JaggedInt = ints, JaggedUInt = uints };
+ var resObj = TestUtils.SerializeDeserialize(obj);
+ Assert.AreEqual(obj.JaggedInt, resObj.JaggedInt);
+ Assert.AreEqual(obj.JaggedUInt, resObj.JaggedUInt);
+
+ var obj2 = new MultidimArraysBinarizable { JaggedInt = ints, JaggedUInt = uints };
+ var resObj2 = TestUtils.SerializeDeserialize(obj);
+ Assert.AreEqual(obj2.JaggedInt, resObj2.JaggedInt);
+ Assert.AreEqual(obj2.JaggedUInt, resObj2.JaggedUInt);
+ }
+
+ /// <summary>
+ /// Tests the multidimensional arrays.
+ /// </summary>
+ [Test]
+ public void TestMultidimensionalArrays()
+ {
+ int[,] ints = {{1, 2, 3}, {4, 5, 6}};
+ Assert.AreEqual(ints, TestUtils.SerializeDeserialize(ints));
+
+ uint[,,] uints = {{{1, 2, 3}, {4, 5, 6}}, {{7, 8, 9}, {10, 11, 12}}};
+ Assert.AreEqual(uints, TestUtils.SerializeDeserialize(uints));
+
+ PropertyType[,] objs = {{new PropertyType {Field1 = 123}}};
+ Assert.AreEqual(123, TestUtils.SerializeDeserialize(objs)[0, 0].Field1);
+
+ var obj = new MultidimArrays { MultidimInt = ints, MultidimUInt = uints };
+ var resObj = TestUtils.SerializeDeserialize(obj);
+ Assert.AreEqual(obj.MultidimInt, resObj.MultidimInt);
+ Assert.AreEqual(obj.MultidimUInt, resObj.MultidimUInt);
+
+ var obj2 = new MultidimArraysBinarizable { MultidimInt = ints, MultidimUInt = uints };
+ var resObj2 = TestUtils.SerializeDeserialize(obj);
+ Assert.AreEqual(obj2.MultidimInt, resObj2.MultidimInt);
+ Assert.AreEqual(obj2.MultidimUInt, resObj2.MultidimUInt);
+ }
+
+ /// <summary>
/// Tests the compact footer setting.
/// </summary>
[Test]
@@ -2604,5 +2656,41 @@ namespace Apache.Ignite.Core.Tests.Binary
return !left.Equals(right);
}
}
+
+ private class MultidimArrays
+ {
+ public int[][] JaggedInt { get; set; }
+ public uint[][][] JaggedUInt { get; set; }
+
+ public int[,] MultidimInt { get; set; }
+ public uint[,,] MultidimUInt { get; set; }
+ }
+
+ private class MultidimArraysBinarizable : IBinarizable
+ {
+ public int[][] JaggedInt { get; set; }
+ public uint[][][] JaggedUInt { get; set; }
+
+ public int[,] MultidimInt { get; set; }
+ public uint[,,] MultidimUInt { get; set; }
+
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ writer.WriteObject("JaggedInt", JaggedInt);
+ writer.WriteObject("JaggedUInt", JaggedUInt);
+
+ writer.WriteObject("MultidimInt", MultidimInt);
+ writer.WriteObject("MultidimUInt", MultidimUInt);
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ JaggedInt = reader.ReadObject<int[][]>("JaggedInt");
+ JaggedUInt = reader.ReadObject<uint[][][]>("JaggedUInt");
+
+ MultidimInt = reader.ReadObject<int[,]>("MultidimInt");
+ MultidimUInt = reader.ReadObject<uint[,,]>("MultidimUInt");
+ }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/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 165a57e..8a32583 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -116,6 +116,8 @@
<Compile Include="Configuration\WalMode.cs" />
<Compile Include="Impl\Binary\BinaryTypeId.cs" />
<Compile Include="Impl\Binary\IBinaryRawWriteAware.cs" />
+ <Compile Include="Impl\Binary\MultidimensionalArrayHolder.cs" />
+ <Compile Include="Impl\Binary\MultidimensionalArraySerializer.cs" />
<Compile Include="Impl\Client\Cache\CacheFlags.cs" />
<Compile Include="Impl\Client\Cache\Query\ClientQueryCursor.cs" />
<Compile Include="Impl\Cache\Query\PlatformQueryQursorBase.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
index 97964cf..a8ea9f1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
@@ -121,7 +121,9 @@ namespace Apache.Ignite.Core.Impl.Binary
if (type.IsPrimitive)
HandlePrimitive(field, out writeAction, out readAction, raw);
else if (type.IsArray)
+ {
HandleArray(field, out writeAction, out readAction, raw);
+ }
else
HandleOther(field, out writeAction, out readAction, raw, forceTimestamp);
}
@@ -252,6 +254,20 @@ namespace Apache.Ignite.Core.Impl.Binary
private static void HandleArray(FieldInfo field, out BinaryReflectiveWriteAction writeAction,
out BinaryReflectiveReadAction readAction, bool raw)
{
+ if (field.FieldType.GetArrayRank() > 1)
+ {
+ writeAction = raw
+ ? GetRawWriter<Array>(field, (w, o) => w.WriteObject(
+ o == null ? null : new MultidimensionalArrayHolder(o)))
+ : GetWriter<Array>(field, (f, w, o) => w.WriteObject(f,
+ o == null ? null : new MultidimensionalArrayHolder(o)));
+ readAction = raw
+ ? GetRawReader(field, r => r.ReadObject<object>())
+ : GetReader(field, (f, r) => r.ReadObject<object>(f));
+
+ return;
+ }
+
Type elemType = field.FieldType.GetElementType();
if (elemType == typeof (bool))
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/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 3f16bc0..430b426 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
@@ -178,6 +178,13 @@ namespace Apache.Ignite.Core.Impl.Binary
if (type.IsArray)
{
+ if (type.GetArrayRank() > 1)
+ {
+ // int[,]-style arrays are wrapped, see comments in holder.
+ return new BinarySystemWriteHandler<Array>(
+ (w, o) => w.WriteObject(new MultidimensionalArrayHolder(o)), true);
+ }
+
// We know how to write any array type.
Type elemType = type.GetElementType();
@@ -491,11 +498,7 @@ namespace Apache.Ignite.Core.Impl.Binary
{
// Infer element type from typeId.
var typeId = ctx.ReadInt();
-
- if (typeId != BinaryUtils.ObjTypeId)
- {
- elemType = ctx.Marshaller.GetDescriptor(true, typeId, true).Type;
- }
+ elemType = BinaryUtils.GetArrayElementType(typeId, ctx.Marshaller);
return BinaryUtils.ReadTypedArray(ctx, false, elemType ?? typeof(object));
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
index 20fea02..3123c07 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -1024,6 +1024,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public static void WriteArray(Array val, BinaryWriter ctx, int? elemTypeId = null)
{
Debug.Assert(val != null && ctx != null);
+ Debug.Assert(val.Rank == 1);
IBinaryStream stream = ctx.Stream;
@@ -1034,18 +1035,15 @@ namespace Apache.Ignite.Core.Impl.Binary
else
{
var elemType = val.GetType().GetElementType();
-
Debug.Assert(elemType != null);
- var typeId = ObjTypeId;
-
- if (elemType != typeof(object))
- typeId = ctx.Marshaller.GetDescriptor(elemType).TypeId;
-
+ var typeId = GetArrayElementTypeId(val, ctx.Marshaller);
stream.WriteInt(typeId);
if (typeId == BinaryTypeId.Unregistered)
+ {
ctx.WriteString(elemType.FullName);
+ }
}
stream.WriteInt(val.Length);
@@ -1055,6 +1053,37 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Gets the array element type identifier.
+ /// </summary>
+ public static int GetArrayElementTypeId(Array val, Marshaller marsh)
+ {
+ var elemType = val.GetType().GetElementType();
+ Debug.Assert(elemType != null);
+
+ return GetArrayElementTypeId(elemType, marsh);
+ }
+
+ /// <summary>
+ /// Gets the array element type identifier.
+ /// </summary>
+ public static int GetArrayElementTypeId(Type elemType, Marshaller marsh)
+ {
+ return elemType == typeof(object)
+ ? ObjTypeId
+ : marsh.GetDescriptor(elemType).TypeId;
+ }
+
+ /// <summary>
+ /// Gets the type of the array element.
+ /// </summary>
+ public static Type GetArrayElementType(int typeId, Marshaller marsh)
+ {
+ return typeId == ObjTypeId
+ ? typeof(object)
+ : marsh.GetDescriptor(true, typeId, true).Type;
+ }
+
+ /// <summary>
/// Read array.
/// </summary>
/// <param name="ctx">Read context.</param>
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
----------------------------------------------------------------------
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 7212cd6..0a7b54c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -725,6 +725,7 @@ namespace Apache.Ignite.Core.Impl.Binary
AddSystemType(0, r => new AssemblyRequest(r));
AddSystemType(0, r => new AssemblyRequestResult(r));
AddSystemType<PeerLoadingObjectHolder>(0, null, serializer: new PeerLoadingObjectHolderSerializer());
+ AddSystemType<MultidimensionalArrayHolder>(0, null, serializer: new MultidimensionalArraySerializer());
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs
new file mode 100644
index 0000000..f9f8df3
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs
@@ -0,0 +1,132 @@
+/*
+ * 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;
+ using System.Collections;
+ using System.Diagnostics;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Impl.Deployment;
+
+ /// <summary>
+ /// Wrapper for multidimensional arrays (int[,] -style).
+ /// <para />
+ /// Jagged arrays (int[][]) are fully supported by the engine and are interoperable with Java.
+ /// However, there is no int[,]-style arrays in Java, and there is no way to support them in a generic way.
+ /// So we have to wrap them inside an object (so it looks like a BinaryObject in Java).
+ /// </summary>
+ internal sealed class MultidimensionalArrayHolder : IBinaryWriteAware
+ {
+ /** Object. */
+ private readonly Array _array;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PeerLoadingObjectHolder"/> class.
+ /// </summary>
+ /// <param name="o">The object.</param>
+ public MultidimensionalArrayHolder(Array o)
+ {
+ Debug.Assert(o != null);
+ Debug.Assert(o.Rank > 1);
+
+ _array = o;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MultidimensionalArrayHolder"/> class.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public MultidimensionalArrayHolder(BinaryReader reader)
+ {
+ var typeId = reader.ReadInt();
+ var type = BinaryUtils.GetArrayElementType(typeId, reader.Marshaller);
+
+ var rank = reader.ReadInt();
+ var lengths = new int[rank];
+ var totalLen = 1;
+
+ for (var i = 0; i < rank; i++)
+ {
+ var len = reader.ReadInt();
+ lengths[i] = len;
+ totalLen *= len;
+ }
+
+ _array = System.Array.CreateInstance(type, lengths);
+
+ for (var i = 0; i < totalLen; i++)
+ {
+ var obj = reader.ReadObject<object>();
+ var idx = GetIndices(i, lengths);
+
+ _array.SetValue(Convert.ChangeType(obj, type), idx);
+ }
+ }
+
+ /// <summary>
+ /// Gets the indices in a multidimensional array from a global index.
+ /// </summary>
+ private static int[] GetIndices(int globalIdx, int[] lengths)
+ {
+ var res = new int[lengths.Length];
+
+ for (var i = lengths.Length - 1; i >= 0; i--)
+ {
+ var len = lengths[i];
+
+ res[i] = globalIdx % len;
+ globalIdx = globalIdx / len;
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Gets the object.
+ /// </summary>
+ public object Array
+ {
+ get { return _array; }
+ }
+
+ /** <inheritdoc /> */
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ var raw = writer.GetRawWriter();
+
+ // Array type.
+ raw.WriteInt(BinaryUtils.GetArrayElementTypeId(_array, ((BinaryWriter) writer).Marshaller));
+
+ // Number of dimensions.
+ var rank = _array.Rank;
+ raw.WriteInt(rank);
+
+ // Sizes per dimensions.
+ for (var i = 0; i < rank; i++)
+ {
+ raw.WriteInt(_array.GetLength(i));
+ }
+
+ // Data.
+ foreach (var obj in (IEnumerable)_array)
+ {
+ raw.WriteObject(obj);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs
new file mode 100644
index 0000000..993b9d5
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs
@@ -0,0 +1,48 @@
+/*
+ * 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;
+ using Apache.Ignite.Core.Impl.Common;
+
+ /// <summary>
+ /// Serializer for <see cref="MultidimensionalArrayHolder"/>. Unwraps underlying object automatically.
+ /// </summary>
+ internal sealed class MultidimensionalArraySerializer : IBinarySerializerInternal
+ {
+ /** <inheritdoc /> */
+ public void WriteBinary<T>(T obj, BinaryWriter writer)
+ {
+ TypeCaster<MultidimensionalArrayHolder>.Cast(obj).WriteBinary(writer);
+ }
+
+ /** <inheritdoc /> */
+ public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos, Type typeOverride)
+ {
+ var holder = new MultidimensionalArrayHolder(reader);
+
+ return (T) holder.Array;
+ }
+
+ /** <inheritdoc /> */
+ public bool SupportsHandles
+ {
+ get { return true; }
+ }
+ }
+}