Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id B94B2200C01 for ; Thu, 19 Jan 2017 11:35:16 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id B820D160B42; Thu, 19 Jan 2017 10:35:16 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 1467E160B54 for ; Thu, 19 Jan 2017 11:35:14 +0100 (CET) Received: (qmail 97502 invoked by uid 500); 19 Jan 2017 10:35:14 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 97465 invoked by uid 99); 19 Jan 2017 10:35:14 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 19 Jan 2017 10:35:14 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 02A95DFA43; Thu, 19 Jan 2017 10:35:13 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: ptupitsyn@apache.org To: commits@ignite.apache.org Date: Thu, 19 Jan 2017 10:35:14 -0000 Message-Id: <54ec1dc4ed55406daf75528997ec5d9f@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/8] ignite git commit: IGNITE-4045 .NET: Support DML API archived-at: Thu, 19 Jan 2017 10:35:16 -0000 http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 08789b6..ce9fcf6 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs @@ -157,8 +157,6 @@ { IgniteArgumentCheck.NotNull(configuration, "configuration"); - CopyLocalProperties(configuration); - using (var stream = IgniteManager.Memory.Allocate().GetStream()) { var marsh = new Marshaller(configuration.BinaryConfiguration); @@ -171,6 +169,8 @@ ReadCore(marsh.StartUnmarshal(stream)); } + + CopyLocalProperties(configuration); } /// @@ -255,12 +255,37 @@ writer.WriteBoolean(false); // Binary config - var isCompactFooterSet = BinaryConfiguration != null && BinaryConfiguration.CompactFooterInternal != null; + if (BinaryConfiguration != null) + { + writer.WriteBoolean(true); - writer.WriteBoolean(isCompactFooterSet); + if (BinaryConfiguration.CompactFooterInternal != null) + { + writer.WriteBoolean(true); + writer.WriteBoolean(BinaryConfiguration.CompactFooter); + } + else + { + writer.WriteBoolean(false); + } + + // 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 (isCompactFooterSet) - writer.WriteBoolean(BinaryConfiguration.CompactFooter); + foreach (var type in types) + { + writer.WriteString(BinaryUtils.SimpleTypeName(type.TypeName)); + writer.WriteBoolean(type.IsEnum); + BinaryEqualityComparerSerializer.Write(writer, type.EqualityComparer); + } + } + else + { + writer.WriteBoolean(false); + } // User attributes var attrs = UserAttributes; @@ -361,7 +386,28 @@ if (r.ReadBoolean()) { BinaryConfiguration = BinaryConfiguration ?? new BinaryConfiguration(); - BinaryConfiguration.CompactFooter = r.ReadBoolean(); + + if (r.ReadBoolean()) + BinaryConfiguration.CompactFooter = r.ReadBoolean(); + + var typeCount = r.ReadInt(); + + if (typeCount > 0) + { + var types = new List(typeCount); + + for (var i = 0; i < typeCount; i++) + { + types.Add(new BinaryTypeConfiguration + { + TypeName = r.ReadString(), + IsEnum = r.ReadBoolean(), + EqualityComparer = BinaryEqualityComparerSerializer.Read(r) + }); + } + + BinaryConfiguration.TypeConfigurations = types; + } } // User attributes @@ -402,17 +448,15 @@ /// The binary reader. private void Read(BinaryReader binaryReader) { - var r = binaryReader; - - CopyLocalProperties(r.Marshaller.Ignite.Configuration); + ReadCore(binaryReader); - ReadCore(r); + CopyLocalProperties(binaryReader.Marshaller.Ignite.Configuration); // Misc - IgniteHome = r.ReadString(); + IgniteHome = binaryReader.ReadString(); - JvmInitialMemoryMb = (int) (r.ReadLong()/1024/2014); - JvmMaxMemoryMb = (int) (r.ReadLong()/1024/2014); + JvmInitialMemoryMb = (int) (binaryReader.ReadLong()/1024/2014); + JvmMaxMemoryMb = (int) (binaryReader.ReadLong()/1024/2014); // Local data (not from reader) JvmDllPath = Process.GetCurrentProcess().Modules.OfType() @@ -426,9 +470,16 @@ private void CopyLocalProperties(IgniteConfiguration cfg) { GridName = cfg.GridName; - BinaryConfiguration = cfg.BinaryConfiguration == null - ? null - : new BinaryConfiguration(cfg.BinaryConfiguration); + + if (BinaryConfiguration != null && cfg.BinaryConfiguration != null) + { + BinaryConfiguration.MergeTypes(cfg.BinaryConfiguration); + } + else if (cfg.BinaryConfiguration != null) + { + BinaryConfiguration = new BinaryConfiguration(cfg.BinaryConfiguration); + } + JvmClasspath = cfg.JvmClasspath; JvmOptions = cfg.JvmOptions; Assemblies = cfg.Assemblies; http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd index b35527d..d54a200 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd @@ -152,6 +152,20 @@ + + + + Equality comparer to compute hash codes and compare objects in IBinaryObject form. + + + + + + Assembly-qualified type name. + + + + @@ -297,6 +311,11 @@ Java field type name. + + + Indicates whether this field belongs to the cache key. + + http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs index 3d55acd..fa7cf6c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs @@ -81,7 +81,7 @@ namespace Apache.Ignite.Core.Impl.Binary throw new IgniteException("Type is not binary (add it to BinaryConfiguration): " + type.FullName); - return Builder0(null, BinaryFromDescriptor(desc), desc); + return Builder0(null, null, desc); } /** */ @@ -91,7 +91,7 @@ namespace Apache.Ignite.Core.Impl.Binary IBinaryTypeDescriptor desc = _marsh.GetDescriptor(typeName); - return Builder0(null, BinaryFromDescriptor(desc), desc); + return Builder0(null, null, desc); } /** */ @@ -182,30 +182,6 @@ namespace Apache.Ignite.Core.Impl.Binary } /// - /// Create empty binary object from descriptor. - /// - /// Descriptor. - /// Empty binary object. - private BinaryObject BinaryFromDescriptor(IBinaryTypeDescriptor desc) - { - const int len = BinaryObjectHeader.Size; - - var flags = desc.UserType ? BinaryObjectHeader.Flag.UserType : BinaryObjectHeader.Flag.None; - - if (_marsh.CompactFooter && desc.UserType) - flags |= BinaryObjectHeader.Flag.CompactFooter; - - var hdr = new BinaryObjectHeader(desc.TypeId, 0, len, 0, len, flags); - - using (var stream = new BinaryHeapStream(len)) - { - BinaryObjectHeader.Write(hdr, stream, 0); - - return new BinaryObject(_marsh, stream.InternalArray, 0, hdr); - } - } - - /// /// Internal builder creation routine. /// /// Parent builder. http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs new file mode 100644 index 0000000..aa4795e --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Impl.Binary +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Apache.Ignite.Core.Binary; + + /// + /// Reads and writes . + /// + internal static class BinaryEqualityComparerSerializer + { + /// + /// SwapSpace type. + /// + private enum Type : byte + { + None = 0, + Array = 1, + Field = 2 + } + + /// + /// Writes an instance. + /// + public static void Write(IBinaryRawWriter writer, IBinaryEqualityComparer comparer) + { + if (comparer == null) + { + writer.WriteByte((byte) Type.None); + return; + } + + var arrCmp = comparer as BinaryArrayEqualityComparer; + + if (arrCmp != null) + { + writer.WriteByte((byte) Type.Array); + return; + } + + var fieldCmp = (BinaryFieldEqualityComparer) comparer; + + writer.WriteByte((byte) Type.Field); + + fieldCmp.Validate(); + + writer.WriteInt(fieldCmp.FieldNames.Count); + + foreach (var field in fieldCmp.FieldNames) + writer.WriteString(field); + } + + /// + /// Reads an instance. + /// + /// The reader. + /// + public static IEqualityComparer Read(IBinaryRawReader reader) + { + var type = (Type) reader.ReadByte(); + + switch (type) + { + case Type.None: + return null; + + case Type.Array: + return new BinaryArrayEqualityComparer(); + + case Type.Field: + return new BinaryFieldEqualityComparer + { + FieldNames = Enumerable.Range(0, reader.ReadInt()).Select(x => reader.ReadString()).ToArray() + }; + + default: + throw new ArgumentOutOfRangeException(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFieldEqualityComparer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFieldEqualityComparer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFieldEqualityComparer.cs new file mode 100644 index 0000000..433657a --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFieldEqualityComparer.cs @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Impl.Binary +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.IO; + using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Common; + using Apache.Ignite.Core.Impl.Binary.IO; + using Apache.Ignite.Core.Impl.Common; + + /// + /// Uses a set of binary object fields to calculate hash code and check equality. + /// Not implemented for now, will be done as part of IGNITE-4397. + /// + internal class BinaryFieldEqualityComparer : IEqualityComparer, IBinaryEqualityComparer + { + /// + /// Initializes a new instance of the class. + /// + public BinaryFieldEqualityComparer() + { + // No-op. + } + + /// + /// Initializes a new instance of the class. + /// + /// The field names for comparison. + public BinaryFieldEqualityComparer(params string[] fieldNames) + { + IgniteArgumentCheck.NotNullOrEmpty(fieldNames, "fieldNames"); + + FieldNames = fieldNames; + } + + /// + /// Gets or sets the field names to be used for equality comparison. + /// + public ICollection FieldNames { get; set; } + + /// + /// Determines whether the specified objects are equal. + /// + /// The first object to compare. + /// The second object to compare. + /// + /// true if the specified objects are equal; otherwise, false. + /// + public bool Equals(IBinaryObject x, IBinaryObject y) + { + throw new NotSupportedException(GetType() + "is not intended for direct usage."); + } + + /// + /// Returns a hash code for this instance. + /// + /// The object. + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public int GetHashCode(IBinaryObject obj) + { + throw new NotSupportedException(GetType() + "is not intended for direct usage."); + } + + /** */ + int IBinaryEqualityComparer.GetHashCode(IBinaryStream stream, int startPos, int length, + BinaryObjectSchemaHolder schema, int schemaId, Marshaller marshaller, IBinaryTypeDescriptor desc) + { + Debug.Assert(stream != null); + Debug.Assert(startPos >= 0); + Debug.Assert(length >= 0); + Debug.Assert(schema != null); + Debug.Assert(marshaller != null); + Debug.Assert(desc != null); + + Validate(); + + stream.Flush(); + + // Preserve stream position. + var pos = stream.Position; + + var reader = marshaller.StartUnmarshal(stream, BinaryMode.ForceBinary); + var fields = schema.GetFullSchema(schemaId); + + int hash = 0; + + foreach (var fieldName in FieldNames) + { + int fieldId = BinaryUtils.FieldId(desc.TypeId, fieldName, desc.NameMapper, desc.IdMapper); + int fieldHash = 0; // Null (missing) field hash code is 0. + int fieldPos; + + if (fields.TryGetValue(fieldId, out fieldPos)) + { + stream.Seek(startPos + fieldPos - BinaryObjectHeader.Size, SeekOrigin.Begin); + var fieldVal = reader.Deserialize(); + fieldHash = fieldVal != null ? fieldVal.GetHashCode() : 0; + } + + hash = 31 * hash + fieldHash; + } + + // Restore stream position. + stream.Seek(pos, SeekOrigin.Begin); + + return hash; + } + + /// + /// Validates this instance. + /// + public void Validate() + { + if (FieldNames == null || FieldNames.Count == 0) + throw new IgniteException("BinaryFieldEqualityComparer.FieldNames can not be null or empty."); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 6dc5d4d..d88e7a9 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs @@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Impl.Binary using System; using System.Collections.Generic; using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Common; using Apache.Ignite.Core.Impl.Binary.Structure; /// @@ -66,6 +67,9 @@ namespace Apache.Ignite.Core.Impl.Binary /** Enum flag. */ private readonly bool _isEnum; + /** Comparer. */ + private readonly IBinaryEqualityComparer _equalityComparer; + /// /// Constructor. /// @@ -79,6 +83,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// Whether to cache deserialized value in IBinaryObject /// Affinity field key name. /// Enum flag. + /// Equality comparer. public BinaryFullTypeDescriptor( Type type, int typeId, @@ -89,7 +94,8 @@ namespace Apache.Ignite.Core.Impl.Binary IBinarySerializerInternal serializer, bool keepDeserialized, string affKeyFieldName, - bool isEnum) + bool isEnum, + IEqualityComparer comparer) { _type = type; _typeId = typeId; @@ -101,6 +107,13 @@ namespace Apache.Ignite.Core.Impl.Binary _keepDeserialized = keepDeserialized; _affKeyFieldName = affKeyFieldName; _isEnum = isEnum; + + _equalityComparer = comparer as IBinaryEqualityComparer; + + if (comparer != null && _equalityComparer == null) + throw new IgniteException(string.Format("Unsupported IEqualityComparer " + + "implementation: {0}. Only predefined implementations " + + "are supported.", comparer.GetType())); } /// @@ -181,6 +194,12 @@ namespace Apache.Ignite.Core.Impl.Binary get { return _isEnum; } } + /** */ + public IBinaryEqualityComparer EqualityComparer + { + get { return _equalityComparer; } + } + /** */ public BinaryStructure WriterTypeStructure { http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs index 39a2f8b..0a14bd2 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs @@ -195,6 +195,14 @@ namespace Apache.Ignite.Core.Impl.Binary get { return _offset; } } + /// + /// Gets the header. + /// + public BinaryObjectHeader Header + { + get { return _header; } + } + public bool TryGetFieldPosition(string fieldName, out int pos) { var desc = _marsh.GetDescriptor(true, _header.TypeId); @@ -244,6 +252,14 @@ namespace Apache.Ignite.Core.Impl.Binary if (_data == that._data && _offset == that._offset) return true; + if (TypeId != that.TypeId) + return false; + + var desc = _marsh.GetDescriptor(true, TypeId); + + if (desc != null && desc.EqualityComparer != null) + return desc.EqualityComparer.Equals(this, that); + // 1. Check headers if (_header == that._header) { @@ -266,8 +282,21 @@ namespace Apache.Ignite.Core.Impl.Binary object fieldVal = GetField(field.Value, null); object thatFieldVal = that.GetField(that._fields[field.Key], null); - if (!Equals(fieldVal, thatFieldVal)) + var arr = fieldVal as Array; + var thatArr = thatFieldVal as Array; + + if (arr != null && thatArr != null && arr.Length == thatArr.Length) + { + for (var i = 0; i < arr.Length; i++) + { + if (!Equals(arr.GetValue(i), thatArr.GetValue(i))) + return false; + } + } + else if (!Equals(fieldVal, thatFieldVal)) + { return false; + } } // 4. Check if objects have the same raw data. http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 1626a2d..db18638 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs @@ -55,7 +55,7 @@ namespace Apache.Ignite.Core.Impl.Binary private IDictionary _cache; /** Hash code. */ - private int _hashCode; + private int? _hashCode; /** Current context. */ private Context _ctx; @@ -87,15 +87,21 @@ namespace Apache.Ignite.Core.Impl.Binary BinaryObject obj, IBinaryTypeDescriptor desc) { Debug.Assert(binary != null); - Debug.Assert(obj != null); Debug.Assert(desc != null); _binary = binary; _parent = parent ?? this; - _obj = obj; _desc = desc; - _hashCode = obj.GetHashCode(); + if (obj != null) + { + _obj = obj; + _hashCode = obj.GetHashCode(); + } + else + { + _obj = BinaryFromDescriptor(desc); + } } /** */ @@ -508,7 +514,7 @@ namespace Apache.Ignite.Core.Impl.Binary BinaryHeapStream inStream, BinaryHeapStream outStream, IBinaryTypeDescriptor desc, - int hashCode, + int? hashCode, IDictionary vals) { // Set correct builder to writer frame. @@ -578,7 +584,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// Values to be replaced. /// Mutated object. private void Mutate0(Context ctx, BinaryHeapStream inStream, IBinaryStream outStream, - bool changeHash, int hash, IDictionary vals) + bool changeHash, int? hash, IDictionary vals) { int inStartPos = inStream.Position; int outStartPos = outStream.Position; @@ -730,7 +736,25 @@ namespace Apache.Ignite.Core.Impl.Binary var outLen = outStream.Position - outStartPos; - var outHash = changeHash ? hash : inHeader.HashCode; + var outHash = inHeader.HashCode; + + if (changeHash) + { + if (hash != null) + { + outHash = hash.Value; + } + else + { + // Get from identity resolver. + outHash = _desc.EqualityComparer != null + ? _desc.EqualityComparer.GetHashCode(outStream, + outStartPos + BinaryObjectHeader.Size, + schemaPos - outStartPos - BinaryObjectHeader.Size, + outSchema, outSchemaId, _binary.Marshaller, _desc) + : 0; + } + } var outHeader = new BinaryObjectHeader(inHeader.TypeId, outHash, outLen, outSchemaId, outSchemaOff, flags); @@ -1027,6 +1051,30 @@ namespace Apache.Ignite.Core.Impl.Binary } /// + /// Create empty binary object from descriptor. + /// + /// Descriptor. + /// Empty binary object. + private BinaryObject BinaryFromDescriptor(IBinaryTypeDescriptor desc) + { + const int len = BinaryObjectHeader.Size; + + var flags = desc.UserType ? BinaryObjectHeader.Flag.UserType : BinaryObjectHeader.Flag.None; + + if (_binary.Marshaller.CompactFooter && desc.UserType) + flags |= BinaryObjectHeader.Flag.CompactFooter; + + var hdr = new BinaryObjectHeader(desc.TypeId, 0, len, 0, len, flags); + + using (var stream = new BinaryHeapStream(len)) + { + BinaryObjectHeader.Write(hdr, stream, 0); + + return new BinaryObject(_binary.Marshaller, stream.InternalArray, 0, hdr); + } + } + + /// /// Mutation context. /// private class Context http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 0e5ad2a..636b177 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs @@ -211,21 +211,40 @@ namespace Apache.Ignite.Core.Impl.Binary /// Gets the raw offset of this object in specified stream. /// /// The stream. - /// The position. + /// The binary object position in the stream. /// Raw offset. public int GetRawOffset(IBinaryStream stream, int position) { Debug.Assert(stream != null); + // Either schema or raw is not present - offset is in the header. if (!HasRaw || !HasSchema) return SchemaOffset; + // Both schema and raw data are present: raw offset is in the last 4 bytes. stream.Seek(position + Length - 4, SeekOrigin.Begin); return stream.ReadInt(); } /// + /// Gets the footer offset where raw and non-raw data ends. + /// + /// Footer offset. + public int FooterStartOffset + { + get + { + // No schema: all we have is data. There is no offset in last 4 bytes. + if (!HasSchema) + return Length; + + // There is schema. Regardless of raw data presence, footer starts with schema. + return SchemaOffset; + } + } + + /// /// Writes specified header to a stream. /// /// The header. http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaHolder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaHolder.cs index c95746a..8ad78a4 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaHolder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaHolder.cs @@ -18,6 +18,7 @@ namespace Apache.Ignite.Core.Impl.Binary { using System; + using System.Collections.Generic; using System.Threading; using Apache.Ignite.Core.Impl.Binary.IO; using Apache.Ignite.Core.Impl.Common; @@ -119,5 +120,26 @@ namespace Apache.Ignite.Core.Impl.Binary return result; } + + /// + /// Gets the schema. + /// + /// The schema offset. + /// Current schema as a dictionary. + public Dictionary GetFullSchema(int schemaOffset) + { + var size = _idx - schemaOffset; + + var result = new Dictionary(size); + + for (int i = schemaOffset; i < _idx; i++) + { + var fld = _fields[i]; + + result[fld.Id] = fld.Offset; + } + + return result; + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 b572e7c..adba577 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs @@ -130,6 +130,12 @@ namespace Apache.Ignite.Core.Impl.Binary get { return false; } } + /** */ + public IBinaryEqualityComparer EqualityComparer + { + get { return null; } + } + /** */ public BinaryStructure WriterTypeStructure { http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 ccb2d1b..bdd7137 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs @@ -614,7 +614,9 @@ namespace Apache.Ignite.Core.Impl.Binary */ private static object ReadEnumArray(BinaryReader ctx, Type type) { - return BinaryUtils.ReadTypedArray(ctx, true, type.GetElementType()); + var elemType = type.GetElementType() ?? typeof(object); + + return BinaryUtils.ReadTypedArray(ctx, true, elemType); } /** @@ -622,7 +624,7 @@ namespace Apache.Ignite.Core.Impl.Binary */ private static object ReadArray(BinaryReader ctx, Type type) { - var elemType = type.IsArray ? type.GetElementType() : typeof(object); + var elemType = type.GetElementType() ?? typeof(object); return BinaryUtils.ReadTypedArray(ctx, true, elemType); } http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 77a22dd..47b0663 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs @@ -1195,9 +1195,10 @@ namespace Apache.Ignite.Core.Impl.Binary { // Write object fields. desc.Serializer.WriteBinary(obj, this); + var dataEnd = _stream.Position; // Write schema - var schemaOffset = _stream.Position - pos; + var schemaOffset = dataEnd - pos; int schemaId; @@ -1230,8 +1231,12 @@ namespace Apache.Ignite.Core.Impl.Binary var len = _stream.Position - pos; - var header = new BinaryObjectHeader(desc.TypeId, obj.GetHashCode(), len, - schemaId, schemaOffset, flags); + var hashCode = desc.EqualityComparer != null + ? desc.EqualityComparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size, + dataEnd - pos - BinaryObjectHeader.Size, _schema, schemaIdx, _marsh, desc) + : obj.GetHashCode(); + + var header = new BinaryObjectHeader(desc.TypeId, hashCode, len, schemaId, schemaOffset, flags); BinaryObjectHeader.Write(header, _stream, pos); http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 index b80348e..6adb847 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs @@ -24,7 +24,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// /// Wraps DateTime item in a binarizable. /// - internal class DateTimeHolder : IBinaryWriteAware + internal struct DateTimeHolder : IBinaryWriteAware { /** */ private readonly DateTime _item; @@ -64,5 +64,18 @@ namespace Apache.Ignite.Core.Impl.Binary writer.GetRawWriter().WriteLong(_item.ToBinary()); } + + /** */ + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is DateTimeHolder && _item.Equals(((DateTimeHolder) obj)._item); + } + + /** */ + public override int GetHashCode() + { + return _item.GetHashCode(); + } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryEqualityComparer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryEqualityComparer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryEqualityComparer.cs new file mode 100644 index 0000000..9628688 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryEqualityComparer.cs @@ -0,0 +1,53 @@ +/* + * 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 Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Impl.Binary.IO; + + /// + /// Internal comparer interface for implementations, + /// provides more efficient API. + /// + internal interface IBinaryEqualityComparer + { + /// + /// Returns a hash code for the binary object in specified stream at specified position. + /// + /// Stream. + /// Data start position (right after the header). + /// Data length (without header and schema). + /// Schema holder. + /// Schema identifier. + /// Marshaller. + /// Type descriptor. + /// + /// A hash code for the object in the stream. + /// + int GetHashCode(IBinaryStream stream, int startPos, int length, BinaryObjectSchemaHolder schema, int schemaId, + Marshaller marshaller, IBinaryTypeDescriptor desc); + + /// + /// Returns a value indicating that two binary object are equal. + /// + /// First object. + /// Second object. + /// True when objects are equal; otherwise false. + bool Equals(IBinaryObject x, IBinaryObject y); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/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 e25d720..6c7e360 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs @@ -78,6 +78,11 @@ namespace Apache.Ignite.Core.Impl.Binary bool IsEnum { get; } /// + /// Gets the equality comparer. + /// + IBinaryEqualityComparer EqualityComparer { get; } + + /// /// Write type structure. /// BinaryStructure WriterTypeStructure { get; } http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryHeapStream.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryHeapStream.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryHeapStream.cs index 2ce2138..ad35ff9 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryHeapStream.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryHeapStream.cs @@ -420,6 +420,15 @@ namespace Apache.Ignite.Core.Impl.Binary.IO } /** */ + public override T Apply(IBinaryStreamProcessor proc, TArg arg) + { + fixed (byte* data0 = _data) + { + return proc.Invoke(data0, arg); + } + } + + /** */ protected override void Dispose(bool disposing) { // No-op. http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamBase.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamBase.cs index 184209f..0b855f8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamBase.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamBase.cs @@ -1119,6 +1119,19 @@ namespace Apache.Ignite.Core.Impl.Binary.IO return Pos; } + /// + /// Returns a hash code for the specified byte range. + /// + public abstract T Apply(IBinaryStreamProcessor proc, TArg arg); + + /// + /// Flushes the data to underlying storage. + /// + public void Flush() + { + // No-op. + } + /** */ public void Dispose() { http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/IBinaryStream.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/IBinaryStream.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/IBinaryStream.cs index cd509c6..3a46515 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/IBinaryStream.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/IBinaryStream.cs @@ -318,5 +318,30 @@ namespace Apache.Ignite.Core.Impl.Binary.IO /// Seek origin. /// Position. int Seek(int offset, SeekOrigin origin); + + /// + /// Applies specified processor to the raw stream data. + /// + T Apply(IBinaryStreamProcessor proc, TArg arg); + + /// + /// Flushes the data to underlying storage. + /// + void Flush(); + } + + /// + /// Binary stream processor. + /// + [CLSCompliant(false)] + public unsafe interface IBinaryStreamProcessor + { + /// + /// Invokes the processor. + /// + /// Data. + /// Argument. + /// Result. + T Invoke(byte* data, TArg arg); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs index 475762a..6dee998 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs @@ -408,7 +408,7 @@ namespace Apache.Ignite.Core.Impl.Binary if (meta != BinaryType.Empty) { desc = new BinaryFullTypeDescriptor(null, meta.TypeId, meta.TypeName, true, null, null, null, false, - meta.AffinityKeyFieldName, meta.IsEnum); + meta.AffinityKeyFieldName, meta.IsEnum, null); _idToDesc.GetOrAdd(typeKey, _ => desc); @@ -419,6 +419,14 @@ namespace Apache.Ignite.Core.Impl.Binary } /// + /// Gets the user type descriptors. + /// + public ICollection GetUserTypeDescriptors() + { + return _typeNameToDesc.Values; + } + + /// /// Add user type. /// /// Configuration. @@ -453,7 +461,7 @@ namespace Apache.Ignite.Core.Impl.Binary var serializer = GetSerializer(cfg, typeCfg, type, typeId, nameMapper, idMapper); AddType(type, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, serializer, - affKeyFld, type.IsEnum); + affKeyFld, type.IsEnum, typeCfg.EqualityComparer); } else { @@ -463,7 +471,7 @@ namespace Apache.Ignite.Core.Impl.Binary int typeId = BinaryUtils.TypeId(typeName, nameMapper, idMapper); AddType(null, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, null, - typeCfg.AffinityKeyFieldName, typeCfg.IsEnum); + typeCfg.AffinityKeyFieldName, typeCfg.IsEnum, typeCfg.EqualityComparer); } } @@ -521,9 +529,11 @@ namespace Apache.Ignite.Core.Impl.Binary /// Serializer. /// Affinity key field name. /// Enum flag. + /// Comparer. private void AddType(Type type, int typeId, string typeName, bool userType, bool keepDeserialized, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper, - IBinarySerializerInternal serializer, string affKeyFieldName, bool isEnum) + IBinarySerializerInternal serializer, string affKeyFieldName, bool isEnum, + IEqualityComparer comparer) { long typeKey = BinaryUtils.TypeKey(userType, typeId); @@ -545,7 +555,7 @@ namespace Apache.Ignite.Core.Impl.Binary throw new BinaryObjectException("Conflicting type name: " + typeName); var descriptor = new BinaryFullTypeDescriptor(type, typeId, typeName, userType, nameMapper, idMapper, - serializer, keepDeserialized, affKeyFieldName, isEnum); + serializer, keepDeserialized, affKeyFieldName, isEnum, comparer); if (type != null) _typeToDesc[type] = descriptor; @@ -571,7 +581,7 @@ namespace Apache.Ignite.Core.Impl.Binary typeId = BinaryUtils.TypeId(type.Name, null, null); AddType(type, typeId, BinaryUtils.GetTypeName(type), false, false, null, null, serializer, affKeyFldName, - false); + false, null); } /// http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs index 99c8f49..26b1d5f 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs @@ -76,5 +76,21 @@ namespace Apache.Ignite.Core.Impl.Binary _item = new BinaryFormatter().Deserialize(streamAdapter, null); } } + + /** */ + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + + return Equals(_item, ((SerializableObjectHolder) obj)._item); + } + + /** */ + public override int GetHashCode() + { + return _item != null ? _item.GetHashCode() : 0; + } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs index e1df50b..bb9cbfc 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs @@ -142,7 +142,7 @@ namespace Apache.Ignite.Core.Impl.Common /// private static void WriteComplexProperty(object obj, XmlWriter writer, Type valueType) { - var props = GetNonDefaultProperties(obj).ToList(); + var props = GetNonDefaultProperties(obj).OrderBy(x => x.Name).ToList(); // Specify type for interfaces and abstract classes if (valueType.IsAbstract) @@ -353,7 +353,8 @@ namespace Apache.Ignite.Core.Impl.Common /// private static List GetConcreteDerivedTypes(Type type) { - return type.Assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && type.IsAssignableFrom(t)).ToList(); + return typeof(IIgnite).Assembly.GetTypes() + .Where(t => t.IsClass && !t.IsAbstract && type.IsAssignableFrom(t)).ToList(); } /// http://git-wip-us.apache.org/repos/asf/ignite/blob/b7908d7a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Memory/PlatformMemoryStream.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Memory/PlatformMemoryStream.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Memory/PlatformMemoryStream.cs index c758d28..3719846 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Memory/PlatformMemoryStream.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Memory/PlatformMemoryStream.cs @@ -732,6 +732,22 @@ namespace Apache.Ignite.Core.Impl.Memory } /// + /// Returns a hash code for the specified byte range. + /// + public T Apply(IBinaryStreamProcessor proc, TArg arg) + { + return proc.Invoke(_data, arg); + } + + /// + /// Flushes the data to underlying storage. + /// + public void Flush() + { + SynchronizeOutput(); + } + + /// /// Ensure capacity for write and shift position. /// /// Bytes count.