http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/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 new file mode 100644 index 0000000..58973f7 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs @@ -0,0 +1,1417 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Impl.Binary +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.IO; + using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Impl.Binary.IO; + using Apache.Ignite.Core.Impl.Binary.Metadata; + using Apache.Ignite.Core.Impl.Binary.Structure; + + /// <summary> + /// Binary writer implementation. + /// </summary> + internal class BinaryWriter : IBinaryWriter, IBinaryRawWriter + { + /** Marshaller. */ + private readonly Marshaller _marsh; + + /** Stream. */ + private readonly IBinaryStream _stream; + + /** Builder (used only during build). */ + private BinaryObjectBuilder _builder; + + /** Handles. */ + private BinaryHandleDictionary<object, long> _hnds; + + /** Metadatas collected during this write session. */ + private IDictionary<int, IBinaryType> _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; + + /** 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; + + /// <summary> + /// Gets the marshaller. + /// </summary> + internal Marshaller Marshaller + { + get { return _marsh; } + } + + /// <summary> + /// Write named boolean value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Boolean value.</param> + public void WriteBoolean(string fieldName, bool val) + { + WriteFieldId(fieldName, BinaryUtils.TypeBool); + + _stream.WriteByte(BinaryUtils.TypeBool); + _stream.WriteBool(val); + } + + /// <summary> + /// Write boolean value. + /// </summary> + /// <param name="val">Boolean value.</param> + public void WriteBoolean(bool val) + { + _stream.WriteBool(val); + } + + /// <summary> + /// Write named boolean array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Boolean array.</param> + public void WriteBooleanArray(string fieldName, bool[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayBool); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayBool); + BinaryUtils.WriteBooleanArray(val, _stream); + } + } + + /// <summary> + /// Write boolean array. + /// </summary> + /// <param name="val">Boolean array.</param> + public void WriteBooleanArray(bool[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayBool); + BinaryUtils.WriteBooleanArray(val, _stream); + } + } + + /// <summary> + /// Write named byte value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Byte value.</param> + public void WriteByte(string fieldName, byte val) + { + WriteFieldId(fieldName, BinaryUtils.TypeBool); + + _stream.WriteByte(BinaryUtils.TypeByte); + _stream.WriteByte(val); + } + + /// <summary> + /// Write byte value. + /// </summary> + /// <param name="val">Byte value.</param> + public void WriteByte(byte val) + { + _stream.WriteByte(val); + } + + /// <summary> + /// Write named byte array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Byte array.</param> + public void WriteByteArray(string fieldName, byte[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayByte); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayByte); + BinaryUtils.WriteByteArray(val, _stream); + } + } + + /// <summary> + /// Write byte array. + /// </summary> + /// <param name="val">Byte array.</param> + public void WriteByteArray(byte[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayByte); + BinaryUtils.WriteByteArray(val, _stream); + } + } + + /// <summary> + /// Write named short value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Short value.</param> + public void WriteShort(string fieldName, short val) + { + WriteFieldId(fieldName, BinaryUtils.TypeShort); + + _stream.WriteByte(BinaryUtils.TypeShort); + _stream.WriteShort(val); + } + + /// <summary> + /// Write short value. + /// </summary> + /// <param name="val">Short value.</param> + public void WriteShort(short val) + { + _stream.WriteShort(val); + } + + /// <summary> + /// Write named short array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Short array.</param> + public void WriteShortArray(string fieldName, short[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayShort); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayShort); + BinaryUtils.WriteShortArray(val, _stream); + } + } + + /// <summary> + /// Write short array. + /// </summary> + /// <param name="val">Short array.</param> + public void WriteShortArray(short[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayShort); + BinaryUtils.WriteShortArray(val, _stream); + } + } + + /// <summary> + /// Write named char value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Char value.</param> + public void WriteChar(string fieldName, char val) + { + WriteFieldId(fieldName, BinaryUtils.TypeChar); + + _stream.WriteByte(BinaryUtils.TypeChar); + _stream.WriteChar(val); + } + + /// <summary> + /// Write char value. + /// </summary> + /// <param name="val">Char value.</param> + public void WriteChar(char val) + { + _stream.WriteChar(val); + } + + /// <summary> + /// Write named char array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Char array.</param> + public void WriteCharArray(string fieldName, char[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayChar); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayChar); + BinaryUtils.WriteCharArray(val, _stream); + } + } + + /// <summary> + /// Write char array. + /// </summary> + /// <param name="val">Char array.</param> + public void WriteCharArray(char[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayChar); + BinaryUtils.WriteCharArray(val, _stream); + } + } + + /// <summary> + /// Write named int value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Int value.</param> + public void WriteInt(string fieldName, int val) + { + WriteFieldId(fieldName, BinaryUtils.TypeInt); + + _stream.WriteByte(BinaryUtils.TypeInt); + _stream.WriteInt(val); + } + + /// <summary> + /// Write int value. + /// </summary> + /// <param name="val">Int value.</param> + public void WriteInt(int val) + { + _stream.WriteInt(val); + } + + /// <summary> + /// Write named int array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Int array.</param> + public void WriteIntArray(string fieldName, int[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayInt); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayInt); + BinaryUtils.WriteIntArray(val, _stream); + } + } + + /// <summary> + /// Write int array. + /// </summary> + /// <param name="val">Int array.</param> + public void WriteIntArray(int[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayInt); + BinaryUtils.WriteIntArray(val, _stream); + } + } + + /// <summary> + /// Write named long value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Long value.</param> + public void WriteLong(string fieldName, long val) + { + WriteFieldId(fieldName, BinaryUtils.TypeLong); + + _stream.WriteByte(BinaryUtils.TypeLong); + _stream.WriteLong(val); + } + + /// <summary> + /// Write long value. + /// </summary> + /// <param name="val">Long value.</param> + public void WriteLong(long val) + { + _stream.WriteLong(val); + } + + /// <summary> + /// Write named long array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Long array.</param> + public void WriteLongArray(string fieldName, long[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayLong); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayLong); + BinaryUtils.WriteLongArray(val, _stream); + } + } + + /// <summary> + /// Write long array. + /// </summary> + /// <param name="val">Long array.</param> + public void WriteLongArray(long[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayLong); + BinaryUtils.WriteLongArray(val, _stream); + } + } + + /// <summary> + /// Write named float value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Float value.</param> + public void WriteFloat(string fieldName, float val) + { + WriteFieldId(fieldName, BinaryUtils.TypeFloat); + + _stream.WriteByte(BinaryUtils.TypeFloat); + _stream.WriteFloat(val); + } + + /// <summary> + /// Write float value. + /// </summary> + /// <param name="val">Float value.</param> + public void WriteFloat(float val) + { + _stream.WriteFloat(val); + } + + /// <summary> + /// Write named float array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Float array.</param> + public void WriteFloatArray(string fieldName, float[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayFloat); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayFloat); + BinaryUtils.WriteFloatArray(val, _stream); + } + } + + /// <summary> + /// Write float array. + /// </summary> + /// <param name="val">Float array.</param> + public void WriteFloatArray(float[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayFloat); + BinaryUtils.WriteFloatArray(val, _stream); + } + } + + /// <summary> + /// Write named double value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Double value.</param> + public void WriteDouble(string fieldName, double val) + { + WriteFieldId(fieldName, BinaryUtils.TypeDouble); + + _stream.WriteByte(BinaryUtils.TypeDouble); + _stream.WriteDouble(val); + } + + /// <summary> + /// Write double value. + /// </summary> + /// <param name="val">Double value.</param> + public void WriteDouble(double val) + { + _stream.WriteDouble(val); + } + + /// <summary> + /// Write named double array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Double array.</param> + public void WriteDoubleArray(string fieldName, double[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayDouble); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayDouble); + BinaryUtils.WriteDoubleArray(val, _stream); + } + } + + /// <summary> + /// Write double array. + /// </summary> + /// <param name="val">Double array.</param> + public void WriteDoubleArray(double[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayDouble); + BinaryUtils.WriteDoubleArray(val, _stream); + } + } + + /// <summary> + /// Write named decimal value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Decimal value.</param> + public void WriteDecimal(string fieldName, decimal? val) + { + WriteFieldId(fieldName, BinaryUtils.TypeDecimal); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeDecimal); + BinaryUtils.WriteDecimal(val.Value, _stream); + } + } + + /// <summary> + /// Write decimal value. + /// </summary> + /// <param name="val">Decimal value.</param> + public void WriteDecimal(decimal? val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeDecimal); + BinaryUtils.WriteDecimal(val.Value, _stream); + } + } + + /// <summary> + /// Write named decimal array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Decimal array.</param> + public void WriteDecimalArray(string fieldName, decimal?[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayDecimal); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayDecimal); + BinaryUtils.WriteDecimalArray(val, _stream); + } + } + + /// <summary> + /// Write decimal array. + /// </summary> + /// <param name="val">Decimal array.</param> + public void WriteDecimalArray(decimal?[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayDecimal); + BinaryUtils.WriteDecimalArray(val, _stream); + } + } + + /// <summary> + /// Write named date value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Date value.</param> + public void WriteTimestamp(string fieldName, DateTime? val) + { + WriteFieldId(fieldName, BinaryUtils.TypeTimestamp); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeTimestamp); + BinaryUtils.WriteTimestamp(val.Value, _stream); + } + } + + /// <summary> + /// Write date value. + /// </summary> + /// <param name="val">Date value.</param> + public void WriteTimestamp(DateTime? val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeTimestamp); + BinaryUtils.WriteTimestamp(val.Value, _stream); + } + } + + /// <summary> + /// Write named date array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Date array.</param> + public void WriteTimestampArray(string fieldName, DateTime?[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeTimestamp); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayTimestamp); + BinaryUtils.WriteTimestampArray(val, _stream); + } + } + + /// <summary> + /// Write date array. + /// </summary> + /// <param name="val">Date array.</param> + public void WriteTimestampArray(DateTime?[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayTimestamp); + BinaryUtils.WriteTimestampArray(val, _stream); + } + } + + /// <summary> + /// Write named string value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">String value.</param> + public void WriteString(string fieldName, string val) + { + WriteFieldId(fieldName, BinaryUtils.TypeString); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeString); + BinaryUtils.WriteString(val, _stream); + } + } + + /// <summary> + /// Write string value. + /// </summary> + /// <param name="val">String value.</param> + public void WriteString(string val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeString); + BinaryUtils.WriteString(val, _stream); + } + } + + /// <summary> + /// Write named string array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">String array.</param> + public void WriteStringArray(string fieldName, string[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayString); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayString); + BinaryUtils.WriteStringArray(val, _stream); + } + } + + /// <summary> + /// Write string array. + /// </summary> + /// <param name="val">String array.</param> + public void WriteStringArray(string[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayString); + BinaryUtils.WriteStringArray(val, _stream); + } + } + + /// <summary> + /// Write named GUID value. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">GUID value.</param> + public void WriteGuid(string fieldName, Guid? val) + { + WriteFieldId(fieldName, BinaryUtils.TypeGuid); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeGuid); + BinaryUtils.WriteGuid(val.Value, _stream); + } + } + + /// <summary> + /// Write GUID value. + /// </summary> + /// <param name="val">GUID value.</param> + public void WriteGuid(Guid? val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeGuid); + BinaryUtils.WriteGuid(val.Value, _stream); + } + } + + /// <summary> + /// Write named GUID array. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">GUID array.</param> + public void WriteGuidArray(string fieldName, Guid?[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayGuid); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayGuid); + BinaryUtils.WriteGuidArray(val, _stream); + } + } + + /// <summary> + /// Write GUID array. + /// </summary> + /// <param name="val">GUID array.</param> + public void WriteGuidArray(Guid?[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayGuid); + BinaryUtils.WriteGuidArray(val, _stream); + } + } + + /// <summary> + /// Write named enum value. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Enum value.</param> + public void WriteEnum<T>(string fieldName, T val) + { + WriteFieldId(fieldName, BinaryUtils.TypeEnum); + + _stream.WriteByte(BinaryUtils.TypeEnum); + BinaryUtils.WriteEnum(_stream, (Enum)(object)val); + } + + /// <summary> + /// Write enum value. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="val">Enum value.</param> + public void WriteEnum<T>(T val) + { + _stream.WriteByte(BinaryUtils.TypeEnum); + BinaryUtils.WriteEnum(_stream, (Enum)(object)val); + } + + /// <summary> + /// Write named enum array. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Enum array.</param> + public void WriteEnumArray<T>(string fieldName, T[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArrayEnum); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayEnum); + BinaryUtils.WriteArray(val, this); + } + } + + /// <summary> + /// Write enum array. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="val">Enum array.</param> + public void WriteEnumArray<T>(T[] val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArrayEnum); + BinaryUtils.WriteArray(val, this); + } + } + + /// <summary> + /// Write named object value. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Object value.</param> + public void WriteObject<T>(string fieldName, T val) + { + WriteFieldId(fieldName, BinaryUtils.TypeObject); + + if (val == null) + WriteNullField(); + else + Write(val); + } + + /// <summary> + /// Write object value. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="val">Object value.</param> + public void WriteObject<T>(T val) + { + Write(val); + } + + /// <summary> + /// Write named object array. + /// </summary> + /// <typeparam name="T">Element type.</typeparam> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Object array.</param> + public void WriteArray<T>(string fieldName, T[] val) + { + WriteFieldId(fieldName, BinaryUtils.TypeArray); + + if (val == null) + WriteNullField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArray); + BinaryUtils.WriteArray(val, this); + } + } + + /// <summary> + /// Write object array. + /// </summary> + /// <typeparam name="T">Element type.</typeparam> + /// <param name="val">Object array.</param> + public void WriteArray<T>(T[] val) + { + WriteArrayInternal(val); + } + + /// <summary> + /// Write object array. + /// </summary> + /// <param name="val">Object array.</param> + public void WriteArrayInternal(Array val) + { + if (val == null) + WriteNullRawField(); + else + { + _stream.WriteByte(BinaryUtils.TypeArray); + BinaryUtils.WriteArray(val, this); + } + } + + /// <summary> + /// Write named collection. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Collection.</param> + public void WriteCollection(string fieldName, ICollection val) + { + WriteFieldId(fieldName, BinaryUtils.TypeCollection); + + if (val == null) + WriteNullField(); + else + WriteCollection(val); + } + + /// <summary> + /// Write collection. + /// </summary> + /// <param name="val">Collection.</param> + public void WriteCollection(ICollection val) + { + WriteByte(BinaryUtils.TypeCollection); + BinaryUtils.WriteCollection(val, this); + } + + /// <summary> + /// Write named dictionary. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="val">Dictionary.</param> + public void WriteDictionary(string fieldName, IDictionary val) + { + WriteFieldId(fieldName, BinaryUtils.TypeDictionary); + + if (val == null) + WriteNullField(); + else + WriteDictionary(val); + } + + /// <summary> + /// Write dictionary. + /// </summary> + /// <param name="val">Dictionary.</param> + public void WriteDictionary(IDictionary val) + { + WriteByte(BinaryUtils.TypeDictionary); + BinaryUtils.WriteDictionary(val, this); + } + + /// <summary> + /// Write NULL field. + /// </summary> + private void WriteNullField() + { + _stream.WriteByte(BinaryUtils.HdrNull); + } + + /// <summary> + /// Write NULL raw field. + /// </summary> + private void WriteNullRawField() + { + _stream.WriteByte(BinaryUtils.HdrNull); + } + + /// <summary> + /// Get raw writer. + /// </summary> + /// <returns> + /// Raw writer. + /// </returns> + public IBinaryRawWriter GetRawWriter() + { + if (_curRawPos == 0) + _curRawPos = _stream.Position; + + return this; + } + + /// <summary> + /// Set new builder. + /// </summary> + /// <param name="builder">Builder.</param> + /// <returns>Previous builder.</returns> + internal BinaryObjectBuilder SetBuilder(BinaryObjectBuilder builder) + { + BinaryObjectBuilder ret = _builder; + + _builder = builder; + + return ret; + } + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="marsh">Marshaller.</param> + /// <param name="stream">Stream.</param> + internal BinaryWriter(Marshaller marsh, IBinaryStream stream) + { + _marsh = marsh; + _stream = stream; + } + + /// <summary> + /// Write object. + /// </summary> + /// <param name="obj">Object.</param> + public void Write<T>(T obj) + { + // Handle special case for null. + if (obj == null) + { + _stream.WriteByte(BinaryUtils.HdrNull); + + return; + } + + // We use GetType() of a real object instead of typeof(T) to take advantage of + // automatic Nullable'1 unwrapping. + Type type = obj.GetType(); + + // Handle common case when primitive is written. + if (type.IsPrimitive) + { + WritePrimitive(obj, type); + + return; + } + + // Handle special case for builder. + if (WriteBuilderSpecials(obj)) + return; + + // Suppose that we faced normal object and perform descriptor lookup. + IBinaryTypeDescriptor desc = _marsh.GetDescriptor(type); + + if (desc != null) + { + // Writing normal object. + var pos = _stream.Position; + + // Dealing with handles. + if (!(desc.Serializer is IBinarySystemTypeSerializer) && WriteHandle(pos, 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; + + // Push new frame. + _curTypeId = desc.TypeId; + _curConverter = desc.NameMapper; + _curMapper = desc.IdMapper; + _curRawPos = 0; + _curPos = pos; + + _curStruct = new BinaryStructureTracker(desc, desc.WriterTypeStructure); + var schemaIdx = _schema.PushSchema(); + + try + { + // Write object fields. + desc.Serializer.WriteBinary(obj, this); + + // Write schema + var schemaOffset = _stream.Position - pos; + + int schemaId; + short flags; + var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, out flags); + + if (!hasSchema) + schemaOffset = BinaryObjectHeader.Size; + + // Calculate and write header. + if (hasSchema && _curRawPos > 0) + _stream.WriteInt(_curRawPos - pos); // raw offset is in the last 4 bytes + + var len = _stream.Position - pos; + + var header = new BinaryObjectHeader(desc.UserType, desc.TypeId, obj.GetHashCode(), len, + schemaId, schemaOffset, !hasSchema, flags); + + BinaryObjectHeader.Write(header, _stream, pos); + + Stream.Seek(pos + len, SeekOrigin.Begin); // Seek to the end + } + finally + { + _schema.PopSchema(schemaIdx); + } + + // Apply structure updates if any. + _curStruct.UpdateWriterStructure(this); + + // Restore old frame. + _curTypeId = oldTypeId; + _curConverter = oldConverter; + _curMapper = oldMapper; + _curRawPos = oldRawPos; + _curPos = oldPos; + + _curStruct = oldStruct; + } + else + { + // Are we dealing with a well-known type? + var handler = BinarySystemHandlers.GetWriteHandler(type); + + if (handler == null) // We did our best, object cannot be marshalled. + throw new BinaryObjectException("Unsupported object type [type=" + type + ", object=" + obj + ']'); + + handler(this, obj); + } + } + + /// <summary> + /// Write primitive type. + /// </summary> + /// <param name="val">Object.</param> + /// <param name="type">Type.</param> + private unsafe void WritePrimitive<T>(T val, Type type) + { + // .Net defines 14 primitive types. We support 12 - excluding IntPtr and UIntPtr. + // Types check sequence is designed to minimize comparisons for the most frequent types. + + if (type == typeof(int)) + { + _stream.WriteByte(BinaryUtils.TypeInt); + _stream.WriteInt((int)(object)val); + } + else if (type == typeof(long)) + { + _stream.WriteByte(BinaryUtils.TypeLong); + _stream.WriteLong((long)(object)val); + } + else if (type == typeof(bool)) + { + _stream.WriteByte(BinaryUtils.TypeBool); + _stream.WriteBool((bool)(object)val); + } + else if (type == typeof(byte)) + { + _stream.WriteByte(BinaryUtils.TypeByte); + _stream.WriteByte((byte)(object)val); + } + else if (type == typeof(short)) + { + _stream.WriteByte(BinaryUtils.TypeShort); + _stream.WriteShort((short)(object)val); + } + else if (type == typeof (char)) + { + _stream.WriteByte(BinaryUtils.TypeChar); + _stream.WriteChar((char)(object)val); + } + else if (type == typeof(float)) + { + _stream.WriteByte(BinaryUtils.TypeFloat); + _stream.WriteFloat((float)(object)val); + } + else if (type == typeof(double)) + { + _stream.WriteByte(BinaryUtils.TypeDouble); + _stream.WriteDouble((double)(object)val); + } + else if (type == typeof(sbyte)) + { + sbyte val0 = (sbyte)(object)val; + + _stream.WriteByte(BinaryUtils.TypeByte); + _stream.WriteByte(*(byte*)&val0); + } + else if (type == typeof(ushort)) + { + ushort val0 = (ushort)(object)val; + + _stream.WriteByte(BinaryUtils.TypeShort); + _stream.WriteShort(*(short*)&val0); + } + else if (type == typeof(uint)) + { + uint val0 = (uint)(object)val; + + _stream.WriteByte(BinaryUtils.TypeInt); + _stream.WriteInt(*(int*)&val0); + } + else if (type == typeof(ulong)) + { + ulong val0 = (ulong)(object)val; + + _stream.WriteByte(BinaryUtils.TypeLong); + _stream.WriteLong(*(long*)&val0); + } + else + throw new BinaryObjectException("Unsupported object type [type=" + type.FullName + ", object=" + val + ']'); + } + + /// <summary> + /// Try writing object as special builder type. + /// </summary> + /// <param name="obj">Object.</param> + /// <returns>True if object was written, false otherwise.</returns> + private bool WriteBuilderSpecials<T>(T obj) + { + if (_builder != null) + { + // Special case for binary object during build. + BinaryObject portObj = obj as BinaryObject; + + if (portObj != null) + { + if (!WriteHandle(_stream.Position, portObj)) + _builder.ProcessBinary(_stream, portObj); + + return true; + } + + // Special case for builder during build. + BinaryObjectBuilder portBuilder = obj as BinaryObjectBuilder; + + if (portBuilder != null) + { + if (!WriteHandle(_stream.Position, portBuilder)) + _builder.ProcessBuilder(_stream, portBuilder); + + return true; + } + } + + return false; + } + + /// <summary> + /// Add handle to handles map. + /// </summary> + /// <param name="pos">Position in stream.</param> + /// <param name="obj">Object.</param> + /// <returns><c>true</c> if object was written as handle.</returns> + private bool WriteHandle(long pos, object obj) + { + if (_hnds == null) + { + // Cache absolute handle position. + _hnds = new BinaryHandleDictionary<object, long>(obj, pos); + + return false; + } + + long hndPos; + + if (!_hnds.TryGetValue(obj, out hndPos)) + { + // Cache absolute handle position. + _hnds.Add(obj, pos); + + return false; + } + + _stream.WriteByte(BinaryUtils.HdrHnd); + + // Handle is written as difference between position before header and handle position. + _stream.WriteInt((int)(pos - hndPos)); + + return true; + } + + /// <summary> + /// Perform action with detached semantics. + /// </summary> + /// <param name="a"></param> + internal void WithDetach(Action<BinaryWriter> a) + { + if (_detaching) + a(this); + else + { + _detaching = true; + + BinaryHandleDictionary<object, long> oldHnds = _hnds; + _hnds = null; + + try + { + a(this); + } + finally + { + _detaching = false; + + if (oldHnds != null) + { + // Merge newly recorded handles with old ones and restore old on the stack. + // Otherwise we can use current handles right away. + if (_hnds != null) + oldHnds.Merge(_hnds); + + _hnds = oldHnds; + } + } + } + } + + /// <summary> + /// Stream. + /// </summary> + internal IBinaryStream Stream + { + get { return _stream; } + } + + /// <summary> + /// Gets collected metadatas. + /// </summary> + /// <returns>Collected metadatas (if any).</returns> + internal IDictionary<int, IBinaryType> GetBinaryTypes() + { + return _metas; + } + + /// <summary> + /// Check whether the given object is binarizeble, i.e. it can be serialized with binary marshaller. + /// </summary> + /// <param name="obj">Object.</param> + /// <returns>True if binarizable.</returns> + internal bool IsBinarizable(object obj) + { + if (obj != null) + { + Type type = obj.GetType(); + + // We assume object as binarizable only in case it has descriptor. + // Collections, Enums and non-primitive arrays do not have descriptors + // and this is fine here because we cannot know whether their members are binarizable. + return _marsh.GetDescriptor(type) != null || BinarySystemHandlers.GetWriteHandler(type) != null; + } + + return true; + } + + /// <summary> + /// Write field ID. + /// </summary> + /// <param name="fieldName">Field name.</param> + /// <param name="fieldTypeId">Field type ID.</param> + private void WriteFieldId(string fieldName, byte fieldTypeId) + { + if (_curRawPos != 0) + throw new BinaryObjectException("Cannot write named fields after raw data is written."); + + var fieldId = _curStruct.GetFieldId(fieldName, fieldTypeId); + + _schema.PushField(fieldId, _stream.Position - _curPos); + } + + /// <summary> + /// Saves metadata for this session. + /// </summary> + /// <param name="typeId">Type ID.</param> + /// <param name="typeName">Type name.</param> + /// <param name="affKeyFieldName">Affinity key field name.</param> + /// <param name="fields">Fields metadata.</param> + internal void SaveMetadata(int typeId, string typeName, string affKeyFieldName, IDictionary<string, int> fields) + { + if (_metas == null) + { + BinaryType meta = + new BinaryType(typeId, typeName, fields, affKeyFieldName); + + _metas = new Dictionary<int, IBinaryType>(1); + + _metas[typeId] = meta; + } + else + { + IBinaryType meta; + + if (_metas.TryGetValue(typeId, out meta)) + { + IDictionary<string, int> existingFields = ((BinaryType)meta).FieldsMap(); + + foreach (KeyValuePair<string, int> field in fields) + { + if (!existingFields.ContainsKey(field.Key)) + existingFields[field.Key] = field.Value; + } + } + else + _metas[typeId] = new BinaryType(typeId, typeName, fields, affKeyFieldName); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/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 new file mode 100644 index 0000000..473f6c4 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs @@ -0,0 +1,68 @@ +/* + * 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 class 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(IBinaryReader reader) + { + Debug.Assert(reader != null); + + _item = DateTime.FromBinary(reader.GetRawReader().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()); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySystemTypeSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySystemTypeSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySystemTypeSerializer.cs new file mode 100644 index 0000000..3571ffb --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySystemTypeSerializer.cs @@ -0,0 +1,34 @@ +/* + * 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; + + /// <summary> + /// Serializer for system types that can create instances directly from a stream and does not support handles. + /// </summary> + internal interface IBinarySystemTypeSerializer : IBinarySerializer + { + /// <summary> + /// Reads the instance from a reader. + /// </summary> + /// <param name="reader">The reader.</param> + /// <returns>Deserialized instance.</returns> + object ReadInstance(BinaryReader reader); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/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 new file mode 100644 index 0000000..99af56d --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs @@ -0,0 +1,133 @@ +/* + * 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 Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Impl.Binary.Structure; + + /// <summary> + /// Type descriptor. + /// </summary> + internal interface IBinaryTypeDescriptor + { + /// <summary> + /// Type. + /// </summary> + Type Type + { + get; + } + + /// <summary> + /// Type ID. + /// </summary> + int TypeId + { + get; + } + + /// <summary> + /// Type name. + /// </summary> + string TypeName + { + get; + } + + /// <summary> + /// User type flag. + /// </summary> + bool UserType + { + get; + } + + /// <summary> + /// Whether to cache deserialized value in IBinaryObject + /// </summary> + bool KeepDeserialized + { + get; + } + + /// <summary> + /// Name converter. + /// </summary> + IBinaryNameMapper NameMapper + { + get; + } + + /// <summary> + /// Mapper. + /// </summary> + IBinaryIdMapper IdMapper + { + get; + } + + /// <summary> + /// Serializer. + /// </summary> + IBinarySerializer Serializer + { + get; + } + + /// <summary> + /// Affinity key field name. + /// </summary> + string AffinityKeyFieldName + { + get; + } + + /// <summary> + /// Write type structure. + /// </summary> + BinaryStructure WriterTypeStructure { get; } + + /// <summary> + /// Read type structure. + /// </summary> + BinaryStructure 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(BinaryStructure exp, 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); + + /// <summary> + /// Gets the schema. + /// </summary> + BinaryObjectSchema Schema { get; } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryWriteAware.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryWriteAware.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryWriteAware.cs new file mode 100644 index 0000000..151338b --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryWriteAware.cs @@ -0,0 +1,34 @@ +/* + * 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; + + /// <summary> + /// Represents an object that can write itself to a binary writer. + /// </summary> + internal interface IBinaryWriteAware + { + /// <summary> + /// Writes this object to the given writer. + /// </summary> + /// <param name="writer">Writer.</param> + /// <exception cref="System.IO.IOException">If write failed.</exception> + void WriteBinary(IBinaryWriter writer); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IgniteBinary.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IgniteBinary.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IgniteBinary.cs new file mode 100644 index 0000000..927ebaf --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IgniteBinary.cs @@ -0,0 +1,191 @@ +/* + * 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.IO; + using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Common; + using Apache.Ignite.Core.Impl.Binary.IO; + using Apache.Ignite.Core.Impl.Common; + + /// <summary> + /// Binary implementation. + /// </summary> + internal class IgniteBinary : IIgniteBinary + { + /** Owning grid. */ + private readonly Marshaller _marsh; + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="marsh">Marshaller.</param> + internal IgniteBinary(Marshaller marsh) + { + _marsh = marsh; + } + + /** <inheritDoc /> */ + public T ToBinary<T>(object obj) + { + if (obj is IBinaryObject) + return (T)obj; + + IBinaryStream stream = new BinaryHeapStream(1024); + + // Serialize. + BinaryWriter writer = _marsh.StartMarshal(stream); + + try + { + writer.Write(obj); + } + finally + { + // Save metadata. + _marsh.FinishMarshal(writer); + } + + // Deserialize. + stream.Seek(0, SeekOrigin.Begin); + + return _marsh.Unmarshal<T>(stream, BinaryMode.ForceBinary); + } + + /** <inheritDoc /> */ + public IBinaryObjectBuilder GetBuilder(Type type) + { + IgniteArgumentCheck.NotNull(type, "type"); + + IBinaryTypeDescriptor desc = _marsh.GetDescriptor(type); + + if (desc == null) + throw new IgniteException("Type is not binary (add it to BinaryConfiguration): " + + type.FullName); + + return Builder0(null, BinaryFromDescriptor(desc), desc); + } + + /** <inheritDoc /> */ + public IBinaryObjectBuilder GetBuilder(string typeName) + { + IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName"); + + IBinaryTypeDescriptor desc = _marsh.GetDescriptor(typeName); + + return Builder0(null, BinaryFromDescriptor(desc), desc); + } + + /** <inheritDoc /> */ + public IBinaryObjectBuilder GetBuilder(IBinaryObject obj) + { + IgniteArgumentCheck.NotNull(obj, "obj"); + + BinaryObject obj0 = obj as BinaryObject; + + if (obj0 == null) + throw new ArgumentException("Unsupported object type: " + obj.GetType()); + + IBinaryTypeDescriptor desc = _marsh.GetDescriptor(true, obj0.TypeId); + + return Builder0(null, obj0, desc); + } + + /** <inheritDoc /> */ + public int GetTypeId(string typeName) + { + IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName"); + + return Marshaller.GetDescriptor(typeName).TypeId; + } + + /** <inheritDoc /> */ + public ICollection<IBinaryType> GetBinaryTypes() + { + return Marshaller.Ignite.ClusterGroup.GetBinaryTypes(); + } + + /** <inheritDoc /> */ + public IBinaryType GetBinaryType(int typeId) + { + return Marshaller.GetBinaryType(typeId); + } + + /** <inheritDoc /> */ + public IBinaryType GetBinaryType(string typeName) + { + IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName"); + + return GetBinaryType(GetTypeId(typeName)); + } + + /** <inheritDoc /> */ + public IBinaryType GetBinaryType(Type type) + { + IgniteArgumentCheck.NotNull(type, "type"); + + var desc = Marshaller.GetDescriptor(type); + + return desc == null ? null : Marshaller.GetBinaryType(desc.TypeId); + } + + /// <summary> + /// Marshaller. + /// </summary> + internal Marshaller Marshaller + { + get + { + return _marsh; + } + } + + /// <summary> + /// Create empty binary object from descriptor. + /// </summary> + /// <param name="desc">Descriptor.</param> + /// <returns>Empty binary object.</returns> + private BinaryObject BinaryFromDescriptor(IBinaryTypeDescriptor desc) + { + var len = BinaryObjectHeader.Size; + + var hdr = new BinaryObjectHeader(desc.UserType, desc.TypeId, 0, len, 0, len, true, 0); + + var stream = new BinaryHeapStream(len); + + BinaryObjectHeader.Write(hdr, stream, 0); + + return new BinaryObject(_marsh, stream.InternalArray, 0, hdr); + } + + /// <summary> + /// Internal builder creation routine. + /// </summary> + /// <param name="parent">Parent builder.</param> + /// <param name="obj">binary object.</param> + /// <param name="desc">Type descriptor.</param> + /// <returns>Builder.</returns> + private BinaryObjectBuilder Builder0(BinaryObjectBuilder parent, BinaryObject obj, + IBinaryTypeDescriptor desc) + { + return new BinaryObjectBuilder(this, parent, obj, desc); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/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 new file mode 100644 index 0000000..2265abc --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryHeapStream.cs @@ -0,0 +1,452 @@ +/* + * 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.IO +{ + using System; + using System.Diagnostics; + using System.IO; + using System.Text; + + /// <summary> + /// Binary onheap stream. + /// </summary> + internal unsafe class BinaryHeapStream : BinaryStreamBase + { + /** Data array. */ + private byte[] _data; + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="cap">Initial capacity.</param> + public BinaryHeapStream(int cap) + { + Debug.Assert(cap >= 0); + + _data = new byte[cap]; + } + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="data">Data array.</param> + public BinaryHeapStream(byte[] data) + { + Debug.Assert(data != null); + + _data = data; + } + + /** <inheritdoc /> */ + public override void WriteByte(byte val) + { + int pos0 = EnsureWriteCapacityAndShift(1); + + _data[pos0] = val; + } + + /** <inheritdoc /> */ + public override byte ReadByte() + { + int pos0 = EnsureReadCapacityAndShift(1); + + return _data[pos0]; + } + + /** <inheritdoc /> */ + public override void WriteByteArray(byte[] val) + { + int pos0 = EnsureWriteCapacityAndShift(val.Length); + + fixed (byte* data0 = _data) + { + WriteByteArray0(val, data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override byte[] ReadByteArray(int cnt) + { + int pos0 = EnsureReadCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + return ReadByteArray0(cnt, data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override void WriteBoolArray(bool[] val) + { + int pos0 = EnsureWriteCapacityAndShift(val.Length); + + fixed (byte* data0 = _data) + { + WriteBoolArray0(val, data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override bool[] ReadBoolArray(int cnt) + { + int pos0 = EnsureReadCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + return ReadBoolArray0(cnt, data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override void WriteShort(short val) + { + int pos0 = EnsureWriteCapacityAndShift(2); + + fixed (byte* data0 = _data) + { + WriteShort0(val, data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override short ReadShort() + { + int pos0 = EnsureReadCapacityAndShift(2); + + fixed (byte* data0 = _data) + { + return ReadShort0(data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override void WriteShortArray(short[] val) + { + int cnt = val.Length << 1; + + int pos0 = EnsureWriteCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + WriteShortArray0(val, data0 + pos0, cnt); + } + } + + /** <inheritdoc /> */ + public override short[] ReadShortArray(int cnt) + { + int cnt0 = cnt << 1; + + int pos0 = EnsureReadCapacityAndShift(cnt0); + + fixed (byte* data0 = _data) + { + return ReadShortArray0(cnt, data0 + pos0, cnt0); + } + } + + /** <inheritdoc /> */ + public override void WriteCharArray(char[] val) + { + int cnt = val.Length << 1; + + int pos0 = EnsureWriteCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + WriteCharArray0(val, data0 + pos0, cnt); + } + } + + /** <inheritdoc /> */ + public override char[] ReadCharArray(int cnt) + { + int cnt0 = cnt << 1; + + int pos0 = EnsureReadCapacityAndShift(cnt0); + + fixed (byte* data0 = _data) + { + return ReadCharArray0(cnt, data0 + pos0, cnt0); + } + } + + /** <inheritdoc /> */ + public override void WriteInt(int val) + { + int pos0 = EnsureWriteCapacityAndShift(4); + + fixed (byte* data0 = _data) + { + WriteInt0(val, data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override void WriteInt(int writePos, int val) + { + EnsureWriteCapacity(writePos + 4); + + fixed (byte* data0 = _data) + { + WriteInt0(val, data0 + writePos); + } + } + + /** <inheritdoc /> */ + public override int ReadInt() + { + int pos0 = EnsureReadCapacityAndShift(4); + + fixed (byte* data0 = _data) + { + return ReadInt0(data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override void WriteIntArray(int[] val) + { + int cnt = val.Length << 2; + + int pos0 = EnsureWriteCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + WriteIntArray0(val, data0 + pos0, cnt); + } + } + + /** <inheritdoc /> */ + public override int[] ReadIntArray(int cnt) + { + int cnt0 = cnt << 2; + + int pos0 = EnsureReadCapacityAndShift(cnt0); + + fixed (byte* data0 = _data) + { + return ReadIntArray0(cnt, data0 + pos0, cnt0); + } + } + + /** <inheritdoc /> */ + public override void WriteFloatArray(float[] val) + { + int cnt = val.Length << 2; + + int pos0 = EnsureWriteCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + WriteFloatArray0(val, data0 + pos0, cnt); + } + } + + /** <inheritdoc /> */ + public override float[] ReadFloatArray(int cnt) + { + int cnt0 = cnt << 2; + + int pos0 = EnsureReadCapacityAndShift(cnt0); + + fixed (byte* data0 = _data) + { + return ReadFloatArray0(cnt, data0 + pos0, cnt0); + } + } + + /** <inheritdoc /> */ + public override void WriteLong(long val) + { + int pos0 = EnsureWriteCapacityAndShift(8); + + fixed (byte* data0 = _data) + { + WriteLong0(val, data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override long ReadLong() + { + int pos0 = EnsureReadCapacityAndShift(8); + + fixed (byte* data0 = _data) + { + return ReadLong0(data0 + pos0); + } + } + + /** <inheritdoc /> */ + public override void WriteLongArray(long[] val) + { + int cnt = val.Length << 3; + + int pos0 = EnsureWriteCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + WriteLongArray0(val, data0 + pos0, cnt); + } + } + + /** <inheritdoc /> */ + public override long[] ReadLongArray(int cnt) + { + int cnt0 = cnt << 3; + + int pos0 = EnsureReadCapacityAndShift(cnt0); + + fixed (byte* data0 = _data) + { + return ReadLongArray0(cnt, data0 + pos0, cnt0); + } + } + + /** <inheritdoc /> */ + public override void WriteDoubleArray(double[] val) + { + int cnt = val.Length << 3; + + int pos0 = EnsureWriteCapacityAndShift(cnt); + + fixed (byte* data0 = _data) + { + WriteDoubleArray0(val, data0 + pos0, cnt); + } + } + + /** <inheritdoc /> */ + public override double[] ReadDoubleArray(int cnt) + { + int cnt0 = cnt << 3; + + int pos0 = EnsureReadCapacityAndShift(cnt0); + + fixed (byte* data0 = _data) + { + return ReadDoubleArray0(cnt, data0 + pos0, cnt0); + } + } + + /** <inheritdoc /> */ + public override int WriteString(char* chars, int charCnt, int byteCnt, Encoding encoding) + { + int pos0 = EnsureWriteCapacityAndShift(byteCnt); + + int written; + + fixed (byte* data0 = _data) + { + written = WriteString0(chars, charCnt, byteCnt, encoding, data0 + pos0); + } + + return written; + } + + /** <inheritdoc /> */ + public override void Write(byte* src, int cnt) + { + EnsureWriteCapacity(Pos + cnt); + + fixed (byte* data0 = _data) + { + WriteInternal(src, cnt, data0); + } + + ShiftWrite(cnt); + } + + /** <inheritdoc /> */ + public override void Read(byte* dest, int cnt) + { + fixed (byte* data0 = _data) + { + ReadInternal(data0, dest, cnt); + } + } + + /** <inheritdoc /> */ + public override int Remaining + { + get { return _data.Length - Pos; } + } + + /** <inheritdoc /> */ + public override byte[] GetArray() + { + return _data; + } + + /** <inheritdoc /> */ + public override byte[] GetArrayCopy() + { + byte[] copy = new byte[Pos]; + + Buffer.BlockCopy(_data, 0, copy, 0, Pos); + + return copy; + } + + /** <inheritdoc /> */ + public override bool IsSameArray(byte[] arr) + { + return _data == arr; + } + + /** <inheritdoc /> */ + protected override void Dispose(bool disposing) + { + // No-op. + } + + /// <summary> + /// Internal array. + /// </summary> + internal byte[] InternalArray + { + get { return _data; } + } + + /** <inheritdoc /> */ + protected override void EnsureWriteCapacity(int cnt) + { + if (cnt > _data.Length) + { + int newCap = Capacity(_data.Length, cnt); + + byte[] data0 = new byte[newCap]; + + // Copy the whole initial array length here because it can be changed + // from Java without position adjusting. + Buffer.BlockCopy(_data, 0, data0, 0, _data.Length); + + _data = data0; + } + } + + /** <inheritdoc /> */ + protected override void EnsureReadCapacity(int cnt) + { + if (_data.Length - Pos < cnt) + throw new EndOfStreamException("Not enough data in stream [expected=" + cnt + + ", remaining=" + (_data.Length - Pos) + ']'); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs new file mode 100644 index 0000000..dcbff81 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs @@ -0,0 +1,114 @@ +/* + * 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.IO +{ + using System; + using System.IO; + + /// <summary> + /// Adapter providing .Net streaming functionality over the binary stream. + /// </summary> + internal class BinaryStreamAdapter : Stream + { + /// <summary> + /// + /// </summary> + private readonly IBinaryStream _stream; + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="stream">Stream.</param> + public BinaryStreamAdapter(IBinaryStream stream) + { + _stream = stream; + } + + /** <inheritDoc /> */ + public override void Write(byte[] buffer, int offset, int count) + { + _stream.Write(buffer, offset, count); + } + + /** <inheritDoc /> */ + public override int Read(byte[] buffer, int offset, int count) + { + _stream.Read(buffer, offset, count); + + return count; + } + + /** <inheritDoc /> */ + public override void Flush() + { + // No-op. + } + + /** <inheritDoc /> */ + public override bool CanRead + { + get { return true; } + } + + /** <inheritDoc /> */ + public override bool CanWrite + { + get { return true; } + } + + /** <inheritDoc /> */ + public override bool CanSeek + { + get { return false; } + } + + /** <inheritDoc /> */ + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Stream is not seekable."); + } + + /** <inheritDoc /> */ + public override long Position + { + get + { + throw new NotSupportedException("Stream is not seekable."); + } + set + { + throw new NotSupportedException("Stream is not seekable."); + } + } + + /** <inheritDoc /> */ + public override long Length + { + get + { + throw new NotSupportedException("Stream is not seekable."); + } + } + + /** <inheritDoc /> */ + public override void SetLength(long value) + { + throw new NotSupportedException("Stream is not seekable."); + } + } +}
