http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs index 19e68a6..56a17a3 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs @@ -131,7 +131,7 @@ namespace Apache.Ignite.Core.Tests.Examples var proc = new IgniteProcess(args.ToArray()); - Assert.IsTrue(ignite.WaitTopology(2), + Assert.IsTrue(ignite.WaitTopology(2), string.Format("Standalone node failed to join topology: [{0}]", proc.GetInfo())); Assert.IsTrue(proc.Alive, string.Format("Standalone node stopped unexpectedly: [{0}]",
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs index 636e0fe..0aebd78 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs @@ -49,28 +49,6 @@ namespace Apache.Ignite.Core.Tests private IIgnite _grid; /// <summary> - /// Test fixture set-up routine. - /// </summary> - [TestFixtureSetUp] - public void TestFixtureSetUp() - { - TestUtils.KillProcesses(); - - _grid = Ignition.Start(Configuration(SpringCfgPath)); - } - - /// <summary> - /// Test fixture tear-down routine. - /// </summary> - [TestFixtureTearDown] - public void TestFixtureTearDown() - { - Ignition.StopAll(true); - - TestUtils.KillProcesses(); - } - - /// <summary> /// Set-up routine. /// </summary> [SetUp] @@ -78,6 +56,8 @@ namespace Apache.Ignite.Core.Tests { TestUtils.KillProcesses(); + _grid = Ignition.Start(Configuration(SpringCfgPath)); + Assert.IsTrue(_grid.WaitTopology(1)); IgniteProcess.SaveConfigurationBackup(); @@ -89,6 +69,10 @@ namespace Apache.Ignite.Core.Tests [TearDown] public void TearDown() { + Ignition.StopAll(true); + + TestUtils.KillProcesses(); + IgniteProcess.RestoreConfigurationBackup(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs deleted file mode 100644 index 2812468..0000000 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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 -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Reflection; - using System.Reflection.Emit; - using System.Runtime.Serialization; - using System.Xml; - using Apache.Ignite.Core.Cluster; - using Apache.Ignite.Core.Compute; - using Apache.Ignite.Core.Impl; - using NUnit.Framework; - - /// <summary> - /// Tests for native serialization. - /// </summary> - public class SerializationTest - { - /** Grid name. */ - private const string GridName = "SerializationTest"; - - /// <summary> - /// Set up routine. - /// </summary> - [TestFixtureSetUp] - public void SetUp() - { - var cfg = new IgniteConfiguration - { - IgniteInstanceName = GridName, - JvmClasspath = TestUtils.CreateTestClasspath(), - JvmOptions = TestUtils.TestJavaOptions(), - SpringConfigUrl = "config\\native-client-test-cache.xml" - }; - - Ignition.Start(cfg); - } - - /// <summary> - /// Tear down routine. - /// </summary> - [TestFixtureTearDown] - public void TearDown() - { - Ignition.StopAll(true); - } - - /// <summary> - /// Test complex file serialization. - /// </summary> - [Test] - public void TestSerializableXmlDoc() - { - var grid = Ignition.GetIgnite(GridName); - var cache = grid.GetCache<int, SerializableXmlDoc>("replicated"); - - var doc = new SerializableXmlDoc(); - - doc.LoadXml("<document><test1>val</test1><test2 attr=\"x\" /></document>"); - - for (var i = 0; i < 50; i++) - { - // Test cache - cache.Put(i, doc); - - var resultDoc = cache.Get(i); - - Assert.AreEqual(doc.OuterXml, resultDoc.OuterXml); - - // Test task with document arg - CheckTask(grid, doc); - } - } - - /// <summary> - /// Checks task execution. - /// </summary> - /// <param name="grid">Grid.</param> - /// <param name="arg">Task arg.</param> - private static void CheckTask(IIgnite grid, object arg) - { - var jobResult = grid.GetCompute().Execute(new CombineStringsTask(), arg); - - var nodeCount = grid.GetCluster().GetNodes().Count; - - var expectedRes = - CombineStringsTask.CombineStrings(Enumerable.Range(0, nodeCount).Select(x => arg.ToString())); - - Assert.AreEqual(expectedRes, jobResult.InnerXml); - } - - /// <summary> - /// Tests custom serialization binder. - /// </summary> - [Test] - public void TestSerializationBinder() - { - const int count = 50; - - var cache = Ignition.GetIgnite(GridName).GetCache<int, object>("local"); - - // Put multiple objects from muliple same-named assemblies to cache - for (var i = 0; i < count; i++) - { - dynamic val = Activator.CreateInstance(GenerateDynamicType()); - - val.Id = i; - val.Name = "Name_" + i; - - cache.Put(i, val); - } - - // Verify correct deserialization - for (var i = 0; i < count; i++) - { - dynamic val = cache.Get(i); - - Assert.AreEqual(val.Id, i); - Assert.AreEqual(val.Name, "Name_" + i); - } - } - - /// <summary> - /// Generates a Type in runtime, puts it into a dynamic assembly. - /// </summary> - /// <returns></returns> - public static Type GenerateDynamicType() - { - var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( - new AssemblyName("GridSerializationTestDynamicAssembly"), AssemblyBuilderAccess.Run); - - var moduleBuilder = asmBuilder.DefineDynamicModule("GridSerializationTestDynamicModule"); - - var typeBuilder = moduleBuilder.DefineType("GridSerializationTestDynamicType", - TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Serializable); - - typeBuilder.DefineField("Id", typeof (int), FieldAttributes.Public); - - typeBuilder.DefineField("Name", typeof (string), FieldAttributes.Public); - - return typeBuilder.CreateType(); - } - } - - [Serializable] - [DataContract] - public sealed class SerializableXmlDoc : XmlDocument, ISerializable - { - /// <summary> - /// Default ctor. - /// </summary> - public SerializableXmlDoc() - { - // No-op - } - - /// <summary> - /// Serialization ctor. - /// </summary> - private SerializableXmlDoc(SerializationInfo info, StreamingContext context) - { - LoadXml(info.GetString("xmlDocument")); - } - - /** <inheritdoc /> */ - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - info.AddValue("xmlDocument", OuterXml, typeof(string)); - } - } - - [Serializable] - public class CombineStringsTask : IComputeTask<object, string, SerializableXmlDoc> - { - public IDictionary<IComputeJob<string>, IClusterNode> Map(IList<IClusterNode> subgrid, object arg) - { - return subgrid.ToDictionary(x => (IComputeJob<string>) new ToStringJob {Arg = arg}, x => x); - } - - public ComputeJobResultPolicy OnResult(IComputeJobResult<string> res, IList<IComputeJobResult<string>> rcvd) - { - return ComputeJobResultPolicy.Wait; - } - - public SerializableXmlDoc Reduce(IList<IComputeJobResult<string>> results) - { - var result = new SerializableXmlDoc(); - - result.LoadXml(CombineStrings(results.Select(x => x.Data))); - - return result; - } - - public static string CombineStrings(IEnumerable<string> strings) - { - var text = string.Concat(strings.Select(x => string.Format("<val>{0}</val>", x))); - - return string.Format("<document>{0}</document>", text); - } - } - - [Serializable] - public class ToStringJob : IComputeJob<string> - { - /// <summary> - /// Job argument. - /// </summary> - public object Arg { get; set; } - - /** <inheritdoc /> */ - public string Execute() - { - return Arg.ToString(); - } - - /** <inheritdoc /> */ - public void Cancel() - { - // No-op. - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs index dcb5393..eb6192d 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs @@ -110,8 +110,13 @@ namespace Apache.Ignite.Core.Tests.Services Assert.IsNull(_svc.ObjProp); prx.ObjProp = new TestClass {Prop = "prop2"}; - Assert.AreEqual("prop2", ((TestClass)prx.ObjProp).Prop); - Assert.AreEqual("prop2", ((TestClass)_svc.ObjProp).Prop); + + var propVal = KeepBinary + ? ((IBinaryObject) prx.ObjProp).Deserialize<TestClass>().Prop + : ((TestClass) prx.ObjProp).Prop; + + Assert.AreEqual("prop2", propVal); + Assert.AreEqual("prop2", ((TestClass) _svc.ObjProp).Prop); } /// <summary> @@ -191,10 +196,19 @@ namespace Apache.Ignite.Core.Tests.Services var prx = GetProxy(); var err = Assert.Throws<ServiceInvocationException>(prx.ExceptionMethod); - Assert.AreEqual("Expected exception", err.InnerException.Message); - var ex = Assert.Throws<ServiceInvocationException>(() => prx.CustomExceptionMethod()); - Assert.IsTrue(ex.ToString().Contains("+CustomException")); + if (KeepBinary) + { + Assert.IsNotNull(err.BinaryCause); + Assert.AreEqual("Expected exception", err.BinaryCause.Deserialize<Exception>().Message); + } + else + { + Assert.IsNotNull(err.InnerException); + Assert.AreEqual("Expected exception", err.InnerException.Message); + } + + Assert.Throws<ServiceInvocationException>(() => prx.CustomExceptionMethod()); } [Test] @@ -243,7 +257,7 @@ namespace Apache.Ignite.Core.Tests.Services /// <summary> /// Creates the proxy. /// </summary> - protected T GetProxy<T>() + private T GetProxy<T>() { _svc = new TestIgniteService(Binary); @@ -591,9 +605,19 @@ namespace Apache.Ignite.Core.Tests.Services /// <summary> /// Custom non-serializable exception. /// </summary> - private class CustomException : Exception + private class CustomException : Exception, IBinarizable { - + /** <inheritDoc /> */ + public void WriteBinary(IBinaryWriter writer) + { + throw new BinaryObjectException("Expected"); + } + + /** <inheritDoc /> */ + public void ReadBinary(IBinaryReader reader) + { + throw new BinaryObjectException("Expected"); + } } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs index 8360bf1..0bb3b7f 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs @@ -27,6 +27,7 @@ namespace Apache.Ignite.Core.Tests using Apache.Ignite.Core.Discovery.Tcp; using Apache.Ignite.Core.Discovery.Tcp.Static; using Apache.Ignite.Core.Impl; + using Apache.Ignite.Core.Impl.Binary; using Apache.Ignite.Core.Impl.Common; using Apache.Ignite.Core.Tests.Process; using NUnit.Framework; @@ -370,5 +371,15 @@ namespace Apache.Ignite.Core.Tests Assert.IsTrue(proc.WaitForExit(15000)); Assert.AreEqual(0, proc.ExitCode); } + + /// <summary> + /// Serializes and deserializes back an object. + /// </summary> + public static T SerializeDeserialize<T>(T obj) + { + var marsh = new Marshaller(null) {CompactFooter = false}; + + return marsh.Unmarshal<T>(marsh.Marshal(obj)); + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 333b9bc..2a174eb 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -186,11 +186,12 @@ <Compile Include="Common\IgniteFutureCancelledException.cs" /> <Compile Include="Common\IgniteGuid.cs" /> <Compile Include="Common\Package-Info.cs" /> - <Compile Include="Impl\Binary\DateTimeSerializer.cs" /> <Compile Include="Impl\Binary\IO\IBinaryStreamProcessor.cs" /> <Compile Include="Impl\Binary\Metadata\BinaryField.cs" /> <Compile Include="Impl\Binary\SerializableSerializer.cs" /> <Compile Include="Impl\Binary\BinaryWriterExtensions.cs" /> + <Compile Include="Impl\Binary\DeserializationCallbackProcessor.cs" /> + <Compile Include="Impl\Binary\ReflectionUtils.cs" /> <Compile Include="Cache\Affinity\AffinityFunctionBase.cs" /> <Compile Include="Impl\Cache\Store\CacheStore.cs" /> <Compile Include="Impl\Cache\Store\ICacheStoreInternal.cs" /> @@ -319,6 +320,7 @@ <Compile Include="Impl\Common\CopyOnWriteConcurrentDictionary.cs" /> <Compile Include="Impl\Common\DelegateConverter.cs" /> <Compile Include="Impl\Common\DelegateTypeDescriptor.cs" /> + <Compile Include="Impl\Common\SerializableTypeDescriptor.cs" /> <Compile Include="Impl\Events\EventTypeConverter.cs" /> <Compile Include="Impl\Common\Fnv1Hash.cs" /> <Compile Include="Impl\Common\Future.cs" /> @@ -385,11 +387,9 @@ <Compile Include="Impl\Messaging\MessageListenerHolder.cs" /> <Compile Include="Impl\Messaging\Messaging.cs" /> <Compile Include="Impl\NativeMethods.cs" /> - <Compile Include="Impl\Binary\DateTimeHolder.cs" /> <Compile Include="Impl\Binary\IO\IBinaryStream.cs" /> <Compile Include="Impl\Binary\IO\BinaryStreamBase.cs" /> <Compile Include="Impl\Binary\IO\BinaryHeapStream.cs" /> - <Compile Include="Impl\Binary\IO\BinaryStreamAdapter.cs" /> <Compile Include="Impl\Binary\IBinaryTypeDescriptor.cs" /> <Compile Include="Impl\Binary\IBinaryWriteAware.cs" /> <Compile Include="Impl\Binary\Metadata\IBinaryTypeHandler.cs" /> @@ -419,7 +419,6 @@ <Compile Include="Impl\Binary\BinaryObject.cs" /> <Compile Include="Impl\Binary\BinaryUtils.cs" /> <Compile Include="Impl\Binary\BinaryWriter.cs" /> - <Compile Include="Impl\Binary\SerializableObjectHolder.cs" /> <Compile Include="Impl\Binary\Structure\BinaryStructure.cs" /> <Compile Include="Impl\Binary\Structure\BinaryStructureEntry.cs" /> <Compile Include="Impl\Binary\Structure\BinaryStructureJumpTable.cs" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs index 29d2ee3..4f48ea5 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs @@ -235,6 +235,9 @@ namespace Apache.Ignite.Core.Cache.Configuration /// <param name="reader">The reader.</param> internal CacheConfiguration(IBinaryRawReader reader) { + // Make sure system marshaller is used. + Debug.Assert(((BinaryReader) reader).Marshaller == BinaryUtils.Marshaller); + AtomicityMode = (CacheAtomicityMode) reader.ReadInt(); AtomicWriteOrderMode = (CacheAtomicWriteOrderMode) reader.ReadInt(); Backups = reader.ReadInt(); @@ -297,6 +300,9 @@ namespace Apache.Ignite.Core.Cache.Configuration /// <param name="writer">The writer.</param> internal void Write(IBinaryRawWriter writer) { + // Make sure system marshaller is used. + Debug.Assert(((BinaryWriter) writer).Marshaller == BinaryUtils.Marshaller); + writer.WriteInt((int) AtomicityMode); writer.WriteInt((int) AtomicWriteOrderMode); writer.WriteInt(Backups); @@ -740,7 +746,7 @@ namespace Apache.Ignite.Core.Cache.Configuration public IAffinityFunction AffinityFunction { get; set; } /// <summary> - /// Gets or sets the factory for <see cref="IExpiryPolicy"/> to be used for all cache operations, + /// Gets or sets the factory for <see cref="IExpiryPolicy"/> to be used for all cache operations, /// unless <see cref="ICache{TK,TV}.WithExpiryPolicy"/> is called. /// <para /> /// Default is null, which means no expiration. http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs index d3bd50c..28842e9 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs @@ -159,7 +159,7 @@ using (var stream = IgniteManager.Memory.Allocate().GetStream()) { - var marsh = new Marshaller(configuration.BinaryConfiguration); + var marsh = BinaryUtils.Marshaller; configuration.Write(marsh.StartMarshal(stream)); @@ -276,15 +276,26 @@ // Send only descriptors with non-null EqualityComparer to preserve old behavior where // remote nodes can have no BinaryConfiguration. - var types = writer.Marshaller.GetUserTypeDescriptors().Where(x => x.EqualityComparer != null).ToList(); - writer.WriteInt(types.Count); + if (BinaryConfiguration.TypeConfigurations != null && + BinaryConfiguration.TypeConfigurations.Any(x => x.EqualityComparer != null)) + { + // Create a new marshaller to reuse type name resolver mechanism. + var types = new Marshaller(BinaryConfiguration).GetUserTypeDescriptors() + .Where(x => x.EqualityComparer != null).ToList(); + + writer.WriteInt(types.Count); - foreach (var type in types) + foreach (var type in types) + { + writer.WriteString(BinaryUtils.SimpleTypeName(type.TypeName)); + writer.WriteBoolean(type.IsEnum); + BinaryEqualityComparerSerializer.Write(writer, type.EqualityComparer); + } + } + else { - writer.WriteString(BinaryUtils.SimpleTypeName(type.TypeName)); - writer.WriteBoolean(type.IsEnum); - BinaryEqualityComparerSerializer.Write(writer, type.EqualityComparer); + writer.WriteInt(0); } } else http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs index 1190c14..f590794 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs @@ -359,11 +359,11 @@ namespace Apache.Ignite.Core if (cfg.BinaryConfiguration == null) cfg.BinaryConfiguration = binaryCfg; - _startup.Marshaller = new Marshaller(cfg.BinaryConfiguration); + _startup.Marshaller = new Marshaller(cfg.BinaryConfiguration, log); // 3. Send configuration details to Java cfg.Validate(log); - cfg.Write(_startup.Marshaller.StartMarshal(outStream)); + cfg.Write(BinaryUtils.Marshaller.StartMarshal(outStream)); // Use system marshaller. } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs index dcb261f..2273a93 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs @@ -17,7 +17,6 @@ namespace Apache.Ignite.Core.Impl.Binary { - using System; using System.Runtime.Serialization; using Apache.Ignite.Core.Binary; @@ -39,9 +38,9 @@ namespace Apache.Ignite.Core.Impl.Binary } /** <inheritdoc /> */ - public T ReadBinary<T>(BinaryReader reader, Type type, int pos) + public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos) { - var obj = (T) FormatterServices.GetUninitializedObject(type); + var obj = (T) FormatterServices.GetUninitializedObject(desc.Type); reader.AddHandle(pos, obj); http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs index d88e7a9..6a911ad 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs @@ -62,7 +62,7 @@ namespace Apache.Ignite.Core.Impl.Binary private volatile BinaryStructure _readerTypeStructure = BinaryStructure.CreateEmpty(); /** Type schema. */ - private readonly BinaryObjectSchema _schema = new BinaryObjectSchema(); + private readonly BinaryObjectSchema _schema; /** Enum flag. */ private readonly bool _isEnum; @@ -70,6 +70,9 @@ namespace Apache.Ignite.Core.Impl.Binary /** Comparer. */ private readonly IBinaryEqualityComparer _equalityComparer; + /** Register flag. */ + private readonly bool _isRegistered; + /// <summary> /// Constructor. /// </summary> @@ -84,6 +87,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="affKeyFieldName">Affinity field key name.</param> /// <param name="isEnum">Enum flag.</param> /// <param name="comparer">Equality comparer.</param> + /// <param name="isRegistered">Registered flag.</param> public BinaryFullTypeDescriptor( Type type, int typeId, @@ -94,8 +98,9 @@ namespace Apache.Ignite.Core.Impl.Binary IBinarySerializerInternal serializer, bool keepDeserialized, string affKeyFieldName, - bool isEnum, - IEqualityComparer<IBinaryObject> comparer) + bool isEnum, + IEqualityComparer<IBinaryObject> comparer, + bool isRegistered = true) { _type = type; _typeId = typeId; @@ -114,6 +119,38 @@ namespace Apache.Ignite.Core.Impl.Binary throw new IgniteException(string.Format("Unsupported IEqualityComparer<IBinaryObject> " + "implementation: {0}. Only predefined implementations " + "are supported.", comparer.GetType())); + + _isRegistered = isRegistered; + _schema = new BinaryObjectSchema(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="BinaryFullTypeDescriptor"/> class, + /// copying values from specified descriptor. + /// </summary> + /// <param name="desc">The descriptor to copy from.</param> + /// <param name="type">Type.</param> + /// <param name="serializer">Serializer.</param> + /// <param name="isRegistered">Registered flag.</param> + public BinaryFullTypeDescriptor(BinaryFullTypeDescriptor desc, Type type, + IBinarySerializerInternal serializer, bool isRegistered) + { + _type = type; + _typeId = desc._typeId; + _typeName = desc._typeName; + _userType = desc._userType; + _nameMapper = desc._nameMapper; + _idMapper = desc._idMapper; + _serializer = serializer; + _keepDeserialized = desc._keepDeserialized; + _affKeyFieldName = desc._affKeyFieldName; + _isEnum = desc._isEnum; + _equalityComparer = desc._equalityComparer; + _isRegistered = isRegistered; + + _schema = desc._schema; + _writerTypeStruct = desc._writerTypeStruct; + _readerTypeStructure = desc._readerTypeStructure; } /// <summary> @@ -237,5 +274,11 @@ namespace Apache.Ignite.Core.Impl.Binary { get { return _schema; } } + + /** <inheritDoc /> */ + public bool IsRegistered + { + get { return _isRegistered; } + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs index e77cbae..e4fb10a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs @@ -676,6 +676,9 @@ namespace Apache.Ignite.Core.Impl.Binary ? BinaryObjectHeader.Flag.UserType : BinaryObjectHeader.Flag.None; + if (inHeader.IsCustomDotNetType) + flags |= BinaryObjectHeader.Flag.CustomDotNetType; + // Write raw data. int outRawOff = outStream.Position - outStartPos; @@ -936,8 +939,6 @@ namespace Apache.Ignite.Core.Impl.Binary case BinaryUtils.TypeArrayString: case BinaryUtils.TypeArrayGuid: case BinaryUtils.TypeArrayTimestamp: - case BinaryUtils.TypeArrayEnum: - case BinaryUtils.TypeArray: int arrLen = inStream.ReadInt(); outStream.WriteInt(arrLen); @@ -947,6 +948,28 @@ namespace Apache.Ignite.Core.Impl.Binary break; + case BinaryUtils.TypeArrayEnum: + case BinaryUtils.TypeArray: + int type = inStream.ReadInt(); + + outStream.WriteInt(type); + + if (type == BinaryUtils.TypeUnregistered) + { + outStream.WriteByte(inStream.ReadByte()); // String header. + + BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream); // String data. + } + + arrLen = inStream.ReadInt(); + + outStream.WriteInt(arrLen); + + for (int i = 0; i < arrLen; i++) + Mutate0(ctx, inStream, outStream, false, EmptyVals); + + break; + case BinaryUtils.TypeCollection: int colLen = inStream.ReadInt(); http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs index 636b177..0f0fafe 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs @@ -58,7 +58,10 @@ namespace Apache.Ignite.Core.Impl.Binary OffsetTwoBytes = 0x10, /** Flag: compact footer, no field IDs. */ - CompactFooter = 0x20 + CompactFooter = 0x20, + + /** Flag: raw data contains .NET type information. */ + CustomDotNetType = 0x40 } /** Actual header layout */ @@ -164,6 +167,14 @@ namespace Apache.Ignite.Core.Impl.Binary } /// <summary> + /// Gets the custom .NET type flag. + /// </summary> + public bool IsCustomDotNetType + { + get { return (Flags & Flag.CustomDotNetType) == Flag.CustomDotNetType; } + } + + /// <summary> /// Gets the size of the schema field offset (1, 2 or 4 bytes). /// </summary> public int SchemaFieldOffsetSize http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs ---------------------------------------------------------------------- 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 f1d2f6a..e2f9ea7 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs @@ -249,6 +249,8 @@ namespace Apache.Ignite.Core.Impl.Binary if (fieldIds == null) { + Debug.Assert(hdr.TypeId != BinaryUtils.TypeUnregistered); + if (marsh.Ignite != null) fieldIds = marsh.Ignite.BinaryProcessor.GetSchema(hdr.TypeId, hdr.SchemaId); http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs ---------------------------------------------------------------------- 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 f5bc370..555a042 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs @@ -17,6 +17,7 @@ namespace Apache.Ignite.Core.Impl.Binary { + using System; using System.Collections.Generic; using System.Diagnostics; using Apache.Ignite.Core.Binary; @@ -36,7 +37,9 @@ namespace Apache.Ignite.Core.Impl.Binary GetMeta = 1, GetAllMeta = 2, PutMeta = 3, - GetSchema = 4 + GetSchema = 4, + RegisterType = 5, + GetType = 6 } /// <summary> @@ -101,7 +104,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// Put binary types to Grid. /// </summary> /// <param name="types">Binary types.</param> - internal void PutBinaryTypes(ICollection<BinaryType> types) + public void PutBinaryTypes(ICollection<BinaryType> types) { DoOutOp((int) Op.PutMeta, w => { @@ -153,5 +156,36 @@ namespace Apache.Ignite.Core.Impl.Binary Marshaller.OnBinaryTypesSent(types); } + + /// <summary> + /// Registers the type. + /// </summary> + /// <param name="id">The identifier.</param> + /// <param name="type">The type.</param> + /// <returns>True if registration succeeded; otherwise, false.</returns> + public bool RegisterType(int id, Type type) + { + Debug.Assert(type != null); + Debug.Assert(id != BinaryUtils.TypeUnregistered); + + return DoOutOp((int) Op.RegisterType, w => + { + w.WriteInt(id); + w.WriteString(type.AssemblyQualifiedName); + }) == True; + } + + /// <summary> + /// Gets the type by id. + /// </summary> + /// <param name="id">The identifier.</param> + /// <returns>Type or null.</returns> + public Type GetType(int id) + { + var typeName = DoOutInOp((int) Op.GetType, w => w.WriteInt(id), + r => Marshaller.StartUnmarshal(r).ReadString()); + + return new TypeResolver().ResolveType(typeName); + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs ---------------------------------------------------------------------- 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 092eb72..49bab77 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs @@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Impl.Binary using System; using System.Collections; using System.Collections.Generic; + using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using Apache.Ignite.Core.Binary; @@ -79,6 +80,14 @@ namespace Apache.Ignite.Core.Impl.Binary get { return _marsh; } } + /// <summary> + /// Gets the mode. + /// </summary> + public BinaryMode Mode + { + get { return _mode; } + } + /** <inheritdoc /> */ public IBinaryRawReader GetRawReader() { @@ -572,6 +581,14 @@ namespace Apache.Ignite.Core.Impl.Binary throw new BinaryObjectException("Invalid header on deserialization [pos=" + pos + ", hdr=" + hdr + ']'); } + + /// <summary> + /// Gets the flag indicating that there is custom type information in raw region. + /// </summary> + public bool GetCustomTypeDataFlag() + { + return _frame.Hdr.IsCustomDotNetType; + } /// <summary> /// Reads the binary object. @@ -676,7 +693,9 @@ namespace Apache.Ignite.Core.Impl.Binary else { // Find descriptor. - var desc = _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId); + var desc = hdr.TypeId == BinaryUtils.TypeUnregistered + ? _marsh.GetDescriptor(Type.GetType(ReadString(), true)) + : _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId, true); // Instantiate object. if (desc.Type == null) @@ -707,7 +726,7 @@ namespace Apache.Ignite.Core.Impl.Binary _frame.Raw = false; // Read object. - var obj = desc.Serializer.ReadBinary<T>(this, desc.Type, pos); + var obj = desc.Serializer.ReadBinary<T>(this, desc, pos); _frame.Struct.UpdateReaderStructure(); @@ -758,8 +777,10 @@ namespace Apache.Ignite.Core.Impl.Binary // Get schema from Java var ignite = Marshaller.Ignite; - var schema = ignite == null - ? null + Debug.Assert(typeId != BinaryUtils.TypeUnregistered); + + var schema = ignite == null + ? null : ignite.BinaryProcessor.GetSchema(_frame.Hdr.TypeId, _frame.Hdr.SchemaId); if (schema == null) @@ -850,6 +871,14 @@ namespace Apache.Ignite.Core.Impl.Binary } /// <summary> + /// Seeks to raw data. + /// </summary> + internal void SeekToRaw() + { + Stream.Seek(_frame.Pos + _frame.Hdr.GetRawOffset(Stream, _frame.Pos), SeekOrigin.Begin); + } + + /// <summary> /// Mark current output as raw. /// </summary> private void MarkRaw() @@ -858,7 +887,7 @@ namespace Apache.Ignite.Core.Impl.Binary { _frame.Raw = true; - Stream.Seek(_frame.Pos + _frame.Hdr.GetRawOffset(Stream, _frame.Pos), SeekOrigin.Begin); + SeekToRaw(); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 795f8ac..907b465 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs @@ -722,7 +722,7 @@ namespace Apache.Ignite.Core.Impl.Binary // Assign field value var targetParam = Expression.Parameter(typeof(object)); - var targetParamConverted = Expression.Convert(targetParam, field.DeclaringType); + var targetParamConverted = Expression.Convert(targetParam, typeof(object)); var assignExpr = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParamConverted, readExpr); http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs index c9fd3cc..e160559 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs @@ -20,19 +20,17 @@ namespace Apache.Ignite.Core.Impl.Binary using System; using System.Collections.Generic; using System.Diagnostics; + using System.Linq; using System.Reflection; using System.Runtime.Serialization; using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Impl.Common; /// <summary> /// Internal reflective serializer. /// </summary> internal sealed class BinaryReflectiveSerializerInternal : IBinarySerializerInternal { - /** Cached binding flags. */ - private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | - BindingFlags.NonPublic | BindingFlags.DeclaredOnly; - /** Raw mode flag. */ private readonly bool _rawMode; @@ -42,6 +40,9 @@ namespace Apache.Ignite.Core.Impl.Binary /** Read actions to be performed. */ private readonly BinaryReflectiveReadAction[] _rActions; + /** Callback type descriptor. */ + private readonly SerializableTypeDescriptor _serializableDescriptor; + /// <summary> /// Initializes a new instance of the <see cref="BinaryReflectiveSerializer"/> class. /// </summary> @@ -53,36 +54,64 @@ namespace Apache.Ignite.Core.Impl.Binary /// <summary> /// Initializes a new instance of the <see cref="BinaryReflectiveSerializer"/> class. /// </summary> - private BinaryReflectiveSerializerInternal(BinaryReflectiveWriteAction[] wActions, BinaryReflectiveReadAction[] rActions, bool raw) + private BinaryReflectiveSerializerInternal(BinaryReflectiveWriteAction[] wActions, + BinaryReflectiveReadAction[] rActions, bool raw, SerializableTypeDescriptor serializableDescriptor) { Debug.Assert(wActions != null); Debug.Assert(rActions != null); + Debug.Assert(serializableDescriptor != null); _wActions = wActions; _rActions = rActions; _rawMode = raw; + _serializableDescriptor = serializableDescriptor; } /** <inheritdoc /> */ void IBinarySerializerInternal.WriteBinary<T>(T obj, BinaryWriter writer) { Debug.Assert(_wActions != null); + Debug.Assert(writer != null); + + var ctx = GetStreamingContext(writer); + + _serializableDescriptor.OnSerializing(obj, ctx); foreach (var action in _wActions) action(obj, writer); + + _serializableDescriptor.OnSerialized(obj, ctx); } /** <inheritdoc /> */ - T IBinarySerializerInternal.ReadBinary<T>(BinaryReader reader, Type type, int pos) + T IBinarySerializerInternal.ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos) { Debug.Assert(_rActions != null); + Debug.Assert(reader != null); + Debug.Assert(desc != null); + + var obj = FormatterServices.GetUninitializedObject(desc.Type); + + var ctx = GetStreamingContext(reader); + + _serializableDescriptor.OnDeserializing(obj, ctx); - var obj = FormatterServices.GetUninitializedObject(type); + DeserializationCallbackProcessor.Push(obj); - reader.AddHandle(pos, obj); + try + { + reader.AddHandle(pos, obj); + + foreach (var action in _rActions) + action(obj, reader); - foreach (var action in _rActions) - action(obj, reader); + _serializableDescriptor.OnDeserialized(obj, ctx); + + } + finally + { + DeserializationCallbackProcessor.Pop(); + } return (T) obj; } @@ -103,20 +132,7 @@ namespace Apache.Ignite.Core.Impl.Binary { Debug.Assert(_wActions == null && _rActions == null); - List<FieldInfo> fields = new List<FieldInfo>(); - - Type curType = type; - - while (curType != null) - { - foreach (FieldInfo field in curType.GetFields(Flags)) - { - if (!field.IsNotSerialized) - fields.Add(field); - } - - curType = curType.BaseType; - } + var fields = ReflectionUtils.GetAllFields(type).Where(x => !x.IsNotSerialized).ToList(); IDictionary<int, string> idMap = new Dictionary<int, string>(); @@ -152,7 +168,9 @@ namespace Apache.Ignite.Core.Impl.Binary rActions[i] = readAction; } - return new BinaryReflectiveSerializerInternal(wActions, rActions, _rawMode); + var serDesc = SerializableTypeDescriptor.Get(type); + + return new BinaryReflectiveSerializerInternal(wActions, rActions, _rawMode, serDesc); } /// <summary> @@ -165,5 +183,21 @@ namespace Apache.Ignite.Core.Impl.Binary return string.Compare(name1, name2, StringComparison.OrdinalIgnoreCase); } + + /// <summary> + /// Gets the streaming context. + /// </summary> + private static StreamingContext GetStreamingContext(IBinaryReader reader) + { + return new StreamingContext(StreamingContextStates.All, reader); + } + + /// <summary> + /// Gets the streaming context. + /// </summary> + private static StreamingContext GetStreamingContext(IBinaryWriter writer) + { + return new StreamingContext(StreamingContextStates.All, writer); + } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs index adba577..8c7e5e9 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs @@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Impl.Binary { using System; using System.Collections.Generic; + using System.Diagnostics; using Apache.Ignite.Core.Binary; using Apache.Ignite.Core.Impl.Binary.Structure; @@ -51,10 +52,14 @@ namespace Apache.Ignite.Core.Impl.Binary /// </summary> /// <param name="cfg">Configuration.</param> /// <param name="id">Type ID.</param> - public BinarySurrogateTypeDescriptor(BinaryConfiguration cfg, int id) + /// <param name="typeName">Name of the type.</param> + public BinarySurrogateTypeDescriptor(BinaryConfiguration cfg, int id, string typeName) { + Debug.Assert(cfg != null); + _cfg = cfg; _id = id; + _name = typeName; } /// <summary> @@ -170,5 +175,11 @@ namespace Apache.Ignite.Core.Impl.Binary { get { return _schema; } } + + /** <inheritDoc /> */ + public bool IsRegistered + { + get { return false; } + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 beb2668..60bbb46 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs @@ -22,7 +22,6 @@ namespace Apache.Ignite.Core.Impl.Binary using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; - using Apache.Ignite.Core.Binary; using Apache.Ignite.Core.Impl.Binary.IO; using Apache.Ignite.Core.Impl.Common; @@ -169,8 +168,7 @@ namespace Apache.Ignite.Core.Impl.Binary var handler = FindWriteHandler(t, out supportsHandles); - return handler == null ? null : new BinarySystemWriteHandler(handler, supportsHandles, - handler == WriteSerializable); + return handler == null ? null : new BinarySystemWriteHandler(handler, supportsHandles); }); } @@ -191,8 +189,6 @@ namespace Apache.Ignite.Core.Impl.Binary return WriteString; if (type == typeof(decimal)) return WriteDecimal; - if (type == typeof(DateTime)) - return WriteDate; if (type == typeof(Guid)) return WriteGuid; if (type == typeof (BinaryObject)) @@ -251,16 +247,11 @@ namespace Apache.Ignite.Core.Impl.Binary // Enums. if (elemType.IsEnum || elemType == typeof(BinaryEnum)) return WriteEnumArray; - + // Object array. - if (elemType == typeof (object) || elemType == typeof (IBinaryObject) || - elemType == typeof (BinaryObject)) - return WriteArray; + return WriteArray; } - if (type.IsSerializable) - return WriteSerializable; - return null; } @@ -315,16 +306,6 @@ namespace Apache.Ignite.Core.Impl.Binary } /// <summary> - /// Write date. - /// </summary> - /// <param name="ctx">Context.</param> - /// <param name="obj">Value.</param> - private static void WriteDate(BinaryWriter ctx, object obj) - { - ctx.Write(new DateTimeHolder((DateTime) obj)); - } - - /// <summary> /// Write string. /// </summary> /// <param name="ctx">Context.</param> @@ -535,21 +516,17 @@ namespace Apache.Ignite.Core.Impl.Binary { ctx.Stream.WriteByte(BinaryUtils.TypeArrayEnum); - var desc = ctx.Marshaller.GetDescriptor(obj.GetType()); - - int typeId = desc == null ? BinaryUtils.ObjTypeId : desc.TypeId; - - BinaryUtils.WriteArray((Array)obj, ctx, typeId); + BinaryUtils.WriteArray((Array) obj, ctx); } - /** - * <summary>Write array.</summary> - */ + /// <summary> + /// Writes the array. + /// </summary> private static void WriteArray(BinaryWriter ctx, object obj) { ctx.Stream.WriteByte(BinaryUtils.TypeArray); - BinaryUtils.WriteArray((Array)obj, ctx); + BinaryUtils.WriteArray((Array) obj, ctx); } /** @@ -603,16 +580,6 @@ namespace Apache.Ignite.Core.Impl.Binary ctx.WriteInt(binEnum.EnumValue); } - /// <summary> - /// Writes serializable. - /// </summary> - /// <param name="writer">The writer.</param> - /// <param name="o">The object.</param> - private static void WriteSerializable(BinaryWriter writer, object o) - { - writer.Write(new SerializableObjectHolder(o)); - } - /** * <summary>Read enum array.</summary> */ @@ -623,13 +590,36 @@ namespace Apache.Ignite.Core.Impl.Binary return BinaryUtils.ReadTypedArray(ctx, true, elemType); } - /** - * <summary>Read array.</summary> - */ + /// <summary> + /// Reads the array. + /// </summary> private static object ReadArray(BinaryReader ctx, Type type) { - var elemType = type.GetElementType() ?? typeof(object); + var elemType = type.GetElementType(); + + if (elemType == null) + { + if (ctx.Mode == BinaryMode.ForceBinary) + { + // Forced binary mode: use object because primitives are not represented as IBinaryObject. + elemType = typeof(object); + } + else + { + // Infer element type from typeId. + var typeId = ctx.ReadInt(); + + if (typeId != BinaryUtils.ObjTypeId) + { + elemType = ctx.Marshaller.GetDescriptor(true, typeId, true).Type; + } + + return BinaryUtils.ReadTypedArray(ctx, false, elemType ?? typeof(object)); + } + } + // Element type is known, no need to check typeId. + // In case of incompatible types we'll get exception either way. return BinaryUtils.ReadTypedArray(ctx, true, elemType); } @@ -798,23 +788,17 @@ namespace Apache.Ignite.Core.Impl.Binary /** */ private readonly bool _supportsHandles; - /** */ - private readonly bool _isSerializable; - /// <summary> /// Initializes a new instance of the <see cref="BinarySystemWriteHandler" /> class. /// </summary> /// <param name="writeAction">The write action.</param> /// <param name="supportsHandles">Handles flag.</param> - /// <param name="isSerializable">Determines whether this handler writes objects as serializable.</param> - public BinarySystemWriteHandler(Action<BinaryWriter, object> writeAction, bool supportsHandles, - bool isSerializable) + public BinarySystemWriteHandler(Action<BinaryWriter, object> writeAction, bool supportsHandles) { Debug.Assert(writeAction != null); _writeAction = writeAction; _supportsHandles = supportsHandles; - _isSerializable = isSerializable; } /// <summary> @@ -834,13 +818,5 @@ namespace Apache.Ignite.Core.Impl.Binary { get { return _supportsHandles; } } - - /// <summary> - /// Gets or sets a value indicating whether this handler writes objects as serializable - /// </summary> - public bool IsSerializable - { - get { return _isSerializable; } - } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs index b416848..1ea1f0b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs @@ -48,7 +48,7 @@ namespace Apache.Ignite.Core.Impl.Binary } /** <inheritDoc /> */ - public T1 ReadBinary<T1>(BinaryReader reader, Type type, int pos) + public T1 ReadBinary<T1>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos) { return TypeCaster<T1>.Cast(_ctor(reader)); } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 2050f67..bb58ea5 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs @@ -52,6 +52,9 @@ namespace Apache.Ignite.Core.Impl.Binary /** Type: object. */ public const byte TypeObject = HdrFull; + /** Type: unregistered. */ + public const byte TypeUnregistered = 0; + /** Type: unsigned byte. */ public const byte TypeByte = 1; @@ -166,12 +169,6 @@ namespace Apache.Ignite.Core.Impl.Binary /** Type: Compute job wrapper. */ public const byte TypeComputeJobWrapper = 86; - /** Type: Serializable wrapper. */ - public const byte TypeSerializableHolder = 87; - - /** Type: DateTime wrapper. */ - public const byte TypeDateTimeHolder = 93; - /** Type: action wrapper. */ public const byte TypeComputeActionJob = 88; @@ -235,8 +232,12 @@ namespace Apache.Ignite.Core.Impl.Binary /** Bindig flags for static search. */ private const BindingFlags BindFlagsStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; - /** Default poratble marshaller. */ - private static readonly Marshaller Marsh = new Marshaller(null); + /** System marshaller. */ + private static readonly Marshaller Marsh = new Marshaller( + new BinaryConfiguration {CompactFooter = false}) + { + RegistrationDisabled = true + }; /** Method: ReadArray. */ public static readonly MethodInfo MtdhReadArray = @@ -1265,14 +1266,31 @@ namespace Apache.Ignite.Core.Impl.Binary /// </summary> /// <param name="val">Array.</param> /// <param name="ctx">Write context.</param> - /// <param name="elementType">Type of the array element.</param> - public static void WriteArray(Array val, BinaryWriter ctx, int elementType = ObjTypeId) + /// <param name="elemTypeId">The element type id.</param> + public static void WriteArray(Array val, BinaryWriter ctx, int? elemTypeId = null) { Debug.Assert(val != null && ctx != null); IBinaryStream stream = ctx.Stream; - stream.WriteInt(elementType); + if (elemTypeId != null && elemTypeId != TypeUnregistered) + { + stream.WriteInt(elemTypeId.Value); + } + else + { + var elemType = val.GetType().GetElementType(); + + var typeId = ObjTypeId; + + if (elemType != typeof(object)) + typeId = ctx.Marshaller.GetDescriptor(elemType).TypeId; + + stream.WriteInt(typeId); + + if (typeId == TypeUnregistered) + ctx.WriteString(elemType.FullName); + } stream.WriteInt(val.Length); @@ -1313,7 +1331,12 @@ namespace Apache.Ignite.Core.Impl.Binary var pos = stream.Position; if (typed) - stream.ReadInt(); + { + int typeId = stream.ReadInt(); + + if (typeId == TypeUnregistered) + ctx.ReadString(); + } int len = stream.ReadInt(); @@ -1538,7 +1561,7 @@ namespace Apache.Ignite.Core.Impl.Binary { var desc = marshaller.GetDescriptor(enumType); - return desc == null ? ObjTypeId : desc.TypeId; + return desc.TypeId; } throw new BinaryObjectException("Only Int32 underlying type is supported for enums: " + @@ -1559,10 +1582,10 @@ namespace Apache.Ignite.Core.Impl.Binary return TypeCaster<T>.Cast(value); // All enums are user types - var desc = marsh.GetDescriptor(true, typeId); + var desc = marsh.GetDescriptor(true, typeId, true); if (desc == null || desc.Type == null) - throw new BinaryObjectException("Unknown enum type id: " + typeId); + return TypeCaster<T>.Cast(value); return (T)Enum.ToObject(desc.Type, value); } @@ -1743,7 +1766,6 @@ namespace Apache.Ignite.Core.Impl.Binary public static int FieldId(int typeId, string fieldName, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper) { - Debug.Assert(typeId != 0); Debug.Assert(fieldName != null); fieldName = ConvertFieldName(fieldName, nameMapper); http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs index 0490ec8..1388d16 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs @@ -48,27 +48,12 @@ namespace Apache.Ignite.Core.Impl.Binary /** Metadatas collected during this write session. */ private IDictionary<int, BinaryType> _metas; - /** Current type ID. */ - private int _curTypeId; - - /** Current name converter */ - private IBinaryNameMapper _curConverter; - - /** Current mapper. */ - private IBinaryIdMapper _curMapper; - - /** Current object start position. */ - private int _curPos; - - /** Current raw position. */ - private int _curRawPos; + /** Current stack frame. */ + private Frame _frame; /** Whether we are currently detaching an object. */ private bool _detaching; - /** Current type structure tracker, */ - private BinaryStructureTracker _curStruct; - /** Schema holder. */ private readonly BinaryObjectSchemaHolder _schema = BinaryObjectSchemaHolder.Current; @@ -150,7 +135,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="val">Byte value.</param> public void WriteByte(string fieldName, byte val) { - WriteFieldId(fieldName, BinaryUtils.TypeBool); + WriteFieldId(fieldName, BinaryUtils.TypeByte); WriteByteField(val); } @@ -875,23 +860,13 @@ namespace Apache.Ignite.Core.Impl.Binary { var desc = _marsh.GetDescriptor(val.GetType()); - if (desc != null) - { - var metaHnd = _marsh.GetBinaryTypeHandler(desc); + var metaHnd = _marsh.GetBinaryTypeHandler(desc); - _stream.WriteByte(BinaryUtils.TypeEnum); + _stream.WriteByte(BinaryUtils.TypeEnum); - BinaryUtils.WriteEnum(this, val); + BinaryUtils.WriteEnum(this, val); - SaveMetadata(desc, metaHnd.OnObjectWriteFinished()); - } - else - { - // Unregistered enum, write with object type id. - _stream.WriteByte(BinaryUtils.TypeEnum); - _stream.WriteInt(BinaryUtils.ObjTypeId); - _stream.WriteInt(TypeCaster<int>.Cast(val)); - } + SaveMetadata(desc, metaHnd.OnObjectWriteFinished()); } } @@ -931,9 +906,7 @@ namespace Apache.Ignite.Core.Impl.Binary { _stream.WriteByte(BinaryUtils.TypeArrayEnum); - var elTypeId = elementTypeId ?? BinaryUtils.GetEnumTypeId(val.GetType().GetElementType(), Marshaller); - - BinaryUtils.WriteArray(val, this, elTypeId); + BinaryUtils.WriteArray(val, this, elementTypeId); } } @@ -1089,8 +1062,8 @@ namespace Apache.Ignite.Core.Impl.Binary /// </returns> public IBinaryRawWriter GetRawWriter() { - if (_curRawPos == 0) - _curRawPos = _stream.Position; + if (_frame.RawPos == 0) + _frame.RawPos = _stream.Position; return this; } @@ -1159,121 +1132,122 @@ namespace Apache.Ignite.Core.Impl.Binary if (WriteBuilderSpecials(obj)) return; - // Suppose that we faced normal object and perform descriptor lookup. - IBinaryTypeDescriptor desc = _marsh.GetDescriptor(type); + // Are we dealing with a well-known type? + var handler = BinarySystemHandlers.GetWriteHandler(type); - if (desc != null) + if (handler != null) { - // Writing normal object. - var pos = _stream.Position; - - // Dealing with handles. - if (desc.Serializer.SupportsHandles && WriteHandle(pos, obj)) + if (handler.SupportsHandles && WriteHandle(_stream.Position, obj)) return; - // Skip header length as not everything is known now - _stream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current); - - // Preserve old frame. - int oldTypeId = _curTypeId; - IBinaryNameMapper oldConverter = _curConverter; - IBinaryIdMapper oldMapper = _curMapper; - int oldRawPos = _curRawPos; - var oldPos = _curPos; - - var oldStruct = _curStruct; + handler.Write(this, obj); - // Push new frame. - _curTypeId = desc.TypeId; - _curConverter = desc.NameMapper; - _curMapper = desc.IdMapper; - _curRawPos = 0; - _curPos = pos; + return; + } - _curStruct = new BinaryStructureTracker(desc, desc.WriterTypeStructure); - var schemaIdx = _schema.PushSchema(); + // Suppose that we faced normal object and perform descriptor lookup. + var desc = _marsh.GetDescriptor(type); - try - { - // Write object fields. - desc.Serializer.WriteBinary(obj, this); - var dataEnd = _stream.Position; + // Writing normal object. + var pos = _stream.Position; - // Write schema - var schemaOffset = dataEnd - pos; + // Dealing with handles. + if (desc.Serializer.SupportsHandles && WriteHandle(pos, obj)) + return; - int schemaId; - - var flags = desc.UserType - ? BinaryObjectHeader.Flag.UserType - : BinaryObjectHeader.Flag.None; + // Skip header length as not everything is known now + _stream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current); - if (Marshaller.CompactFooter && desc.UserType) - flags |= BinaryObjectHeader.Flag.CompactFooter; + // Write type name for unregistered types + if (!desc.IsRegistered) + WriteString(type.AssemblyQualifiedName); - var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags); + var headerSize = _stream.Position - pos; - if (hasSchema) - { - flags |= BinaryObjectHeader.Flag.HasSchema; + // Preserve old frame. + var oldFrame = _frame; - // Calculate and write header. - if (_curRawPos > 0) - _stream.WriteInt(_curRawPos - pos); // raw offset is in the last 4 bytes + // Push new frame. + _frame.RawPos = 0; + _frame.Pos = pos; + _frame.Struct = new BinaryStructureTracker(desc, desc.WriterTypeStructure); + _frame.HasCustomTypeData = false; - // Update schema in type descriptor - if (desc.Schema.Get(schemaId) == null) - desc.Schema.Add(schemaId, _schema.GetSchema(schemaIdx)); - } - else - schemaOffset = BinaryObjectHeader.Size; + var schemaIdx = _schema.PushSchema(); - if (_curRawPos > 0) - flags |= BinaryObjectHeader.Flag.HasRaw; + try + { + // Write object fields. + desc.Serializer.WriteBinary(obj, this); + var dataEnd = _stream.Position; - var len = _stream.Position - pos; + // Write schema + var schemaOffset = dataEnd - pos; - var comparer = BinaryUtils.GetEqualityComparer(desc); + int schemaId; + + var flags = desc.UserType + ? BinaryObjectHeader.Flag.UserType + : BinaryObjectHeader.Flag.None; - var hashCode = comparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size, - dataEnd - pos - BinaryObjectHeader.Size, _schema, schemaIdx, _marsh, desc); + if (_frame.HasCustomTypeData) + flags |= BinaryObjectHeader.Flag.CustomDotNetType; - var header = new BinaryObjectHeader(desc.TypeId, hashCode, len, schemaId, schemaOffset, flags); + if (Marshaller.CompactFooter && desc.UserType) + flags |= BinaryObjectHeader.Flag.CompactFooter; - BinaryObjectHeader.Write(header, _stream, pos); + var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags); - Stream.Seek(pos + len, SeekOrigin.Begin); // Seek to the end - } - finally + if (hasSchema) { - _schema.PopSchema(schemaIdx); + flags |= BinaryObjectHeader.Flag.HasSchema; + + // Calculate and write header. + if (_frame.RawPos > 0) + _stream.WriteInt(_frame.RawPos - pos); // raw offset is in the last 4 bytes + + // Update schema in type descriptor + if (desc.Schema.Get(schemaId) == null) + desc.Schema.Add(schemaId, _schema.GetSchema(schemaIdx)); } + else + schemaOffset = headerSize; + + if (_frame.RawPos > 0) + flags |= BinaryObjectHeader.Flag.HasRaw; + + var len = _stream.Position - pos; + + var comparer = BinaryUtils.GetEqualityComparer(desc); + + var hashCode = comparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size, + dataEnd - pos - BinaryObjectHeader.Size, _schema, schemaIdx, _marsh, desc); - // Apply structure updates if any. - _curStruct.UpdateWriterStructure(this); + var header = new BinaryObjectHeader(desc.IsRegistered ? desc.TypeId : BinaryUtils.TypeUnregistered, + hashCode, len, schemaId, schemaOffset, flags); - // Restore old frame. - _curTypeId = oldTypeId; - _curConverter = oldConverter; - _curMapper = oldMapper; - _curRawPos = oldRawPos; - _curPos = oldPos; + BinaryObjectHeader.Write(header, _stream, pos); - _curStruct = oldStruct; + Stream.Seek(pos + len, SeekOrigin.Begin); // Seek to the end } - else + finally { - // Are we dealing with a well-known type? - var handler = BinarySystemHandlers.GetWriteHandler(type); + _schema.PopSchema(schemaIdx); + } - if (handler == null) // We did our best, object cannot be marshalled. - throw BinaryUtils.GetUnsupportedTypeException(type, obj); - - if (handler.SupportsHandles && WriteHandle(_stream.Position, obj)) - return; + // Apply structure updates if any. + _frame.Struct.UpdateWriterStructure(this); - handler.Write(this, obj); - } + // Restore old frame. + _frame = oldFrame; + } + + /// <summary> + /// Marks current object with a custom type data flag. + /// </summary> + public void SetCustomTypeDataFlag(bool hasCustomTypeData) + { + _frame.HasCustomTypeData = hasCustomTypeData; } /// <summary> @@ -1455,12 +1429,12 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="fieldTypeId">Field type ID.</param> private void WriteFieldId(string fieldName, byte fieldTypeId) { - if (_curRawPos != 0) + if (_frame.RawPos != 0) throw new BinaryObjectException("Cannot write named fields after raw data is written."); - var fieldId = _curStruct.GetFieldId(fieldName, fieldTypeId); + var fieldId = _frame.Struct.GetFieldId(fieldName, fieldTypeId); - _schema.PushField(fieldId, _stream.Position - _curPos); + _schema.PushField(fieldId, _stream.Position - _frame.Pos); } /// <summary> @@ -1489,5 +1463,23 @@ namespace Apache.Ignite.Core.Impl.Binary _metas[desc.TypeId] = new BinaryType(desc, fields); } } + + /// <summary> + /// Stores current writer stack frame. + /// </summary> + private struct Frame + { + /** Current object start position. */ + public int Pos; + + /** Current raw position. */ + public int RawPos; + + /** Current type structure tracker. */ + public BinaryStructureTracker Struct; + + /** Custom type data. */ + public bool HasCustomTypeData; + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs deleted file mode 100644 index 21c56a9..0000000 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.Diagnostics; - using Apache.Ignite.Core.Binary; - - /// <summary> - /// Wraps DateTime item in a binarizable. - /// </summary> - internal struct DateTimeHolder : IBinaryWriteAware - { - /** */ - private readonly DateTime _item; - - /// <summary> - /// Constructor. - /// </summary> - /// <param name="item">The item to wrap.</param> - public DateTimeHolder(DateTime item) - { - _item = item; - } - - /// <summary> - /// Constructor. - /// </summary> - /// <param name="reader">The reader.</param> - public DateTimeHolder(IBinaryRawReader reader) - { - Debug.Assert(reader != null); - - _item = DateTime.FromBinary(reader.ReadLong()); - } - - /// <summary> - /// Gets the item to wrap. - /// </summary> - public DateTime Item - { - get { return _item; } - } - - /** <inheritDoc /> */ - public void WriteBinary(IBinaryWriter writer) - { - Debug.Assert(writer != null); - - writer.GetRawWriter().WriteLong(_item.ToBinary()); - } - - /** <inheritDoc /> */ - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is DateTimeHolder && Equals((DateTimeHolder) obj); - } - - /** <inheritDoc /> */ - public override int GetHashCode() - { - return _item.GetHashCode(); - } - - /** <inheritDoc /> */ - public static bool operator ==(DateTimeHolder left, DateTimeHolder right) - { - return left.Equals(right); - } - - /** <inheritDoc /> */ - public static bool operator !=(DateTimeHolder left, DateTimeHolder right) - { - return !left.Equals(right); - } - - /// <summary> - /// Checks equality. - /// </summary> - private bool Equals(DateTimeHolder other) - { - return _item.Equals(other._item); - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs deleted file mode 100644 index bea7d58..0000000 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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> - /// DateTime serializer. - /// </summary> - internal class DateTimeSerializer : IBinarySerializerInternal - { - /** <inheritdoc /> */ - public void WriteBinary<T>(T obj, BinaryWriter writer) - { - TypeCaster<DateTimeHolder>.Cast(obj).WriteBinary(writer); - } - - /** <inheritdoc /> */ - public T ReadBinary<T>(BinaryReader reader, Type type, int pos) - { - var holder = new DateTimeHolder(reader); - - return TypeCaster<T>.Cast(holder.Item); - } - - /** <inheritdoc /> */ - public bool SupportsHandles - { - get { return false; } - } - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs new file mode 100644 index 0000000..3b21946 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs @@ -0,0 +1,102 @@ +/* + * 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.Collections.Generic; + using System.Runtime.Serialization; + using System.Threading; + + /// <summary> + /// Tracks object graph and invokes <see cref="IDeserializationCallback" />. + /// <para /> + /// <see cref="IDeserializationCallback.OnDeserialization" /> must be called after entire object graph has been + /// deserialized. We preserve all objects in a thread-local list and invoke callbacks once all objects + /// are fully deserialized. + /// </summary> + internal static class DeserializationCallbackProcessor + { + /// <summary> + /// Object graph for current thread. + /// </summary> + private static readonly ThreadLocal<ObjectGraph> Graph + = new ThreadLocal<ObjectGraph>(() => new ObjectGraph()); + + /// <summary> + /// Register an object for deserialization callback. + /// </summary> + /// <param name="obj">The object.</param> + /// <returns>Id of the object.</returns> + public static void Push(object obj) + { + var graph = Graph.Value; + + graph.Depth++; + + var cb = obj as IDeserializationCallback; + + if (cb != null) + { + graph.Objects.Add(cb); + } + } + + /// <summary> + /// Called when deserialization of an object has completed. + /// When Pop() has been called for all registered objects, all callbacks are invoked. + /// </summary> + public static void Pop() + { + var graph = Graph.Value; + + graph.Depth--; + + if (graph.Depth == 0) + { + // Entire graph has been deserialized: invoke callbacks in direct order (like BinaryFormatter does). + foreach (var obj in graph.Objects) + { + obj.OnDeserialization(null); + } + + graph.Objects.Clear(); + } + } + + /// <summary> + /// Object graph. + /// </summary> + private class ObjectGraph + { + /** */ + private readonly List<IDeserializationCallback> _objects = new List<IDeserializationCallback>(); + + /// <summary> + /// Gets or sets the depth. + /// </summary> + public int Depth { get; set; } + + /// <summary> + /// Gets the objects. + /// </summary> + public List<IDeserializationCallback> Objects + { + get { return _objects; } + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs index 58844d6..b775999 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs @@ -17,8 +17,6 @@ namespace Apache.Ignite.Core.Impl.Binary { - using System; - /// <summary> /// Internal generic serializer interface. /// </summary> @@ -32,7 +30,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// <summary> /// Read binary object. /// </summary> - T ReadBinary<T>(BinaryReader reader, Type type, int pos); + T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos); /// <summary> /// Gets a value indicating whether this serializer supports handles. http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs index 6c7e360..6bec70f 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs @@ -112,5 +112,13 @@ namespace Apache.Ignite.Core.Impl.Binary /// Gets the schema. /// </summary> BinaryObjectSchema Schema { get; } + + /// <summary> + /// Gets a value indicating whether this descriptor is registered in the cluster. + /// </summary> + /// <value> + /// <c>true</c> if this instance is registered; otherwise, <c>false</c>. + /// </value> + bool IsRegistered { get; } } }
