IGNITE-1665: Avoid field ID re-calculation during reads.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f85c6a3e Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f85c6a3e Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f85c6a3e Branch: refs/heads/ignite-1655 Commit: f85c6a3e6b81e9a3c22bcb5a301cad1dc5b57e8a Parents: d85fa94 Author: Pavel Tupitsyn <[email protected]> Authored: Thu Oct 22 12:58:29 2015 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Thu Oct 22 12:58:29 2015 +0300 ---------------------------------------------------------------------- .../Apache.Ignite.Benchmarks.csproj | 1 + .../Apache.Ignite.Benchmarks/BenchmarkRunner.cs | 2 +- .../Portable/PortableReadBenchmark.cs | 126 ++++++++++++++++++ .../Portable/PortableStructureTest.cs | 21 +-- .../Apache.Ignite.Core.csproj | 1 + .../Impl/Portable/IPortableTypeDescriptor.cs | 21 ++- .../Impl/Portable/PortableFullTypeDescriptor.cs | 29 +++- .../Impl/Portable/PortableReaderImpl.cs | 26 ++-- .../Portable/PortableSurrogateTypeDescriptor.cs | 27 +++- .../Impl/Portable/PortableUtils.cs | 12 +- .../Impl/Portable/PortableWriterImpl.cs | 79 +---------- .../Portable/Structure/PortableStructure.cs | 4 +- .../Structure/PortableStructureEntry.cs | 2 +- .../Structure/PortableStructureTracker.cs | 132 +++++++++++++++++++ 14 files changed, 355 insertions(+), 128 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj ---------------------------------------------------------------------- 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 a85b189..26e4fff 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj @@ -57,6 +57,7 @@ <Compile Include="Model\Employee.cs" /> <Compile Include="Model\Sex.cs" /> <Compile Include="Model\TestModel.cs" /> + <Compile Include="Portable\PortableReadBenchmark.cs" /> <Compile Include="Portable\PortableWriteBenchmark.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Result\BenchmarkConsoleResultWriter.cs" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs index 506106e..2d0d348 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs @@ -35,7 +35,7 @@ namespace Apache.Ignite.Benchmarks public static void Main(string[] args) { args = new[] { - typeof(PortableWriteBenchmark).FullName, + typeof(PortableReadBenchmark).FullName, "-ConfigPath", @"modules\platforms\dotnet\Apache.Ignite.Benchmarks\Config\benchmark.xml", "-Threads", "1", "-Warmup", "0", http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Portable/PortableReadBenchmark.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Portable/PortableReadBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Portable/PortableReadBenchmark.cs new file mode 100644 index 0000000..4df225e --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Portable/PortableReadBenchmark.cs @@ -0,0 +1,126 @@ +/* + * 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.Benchmarks.Portable +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Apache.Ignite.Benchmarks.Model; + using Apache.Ignite.Core.Impl.Memory; + using Apache.Ignite.Core.Impl.Portable; + using Apache.Ignite.Core.Portable; + + /// <summary> + /// Portable read benchmark. + /// </summary> + internal class PortableReadBenchmark : BenchmarkBase + { + /** Marshaller. */ + private readonly PortableMarshaller _marsh; + + /** Memory manager. */ + private readonly PlatformMemoryManager _memMgr = new PlatformMemoryManager(1024); + + /** Memory chunk. */ + private readonly IPlatformMemory _mem; + + /** Pre-allocated address. */ + private readonly Address _address = BenchmarkUtils.GetRandomAddress(); + + + /** Pre-allocated model. */ + private readonly TestModel _model = new TestModel + { + Byte = 5, + Boolean = true, + BooleanArray = new[] {true, false, false, false, true, true}, + ByteArray = new byte[] {128, 1, 2, 3, 5, 6, 8, 9, 14}, + Char = 'h', + CharArray = new[] {'b', 'n', 'm', 'q', 'w', 'e', 'r', 't', 'y'}, + Date = DateTime.Now, + DateArray = Enumerable.Range(1, 15).Select(x => (DateTime?) DateTime.Now.AddDays(x)).ToArray(), + Decimal = decimal.MinValue, + DecimalArray = new decimal?[] {1.1M, decimal.MinValue, decimal.MaxValue, decimal.MinusOne, decimal.One}, + Double = double.MaxValue/2, + DoubleArray = new[] {double.MaxValue, double.MinValue, double.Epsilon, double.NegativeInfinity}, + Float = 98, + FloatArray = new[] {float.MinValue, float.MaxValue, 10F, 36F}, + Guid = Guid.NewGuid(), + GuidArray = Enumerable.Range(1, 9).Select(x => (Guid?) Guid.NewGuid()).ToArray(), + Int = -90, + IntArray = new[] {128, 1, 2, 3, 5, 6, 8, 9, 14}, + Long = long.MinValue, + LongArray = Enumerable.Range(1, 12).Select(x => (long) x).ToArray(), + Short = 67, + ShortArray = Enumerable.Range(100, 12).Select(x => (short) x).ToArray(), + String = "String value test 123", + StringArray = Enumerable.Range(1, 13).Select(x => Guid.NewGuid().ToString()).ToArray() + }; + + /// <summary> + /// Initializes a new instance of the <see cref="PortableReadBenchmark"/> class. + /// </summary> + public PortableReadBenchmark() + { + _marsh = new PortableMarshaller(new PortableConfiguration + { + TypeConfigurations = new List<PortableTypeConfiguration> + { + new PortableTypeConfiguration(typeof (Address)) {MetadataEnabled = true}, + new PortableTypeConfiguration(typeof (TestModel)) {MetadataEnabled = false} + } + }); + + _mem = _memMgr.Allocate(); + + var stream = _mem.GetStream(); + + //_marsh.StartMarshal(stream).Write(_model); + _marsh.StartMarshal(stream).Write(_address); + + stream.SynchronizeOutput(); + } + + /// <summary> + /// Populate descriptors. + /// </summary> + /// <param name="descs">Descriptors.</param> + protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs) + { + descs.Add(BenchmarkOperationDescriptor.Create("ReadTestModel", ReadTestModel, 1)); + } + + /// <summary> + /// Write address. + /// </summary> + /// <param name="state">State.</param> + private void ReadTestModel(BenchmarkState state) + { + //var model = _marsh.StartUnmarshal(_mem.GetStream()).ReadObject<TestModel>(); + + //if (model.Byte != _model.Byte) + // throw new InvalidOperationException(); + + var model = _marsh.StartUnmarshal(_mem.GetStream()).ReadObject<Address>(); + + if (model.FlatNumber != _address.FlatNumber) + throw new InvalidOperationException(); + + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableStructureTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableStructureTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableStructureTest.cs index 580522e..4baebde 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableStructureTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableStructureTest.cs @@ -19,9 +19,9 @@ namespace Apache.Ignite.Core.Tests.Portable { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Apache.Ignite.Core.Impl; using Apache.Ignite.Core.Impl.Portable; - using Apache.Ignite.Core.Impl.Portable.Structure; using Apache.Ignite.Core.Portable; using NUnit.Framework; @@ -80,26 +80,15 @@ namespace Apache.Ignite.Core.Tests.Portable Console.WriteLine(); // 4. Ensure that all fields are recorded. - IPortableTypeDescriptor desc = marsh.GetDescriptor(typeof (BranchedType)); + var desc = marsh.GetDescriptor(typeof (BranchedType)); - PortableStructure typeStruct = desc.TypeStructure; - - IDictionary<string, byte> fields = typeStruct.FieldTypes; - - Assert.IsTrue(fields.Count == 8); - - Assert.IsTrue(fields.ContainsKey("mode")); - Assert.IsTrue(fields.ContainsKey("f2")); - Assert.IsTrue(fields.ContainsKey("f3")); - Assert.IsTrue(fields.ContainsKey("f4")); - Assert.IsTrue(fields.ContainsKey("f5")); - Assert.IsTrue(fields.ContainsKey("f6")); - Assert.IsTrue(fields.ContainsKey("f7")); - Assert.IsTrue(fields.ContainsKey("f8")); + CollectionAssert.AreEquivalent(new[] {"mode", "f2", "f3", "f4", "f5", "f6", "f7", "f8"}, + desc.WriterTypeStructure.FieldTypes.Keys); } } } + [SuppressMessage("ReSharper", "InconsistentNaming")] public class BranchedType : IPortableMarshalAware { public int mode; http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/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 9bcb41a..a45d6ed 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -270,6 +270,7 @@ <Compile Include="Impl\Portable\PortableReflectiveRoutines.cs" /> <Compile Include="Impl\Portable\PortableReflectiveSerializer.cs" /> <Compile Include="Impl\Portable\PortablesImpl.cs" /> + <Compile Include="Impl\Portable\Structure\PortableStructureTracker.cs" /> <Compile Include="Impl\Portable\PortableSurrogateTypeDescriptor.cs" /> <Compile Include="Impl\Portable\PortableSystemHandlers.cs" /> <Compile Include="Impl\Portable\PortableSystemTypeSerializer.cs" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs index 81b6c8d..3872773 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs @@ -109,16 +109,29 @@ namespace Apache.Ignite.Core.Impl.Portable } /// <summary> - /// Type structure. + /// Write type structure. /// </summary> - PortableStructure TypeStructure { get; } + PortableStructure WriterTypeStructure { get; } /// <summary> - /// Update type structure. + /// Read type structure. + /// </summary> + PortableStructure ReaderTypeStructure { get; } + + /// <summary> + /// Update write type structure. + /// </summary> + /// <param name="exp">Expected type structure.</param> + /// <param name="pathIdx">Path index.</param> + /// <param name="updates">Recorded updates.</param> + void UpdateWriteStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates); + + /// <summary> + /// Update read type structure. /// </summary> /// <param name="exp">Expected type structure.</param> /// <param name="pathIdx">Path index.</param> /// <param name="updates">Recorded updates.</param> - void UpdateStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates); + void UpdateReadStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs index ecad8ba..312cefa 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs @@ -59,7 +59,10 @@ namespace Apache.Ignite.Core.Impl.Portable private readonly string _affKeyFieldName; /** Type structure. */ - private volatile PortableStructure _typeStruct = PortableStructure.CreateEmpty(); + private volatile PortableStructure _writerTypeStruct = PortableStructure.CreateEmpty(); + + /** Type structure. */ + private volatile PortableStructure _readerTypeStructure = PortableStructure.CreateEmpty(); /// <summary> /// Constructor. @@ -179,18 +182,34 @@ namespace Apache.Ignite.Core.Impl.Portable } /** <inheritDoc /> */ - public PortableStructure TypeStructure + public PortableStructure WriterTypeStructure + { + get { return _writerTypeStruct; } + } + + /** <inheritDoc /> */ + public PortableStructure ReaderTypeStructure + { + get { return _readerTypeStructure; } + } + + /** <inheritDoc /> */ + public void UpdateWriteStructure(PortableStructure exp, int pathIdx, + IList<PortableStructureUpdate> updates) { - get { return _typeStruct; } + lock (this) + { + _writerTypeStruct = _writerTypeStruct.Merge(exp, pathIdx, updates); + } } /** <inheritDoc /> */ - public void UpdateStructure(PortableStructure exp, int pathIdx, + public void UpdateReadStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates) { lock (this) { - _typeStruct = _typeStruct.Merge(exp, pathIdx, updates); + _readerTypeStructure = _readerTypeStructure.Merge(exp, pathIdx, updates); } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs index ff9aa34..dd78702 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs @@ -25,6 +25,7 @@ namespace Apache.Ignite.Core.Impl.Portable using System.Runtime.Serialization; using Apache.Ignite.Core.Impl.Common; using Apache.Ignite.Core.Impl.Portable.IO; + using Apache.Ignite.Core.Impl.Portable.Structure; using Apache.Ignite.Core.Portable; /// <summary> @@ -53,12 +54,6 @@ namespace Apache.Ignite.Core.Impl.Portable /** Current raw data offset. */ private int _curRawOffset; - /** Current converter. */ - private IPortableNameMapper _curConverter; - - /** Current mapper. */ - private IPortableIdMapper _curMapper; - /** Current raw flag. */ private bool _curRaw; @@ -68,6 +63,10 @@ namespace Apache.Ignite.Core.Impl.Portable /** Portable read mode. */ private PortableMode _mode; + /** Current type structure tracker. */ + private PortableStructureTracker _curStruct; + + /// <summary> /// Constructor. /// </summary> @@ -449,7 +448,7 @@ namespace Apache.Ignite.Core.Impl.Portable if (_curRaw) throw new PortableException("Cannot read named fields after raw data is read."); - int fieldId = PortableUtils.FieldId(_curTypeId, fieldName, _curConverter, _curMapper); + int fieldId = _curStruct.GetFieldId(fieldName); if (SeekField(fieldId)) return Deserialize<T>(); @@ -747,16 +746,14 @@ namespace Apache.Ignite.Core.Impl.Portable int oldTypeId = _curTypeId; int oldPos = _curPos; int oldRawOffset = _curRawOffset; - IPortableNameMapper oldConverter = _curConverter; - IPortableIdMapper oldMapper = _curMapper; + var oldStruct = _curStruct; bool oldRaw = _curRaw; // Set new frame. _curTypeId = typeId; _curPos = pos; _curRawOffset = rawOffset; - _curConverter = desc.NameConverter; - _curMapper = desc.Mapper; + _curStruct = new PortableStructureTracker(desc, desc.ReaderTypeStructure); _curRaw = false; // Read object. @@ -784,12 +781,13 @@ namespace Apache.Ignite.Core.Impl.Portable desc.Serializer.ReadPortable(obj, this); } + _curStruct.UpdateReaderStructure(); + // Restore old frame. _curTypeId = oldTypeId; _curPos = oldPos; _curRawOffset = oldRawOffset; - _curConverter = oldConverter; - _curMapper = oldMapper; + _curStruct = oldStruct; _curRaw = oldRaw; var wrappedSerializable = obj as SerializableObjectHolder; @@ -952,7 +950,7 @@ namespace Apache.Ignite.Core.Impl.Portable if (_curRaw) throw new PortableException("Cannot read named fields after raw data is read."); - var fieldId = PortableUtils.FieldId(_curTypeId, fieldName, _curConverter, _curMapper); + var fieldId = _curStruct.GetFieldId(fieldName); if (!SeekField(fieldId)) return false; http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs index 8dc18b6..8560ce8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs @@ -39,7 +39,10 @@ namespace Apache.Ignite.Core.Impl.Portable private readonly string _name; /** Type structure. */ - private volatile PortableStructure _typeStruct = PortableStructure.CreateEmpty(); + private volatile PortableStructure _writerTypeStruct = PortableStructure.CreateEmpty(); + + /** Type structure. */ + private PortableStructure _readerTypeStructure = PortableStructure.CreateEmpty(); /// <summary> /// Constructor. @@ -126,17 +129,31 @@ namespace Apache.Ignite.Core.Impl.Portable } /** <inheritDoc /> */ - public PortableStructure TypeStructure + public PortableStructure WriterTypeStructure + { + get { return _writerTypeStruct; } + } + + public PortableStructure ReaderTypeStructure + { + get { return _readerTypeStructure; } + } + + /** <inheritDoc /> */ + public void UpdateWriteStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates) { - get { return _typeStruct; } + lock (this) + { + _writerTypeStruct = _writerTypeStruct.Merge(exp, pathIdx, updates); + } } /** <inheritDoc /> */ - public void UpdateStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates) + public void UpdateReadStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates) { lock (this) { - _typeStruct = _typeStruct.Merge(exp, pathIdx, updates); + _readerTypeStructure = _readerTypeStructure.Merge(exp, pathIdx, updates); } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs index 15466d5..ed8d5e1 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs @@ -1558,16 +1558,14 @@ namespace Apache.Ignite.Core.Impl.Portable { if (val == null) return 0; + int hash = 0; - for (int i = 0; i < val.Length; i++) + unchecked { - char c = val[i]; - - if ('A' <= c && c <= 'Z') - c = (char)(c | 0x20); - - hash = 31 * hash + c; + // ReSharper disable once LoopCanBeConvertedToQuery (performance) + foreach (var c in val) + hash = 31 * hash + ('A' <= c && c <= 'Z' ? c | 0x20 : c); } return hash; http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs index 5a66a0f..ffa475e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs @@ -61,17 +61,8 @@ namespace Apache.Ignite.Core.Impl.Portable /** Current raw position. */ private long _curRawPos; - /** Current type structure. */ - private PortableStructure _curStruct; - - /** Current type structure path index. */ - private int _curStructPath; - - /** Current type structure action index. */ - private int _curStructAction; - - /** Current type structure updates. */ - private List<PortableStructureUpdate> _curStructUpdates; + /** Current type structure tracker, */ + private PortableStructureTracker _curStruct; /** Whether we are currently detaching an object. */ private bool _detaching; @@ -1205,10 +1196,7 @@ namespace Apache.Ignite.Core.Impl.Portable IPortableIdMapper oldMapper = _curMapper; long oldRawPos = _curRawPos; - PortableStructure oldStruct = _curStruct; - int oldStructPath = _curStructPath; - int oldStructAction = _curStructAction; - var oldStructUpdates = _curStructUpdates; + var oldStruct = _curStruct; // Push new frame. _curTypeId = desc.TypeId; @@ -1216,10 +1204,7 @@ namespace Apache.Ignite.Core.Impl.Portable _curMapper = desc.Mapper; _curRawPos = 0; - _curStruct = desc.TypeStructure; - _curStructPath = 0; - _curStructAction = 0; - _curStructUpdates = null; + _curStruct = new PortableStructureTracker(desc, desc.WriterTypeStructure); // Write object fields. desc.Serializer.WritePortable(obj, this); @@ -1235,23 +1220,7 @@ namespace Apache.Ignite.Core.Impl.Portable _stream.WriteInt(pos + PU.OffsetRaw, len); // Apply structure updates if any. - if (_curStructUpdates != null) - { - desc.UpdateStructure(_curStruct, _curStructPath, _curStructUpdates); - - IPortableMetadataHandler metaHnd = _marsh.GetMetadataHandler(desc); - - if (metaHnd != null) - { - foreach (var u in _curStructUpdates) - metaHnd.OnFieldWrite(u.FieldId, u.FieldName, u.FieldType); - - IDictionary<string, int> meta = metaHnd.OnObjectWriteFinished(); - - if (meta != null) - SaveMetadata(_curTypeId, desc.TypeName, desc.AffinityKeyFieldName, meta); - } - } + _curStruct.UpdateWriterStructure(this); // Restore old frame. _curTypeId = oldTypeId; @@ -1260,9 +1229,6 @@ namespace Apache.Ignite.Core.Impl.Portable _curRawPos = oldRawPos; _curStruct = oldStruct; - _curStructPath = oldStructPath; - _curStructAction = oldStructAction; - _curStructUpdates = oldStructUpdates; } else { @@ -1519,40 +1485,7 @@ namespace Apache.Ignite.Core.Impl.Portable if (_curRawPos != 0) throw new PortableException("Cannot write named fields after raw data is written."); - int action = _curStructAction++; - - int fieldId; - - if (_curStructUpdates == null) - { - fieldId = _curStruct.GetFieldId(fieldName, fieldTypeId, ref _curStructPath, action); - - if (fieldId == 0) - fieldId = GetNewFieldId(fieldName, fieldTypeId, action); - } - else - fieldId = GetNewFieldId(fieldName, fieldTypeId, action); - - _stream.WriteInt(fieldId); - } - - /// <summary> - /// Get ID for the new field and save structure update. - /// </summary> - /// <param name="fieldName">Field name.</param> - /// <param name="fieldTypeId">Field type ID.</param> - /// <param name="action">Action index.</param> - /// <returns>Field ID.</returns> - private int GetNewFieldId(string fieldName, byte fieldTypeId, int action) - { - int fieldId = PU.FieldId(_curTypeId, fieldName, _curConverter, _curMapper); - - if (_curStructUpdates == null) - _curStructUpdates = new List<PortableStructureUpdate>(); - - _curStructUpdates.Add(new PortableStructureUpdate(fieldName, fieldId, fieldTypeId, action)); - - return fieldId; + _stream.WriteInt(_curStruct.GetFieldId(fieldName, fieldTypeId)); } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructure.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructure.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructure.cs index 2d47755..5b97ef7 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructure.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructure.cs @@ -48,7 +48,7 @@ namespace Apache.Ignite.Core.Impl.Portable.Structure private readonly PortableStructureJumpTable[] _jumps; /** Field types. */ - private readonly IDictionary<string, byte> _fieldTypes; + private readonly IDictionary<string, byte> _fieldTypes; /// <summary> /// Constructor. @@ -318,7 +318,7 @@ namespace Apache.Ignite.Core.Impl.Portable.Structure newFieldTypes[update.FieldName] = update.FieldType; } - return newFieldTypes.Count == _fieldTypes.Count ? + return newFieldTypes.Count == _fieldTypes.Count ? this : new PortableStructure(_paths, _jumps, newFieldTypes); } http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureEntry.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureEntry.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureEntry.cs index 9476635..9b6d282 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureEntry.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureEntry.cs @@ -34,7 +34,7 @@ namespace Apache.Ignite.Core.Impl.Portable.Structure /** Field type. */ private readonly byte _type; - + /// <summary> /// Constructor for jump table entry. /// </summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/f85c6a3e/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs new file mode 100644 index 0000000..8cec87a --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.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.Portable.Structure +{ + using System.Collections.Generic; + + /// <summary> + /// Encapsulates logic for tracking field access and updating type descriptor structure. + /// </summary> + internal struct PortableStructureTracker + { + /** Current type structure. */ + private readonly IPortableTypeDescriptor _desc; + + /** Struct. */ + private readonly PortableStructure _portStruct; + + /** Current type structure path index. */ + private int _curStructPath; + + /** Current type structure action index. */ + private int _curStructAction; + + /** Current type structure updates. */ + private List<PortableStructureUpdate> _curStructUpdates; + + /// <summary> + /// Initializes a new instance of the <see cref="PortableStructureTracker" /> class. + /// </summary> + /// <param name="desc">The desc.</param> + /// <param name="portStruct">The structure to work with.</param> + public PortableStructureTracker(IPortableTypeDescriptor desc, PortableStructure portStruct) + { + _desc = desc; + _portStruct = portStruct; + _curStructPath = 0; + _curStructAction = 0; + _curStructUpdates = null; + } + + /// <summary> + /// Gets the field ID. + /// </summary> + public int GetFieldId(string fieldName, byte fieldTypeId = 0) + { + _curStructAction++; + + if (_curStructUpdates == null) + { + var fieldId = _portStruct.GetFieldId(fieldName, fieldTypeId, ref _curStructPath, + _curStructAction); + + if (fieldId != 0) + return fieldId; + } + + return GetNewFieldId(fieldName, fieldTypeId, _curStructAction); + } + + /// <summary> + /// Updates the type structure. + /// </summary> + public void UpdateReaderStructure() + { + if (_curStructUpdates != null) + _desc.UpdateReadStructure(_desc.ReaderTypeStructure, _curStructPath, _curStructUpdates); + } + + /// <summary> + /// Updates the type structure and metadata for the specified writer. + /// </summary> + /// <param name="writer">The writer.</param> + public void UpdateWriterStructure(PortableWriterImpl writer) + { + if (_curStructUpdates != null) + { + _desc.UpdateWriteStructure(_desc.WriterTypeStructure, _curStructPath, _curStructUpdates); + + var marsh = writer.Marshaller; + + var metaHnd = marsh.GetMetadataHandler(_desc); + + if (metaHnd != null) + { + foreach (var u in _curStructUpdates) + metaHnd.OnFieldWrite(u.FieldId, u.FieldName, u.FieldType); + + var meta = metaHnd.OnObjectWriteFinished(); + + if (meta != null) + writer.SaveMetadata(_desc.TypeId, _desc.TypeName, _desc.AffinityKeyFieldName, meta); + } + } + } + + /// <summary> + /// Get ID for the new field and save structure update. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="fieldTypeId">Field type ID.</param> + /// <param name="action">Action index.</param> + /// <returns> + /// Field ID. + /// </returns> + private int GetNewFieldId(string fieldName, byte fieldTypeId, int action) + { + var fieldId = PortableUtils.FieldId(_desc.TypeId, fieldName, _desc.NameConverter, _desc.Mapper); + + if (_curStructUpdates == null) + _curStructUpdates = new List<PortableStructureUpdate>(); + + _curStructUpdates.Add(new PortableStructureUpdate(fieldName, fieldId, fieldTypeId, action)); + + return fieldId; + } + } +} \ No newline at end of file
