IGNITE-6627 .NET: Fix repeated known metadata updates This closes #2876
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/92cbc6b3 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/92cbc6b3 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/92cbc6b3 Branch: refs/heads/ignite-3478-tree Commit: 92cbc6b33dd936de2163bf1ec340c2c9f567e039 Parents: c65399c Author: Pavel Tupitsyn <[email protected]> Authored: Thu Oct 19 12:36:39 2017 +0300 Committer: Pavel Tupitsyn <[email protected]> Committed: Thu Oct 19 12:36:39 2017 +0300 ---------------------------------------------------------------------- .../BasicSerializableObjectsTest.cs | 3 +- .../Impl/Binary/BinaryFullTypeDescriptor.cs | 19 ++- .../Binary/BinarySurrogateTypeDescriptor.cs | 8 +- .../Impl/Binary/IBinaryTypeDescriptor.cs | 6 +- .../Impl/Binary/Structure/BinaryStructure.cs | 147 +++++++++---------- .../Binary/Structure/BinaryStructureTracker.cs | 16 +- 6 files changed, 97 insertions(+), 102 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/92cbc6b3/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs index e9b5576..846cd4c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs @@ -44,12 +44,13 @@ namespace Apache.Ignite.Core.Tests.Binary.Serializable public void TestEmptyObjectOnline() { using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration())) + using (var ignite2 = Ignition.Start(TestUtils.GetTestConfiguration(name: "1"))) { var cache = ignite.CreateCache<int, EmptyObject>("c"); cache[1] = new EmptyObject(); - var res = cache[1]; + var res = ignite2.GetCache<int, EmptyObject>("c")[1]; Assert.IsNotNull(res); } http://git-wip-us.apache.org/repos/asf/ignite/blob/92cbc6b3/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 e38b5ba..50c8c27 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs @@ -55,7 +55,7 @@ namespace Apache.Ignite.Core.Impl.Binary private readonly string _affKeyFieldName; /** Type structure. */ - private volatile BinaryStructure _writerTypeStruct = BinaryStructure.CreateEmpty(); + private volatile BinaryStructure _writerTypeStruct; /** Type structure. */ private volatile BinaryStructure _readerTypeStructure = BinaryStructure.CreateEmpty(); @@ -230,22 +230,27 @@ namespace Apache.Ignite.Core.Impl.Binary } /** <inheritDoc /> */ - public void UpdateWriteStructure(BinaryStructure exp, int pathIdx, - IList<BinaryStructureUpdate> updates) + public void UpdateWriteStructure(int pathIdx, IList<BinaryStructureUpdate> updates) { lock (this) { - _writerTypeStruct = _writerTypeStruct.Merge(exp, pathIdx, updates); + if (_writerTypeStruct == null) + { + // Null struct serves as an indication of a binary type that has never been sent to the cluster, + // which is important for types without any fields. + _writerTypeStruct = BinaryStructure.CreateEmpty(); + } + + _writerTypeStruct = _writerTypeStruct.Merge(pathIdx, updates); } } /** <inheritDoc /> */ - public void UpdateReadStructure(BinaryStructure exp, int pathIdx, - IList<BinaryStructureUpdate> updates) + public void UpdateReadStructure(int pathIdx, IList<BinaryStructureUpdate> updates) { lock (this) { - _readerTypeStructure = _readerTypeStructure.Merge(exp, pathIdx, updates); + _readerTypeStructure = _readerTypeStructure.Merge(pathIdx, updates); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/92cbc6b3/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 737c7c4..6fece77 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs @@ -134,20 +134,20 @@ namespace Apache.Ignite.Core.Impl.Binary } /** <inheritDoc /> */ - public void UpdateWriteStructure(BinaryStructure exp, int pathIdx, IList<BinaryStructureUpdate> updates) + public void UpdateWriteStructure(int pathIdx, IList<BinaryStructureUpdate> updates) { lock (this) { - _writerTypeStruct = _writerTypeStruct.Merge(exp, pathIdx, updates); + _writerTypeStruct = _writerTypeStruct.Merge(pathIdx, updates); } } /** <inheritDoc /> */ - public void UpdateReadStructure(BinaryStructure exp, int pathIdx, IList<BinaryStructureUpdate> updates) + public void UpdateReadStructure(int pathIdx, IList<BinaryStructureUpdate> updates) { lock (this) { - _readerTypeStructure = _readerTypeStructure.Merge(exp, pathIdx, updates); + _readerTypeStructure = _readerTypeStructure.Merge(pathIdx, updates); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/92cbc6b3/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 4bd7e73..840fc08 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs @@ -90,18 +90,16 @@ namespace Apache.Ignite.Core.Impl.Binary /// <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(BinaryStructure exp, int pathIdx, IList<BinaryStructureUpdate> updates); + void UpdateWriteStructure(int pathIdx, IList<BinaryStructureUpdate> 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 UpdateReadStructure(BinaryStructure exp, int pathIdx, IList<BinaryStructureUpdate> updates); + void UpdateReadStructure(int pathIdx, IList<BinaryStructureUpdate> updates); /// <summary> /// Gets the schema. http://git-wip-us.apache.org/repos/asf/ignite/blob/92cbc6b3/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructure.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructure.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructure.cs index 92c841c..908059a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructure.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructure.cs @@ -118,14 +118,12 @@ namespace Apache.Ignite.Core.Impl.Binary.Structure /// <summary> /// Merge updates into a new type structure. /// </summary> - /// <param name="exp">Expected type structure to apply updates to </param> /// <param name="pathIdx">Path index.</param> /// <param name="updates">Updates.</param> /// <returns>New type structure with updates.</returns> - public BinaryStructure Merge(BinaryStructure exp, int pathIdx, - IList<BinaryStructureUpdate> updates) + public BinaryStructure Merge(int pathIdx, IList<BinaryStructureUpdate> updates) { - if (updates.Count == 0) + if (updates == null || updates.Count == 0) return this; // Algorithm ensures that updates are applied to the same type structure, @@ -137,102 +135,97 @@ namespace Apache.Ignite.Core.Impl.Binary.Structure // Note that field types are merged anyway to avoid metadata clashes. BinaryStructure res = MergeFieldTypes(updates); + BinaryStructureUpdate firstUpdate = updates[0]; - if (ReferenceEquals(exp, this)) + if (firstUpdate.Index == 0) { - BinaryStructureUpdate firstUpdate = updates[0]; + // Special case: the very first structure update. Simply attach all updates. + Debug.Assert(_paths.Length == 1); + Debug.Assert(_paths[0].Length == 0); + Debug.Assert(pathIdx == 0); - if (firstUpdate.Index == 0) - { - // Special case: the very first structure update. Simply attach all updates. - Debug.Assert(_paths.Length == 1); - Debug.Assert(_paths[0].Length == 0); - Debug.Assert(pathIdx == 0); - - var newPaths = CopyPaths(updates.Count, 0); + var newPaths = CopyPaths(updates.Count, 0); - ApplyUpdatesToPath(newPaths[0], updates); - - res = new BinaryStructure(newPaths, _jumps, res._fieldTypes); - } - else - { - // Get entry where updates should start. - BinaryStructureEntry[] path = _paths[pathIdx]; + ApplyUpdatesToPath(newPaths[0], updates); - BinaryStructureEntry startEntry = default(BinaryStructureEntry); - - if (firstUpdate.Index < path.Length) - startEntry = path[firstUpdate.Index]; + res = new BinaryStructure(newPaths, _jumps, res._fieldTypes); + } + else + { + // Get entry where updates should start. + BinaryStructureEntry[] path = _paths[pathIdx]; - if (startEntry.IsEmpty) - { - // We are on the empty/non-existent entry. Continue the path without branching. - var newPaths = CopyPaths(firstUpdate.Index + updates.Count, 0); + BinaryStructureEntry startEntry = default(BinaryStructureEntry); - ApplyUpdatesToPath(newPaths[pathIdx], updates); + if (firstUpdate.Index < path.Length) + startEntry = path[firstUpdate.Index]; - res = new BinaryStructure(newPaths, _jumps, res._fieldTypes); - } - else if (startEntry.IsJumpTable) - { - // We are on the jump table. Add a new path and record it in the jump table. - - // 1. Prepare new structures. - var newPaths = CopyPaths(firstUpdate.Index + updates.Count, 1); - var newJumps = CopyJumps(0); + if (startEntry.IsEmpty) + { + // We are on the empty/non-existent entry. Continue the path without branching. + var newPaths = CopyPaths(firstUpdate.Index + updates.Count, 0); - // New path will be the last one. - int newPathIdx = newPaths.Length - 1; + ApplyUpdatesToPath(newPaths[pathIdx], updates); - // Apply updates to the new path. - ApplyUpdatesToPath(newPaths[newPathIdx], updates); + res = new BinaryStructure(newPaths, _jumps, res._fieldTypes); + } + else if (startEntry.IsJumpTable) + { + // We are on the jump table. Add a new path and record it in the jump table. - // Add the jump to the table. - newJumps[startEntry.Id] = - newJumps[startEntry.Id].CopyAndAdd(firstUpdate.FieldName, newPathIdx); + // 1. Prepare new structures. + var newPaths = CopyPaths(firstUpdate.Index + updates.Count, 1); + var newJumps = CopyJumps(0); - res = new BinaryStructure(newPaths, newJumps, res._fieldTypes); - } - else - { - // We are on existing entry. Need to create a new jump table here and two new paths. + // New path will be the last one. + int newPathIdx = newPaths.Length - 1; - // 1. Prepaare new structures. - var newPaths = CopyPaths(firstUpdate.Index + updates.Count, 2); - var newJumps = CopyJumps(1); + // Apply updates to the new path. + ApplyUpdatesToPath(newPaths[newPathIdx], updates); - // Old path will be moved here. - int oldPathIdx = newPaths.Length - 2; + // Add the jump to the table. + newJumps[startEntry.Id] = + newJumps[startEntry.Id].CopyAndAdd(firstUpdate.FieldName, newPathIdx); - // New path will reside here. - int newPathIdx = newPaths.Length - 1; + res = new BinaryStructure(newPaths, newJumps, res._fieldTypes); + } + else + { + // We are on existing entry. Need to create a new jump table here and two new paths. - // Create new jump table. - int newJumpIdx = newJumps.Length - 1; + // 1. Prepaare new structures. + var newPaths = CopyPaths(firstUpdate.Index + updates.Count, 2); + var newJumps = CopyJumps(1); - newJumps[newJumpIdx] = new BinaryStructureJumpTable(startEntry.Name, oldPathIdx, - firstUpdate.FieldName, newPathIdx); + // Old path will be moved here. + int oldPathIdx = newPaths.Length - 2; - // Re-create old path in two steps: move old path to the new place, then clean the old path. - for (int i = firstUpdate.Index; i < path.Length; i++) - { - newPaths[oldPathIdx][i] = newPaths[pathIdx][i]; + // New path will reside here. + int newPathIdx = newPaths.Length - 1; - if (i == firstUpdate.Index) - // Inject jump table ... - newPaths[pathIdx][i] = new BinaryStructureEntry(newJumpIdx); - else - // ... or just reset. - newPaths[pathIdx][i] = new BinaryStructureEntry(); - } + // Create new jump table. + int newJumpIdx = newJumps.Length - 1; - // Apply updates to the new path. - ApplyUpdatesToPath(newPaths[newPaths.Length - 1], updates); + newJumps[newJumpIdx] = new BinaryStructureJumpTable(startEntry.Name, oldPathIdx, + firstUpdate.FieldName, newPathIdx); - res = new BinaryStructure(newPaths, newJumps, res._fieldTypes); + // Re-create old path in two steps: move old path to the new place, then clean the old path. + for (int i = firstUpdate.Index; i < path.Length; i++) + { + newPaths[oldPathIdx][i] = newPaths[pathIdx][i]; + + if (i == firstUpdate.Index) + // Inject jump table ... + newPaths[pathIdx][i] = new BinaryStructureEntry(newJumpIdx); + else + // ... or just reset. + newPaths[pathIdx][i] = new BinaryStructureEntry(); } + // Apply updates to the new path. + ApplyUpdatesToPath(newPaths[newPaths.Length - 1], updates); + + res = new BinaryStructure(newPaths, newJumps, res._fieldTypes); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/92cbc6b3/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructureTracker.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructureTracker.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructureTracker.cs index 3517342..ee2e7e1 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructureTracker.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Structure/BinaryStructureTracker.cs @@ -68,7 +68,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Structure { _curStructAction++; - if (_curStructUpdates == null) + if (_curStructUpdates == null && _portStruct != null) { var fieldId = _portStruct.GetFieldId(fieldName, fieldTypeId, ref _curStructPath, _curStructAction); @@ -86,7 +86,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Structure public void UpdateReaderStructure() { if (_curStructUpdates != null) - _desc.UpdateReadStructure(_desc.ReaderTypeStructure, _curStructPath, _curStructUpdates); + _desc.UpdateReadStructure(_curStructPath, _curStructUpdates); } /// <summary> @@ -97,7 +97,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Structure { if (_curStructUpdates != null) { - _desc.UpdateWriteStructure(_desc.WriterTypeStructure, _curStructPath, _curStructUpdates); + _desc.UpdateWriteStructure(_curStructPath, _curStructUpdates); var marsh = writer.Marshaller; @@ -115,15 +115,13 @@ namespace Apache.Ignite.Core.Impl.Binary.Structure writer.SaveMetadata(_desc, fields); } } - else + else if (_desc.WriterTypeStructure == null) { - // Special case when the object is with no properties. - // Save meta to Marshaller. + // Empty object (no fields). + // Null WriterTypeStructure indicates that meta has never been sent for this type. writer.Marshaller.GetBinaryTypeHandler(_desc); - - // Save meta to cluster. writer.SaveMetadata(_desc, null); - return; + _desc.UpdateWriteStructure(_curStructPath, null); } }
