Esempio n. 1
0
        /// <summary>
        /// Reads the binary object in binary form.
        /// </summary>
        private BinaryObject ReadAsBinary(int binaryBytesPos, int dataLen, bool doDetach)
        {
            try
            {
                Stream.Seek(dataLen + binaryBytesPos, SeekOrigin.Begin);

                var offs = Stream.ReadInt(); // offset inside data

                var pos = binaryBytesPos + offs;

                var hdr = BinaryObjectHeader.Read(Stream, pos);

                if (!doDetach)
                {
                    return(new BinaryObject(_marsh, Stream.GetArray(), pos, hdr));
                }

                Stream.Seek(pos, SeekOrigin.Begin);

                return(new BinaryObject(_marsh, Stream.ReadByteArray(hdr.Length), 0, hdr));
            }
            finally
            {
                Stream.Seek(binaryBytesPos + dataLen + 4, SeekOrigin.Begin);
            }
        }
Esempio n. 2
0
        /** <inheritDoc /> */
        public IBinaryObject Build()
        {
            // Assume that resulting length will be no less than header + [fields_cnt] * 12;
            int estimatedCapacity = BinaryObjectHeader.Size + (_vals == null ? 0 : _vals.Count * 12);

            using (var outStream = new BinaryHeapStream(estimatedCapacity))
            {
                BinaryWriter writer = _binary.Marshaller.StartMarshal(outStream);

                writer.SetBuilder(this);

                // All related builders will work in this context with this writer.
                _parent._ctx = new Context(writer);

                try
                {
                    // Write.
                    writer.Write(this);

                    // Process metadata.
                    _binary.Marshaller.FinishMarshal(writer);

                    // Create binary object once metadata is processed.
                    return(new BinaryObject(_binary.Marshaller, outStream.InternalArray, 0,
                                            BinaryObjectHeader.Read(outStream, 0)));
                }
                finally
                {
                    // Cleanup.
                    _parent._ctx.Closed = true;
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Reads the schema, maintains stream position.
        /// </summary>
        public static int[] GetFieldIds(BinaryObjectHeader hdr, IIgniteInternal ignite, IBinaryStream stream,
                                        int objectPos)
        {
            Debug.Assert(stream != null);

            if (hdr.IsCompactFooter)
            {
                // Get schema from Java
                return(GetFieldIds(hdr, ignite));
            }

            var pos = stream.Position;

            stream.Seek(objectPos + hdr.SchemaOffset, SeekOrigin.Begin);

            var count = hdr.SchemaFieldCount;

            var offsetSize = hdr.SchemaFieldOffsetSize;

            var res = new int[count];

            for (var i = 0; i < count; i++)
            {
                res[i] = stream.ReadInt();
                stream.Seek(offsetSize, SeekOrigin.Current);  // Skip offsets.
            }

            stream.Seek(pos, SeekOrigin.Begin);

            return(res);
        }
Esempio n. 4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BinaryObject" /> class.
        /// </summary>
        /// <param name="marsh">Marshaller.</param>
        /// <param name="data">Raw data of this binary object.</param>
        /// <param name="offset">Offset in data array.</param>
        /// <param name="header">The header.</param>
        public BinaryObject(Marshaller marsh, byte[] data, int offset, BinaryObjectHeader header)
        {
            _marsh = marsh;

            _data   = data;
            _offset = offset;

            _header = header;
        }
Esempio n. 5
0
        /// <summary>
        /// Gets the cached schema.
        /// </summary>
        private static int[] GetCachedSchema(BinaryObjectHeader hdr, IIgniteInternal ignite)
        {
            var cachedHolder = ignite.Marshaller.GetCachedBinaryTypeHolder(hdr.TypeId);

            if (cachedHolder == null || cachedHolder.BinaryType == null || cachedHolder.BinaryType.Schema == null)
            {
                return(null);
            }

            return(cachedHolder.BinaryType.Schema.Get(hdr.SchemaId));
        }
Esempio n. 6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BinaryObject" /> class.
        /// </summary>
        /// <param name="marsh">Marshaller.</param>
        /// <param name="data">Raw data of this binary object.</param>
        /// <param name="offset">Offset in data array.</param>
        /// <param name="header">The header.</param>
        public BinaryObject(Marshaller marsh, byte[] data, int offset, BinaryObjectHeader header)
        {
            Debug.Assert(marsh != null);
            Debug.Assert(data != null);
            Debug.Assert(offset >= 0 && offset < data.Length);

            _marsh = marsh;

            _data   = data;
            _offset = offset;

            _header = header;
        }
Esempio n. 7
0
        /// <summary>
        /// Lazy fields initialization routine.
        /// </summary>
        private void InitializeFields()
        {
            if (_fields != null)
            {
                return;
            }

            var stream = new BinaryHeapStream(_data);

            var hdr = BinaryObjectHeader.Read(stream, _offset);

            _fields = hdr.ReadSchemaAsDictionary(stream, _offset) ?? EmptyFields;
        }
Esempio n. 8
0
        /// <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.TypeId, 0, len, 0, len,
                                             desc.UserType ? BinaryObjectHeader.Flag.UserType : BinaryObjectHeader.Flag.None);

            var stream = new BinaryHeapStream(len);

            BinaryObjectHeader.Write(hdr, stream, 0);

            return(new BinaryObject(_marsh, stream.InternalArray, 0, hdr));
        }
Esempio n. 9
0
        /// <summary>
        /// Lazy fields initialization routine.
        /// </summary>
        private void InitializeFields(IBinaryTypeDescriptor desc = null)
        {
            if (_fields != null)
            {
                return;
            }

            desc = desc ?? _marsh.GetDescriptor(true, _header.TypeId);

            using (var stream = new BinaryHeapStream(_data))
            {
                var hdr = BinaryObjectHeader.Read(stream, _offset);

                _fields = BinaryObjectSchemaSerializer.ReadSchema(stream, _offset, hdr, desc.Schema, _marsh)
                          .ToDictionary() ?? EmptyFields;
            }
        }
        /// <summary>
        /// Gets the field ids.
        /// </summary>
        private static int[] GetFieldIds(BinaryObjectHeader hdr, Ignite ignite)
        {
            Debug.Assert(hdr.TypeId != BinaryUtils.TypeUnregistered);

            int[] fieldIds = null;

            if (ignite != null)
            {
                fieldIds = ignite.BinaryProcessor.GetSchema(hdr.TypeId, hdr.SchemaId);
            }

            if (fieldIds == null)
            {
                throw new BinaryObjectException("Cannot find schema for object with compact footer [" +
                                                "typeId=" + hdr.TypeId + ", schemaId=" + hdr.SchemaId + ']');
            }
            return(fieldIds);
        }
        /// <summary>
        /// Gets the field ids.
        /// </summary>
        private static int[] GetFieldIds(BinaryObjectHeader hdr, BinaryObjectSchema schema, Marshaller marsh)
        {
            var fieldIds = schema.Get(hdr.SchemaId);

            if (fieldIds == null)
            {
                if (marsh.Ignite != null)
                {
                    fieldIds = marsh.Ignite.BinaryProcessor.GetSchema(hdr.TypeId, hdr.SchemaId);
                }

                if (fieldIds == null)
                {
                    throw new BinaryObjectException("Cannot find schema for object with compact footer [" +
                                                    "typeId=" + hdr.TypeId + ", schemaId=" + hdr.SchemaId + ']');
                }
            }
            return(fieldIds);
        }
Esempio n. 12
0
        /// <summary>
        /// Create empty binary object from descriptor.
        /// </summary>
        /// <param name="desc">Descriptor.</param>
        /// <returns>Empty binary object.</returns>
        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));
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Gets the field ids.
        /// </summary>
        private static int[] GetFieldIds(BinaryObjectHeader hdr, IIgniteInternal ignite)
        {
            Debug.Assert(hdr.TypeId != BinaryTypeId.Unregistered);

            int[] fieldIds = null;

            if (ignite != null)
            {
                fieldIds = GetCachedSchema(hdr, ignite) ??
                           ignite.Marshaller.GetBinaryType(hdr.TypeId).Schema.Get(hdr.SchemaId);
            }

            if (fieldIds == null)
            {
                throw new BinaryObjectException("Cannot find schema for object with compact footer [" +
                                                "typeId=" + hdr.TypeId + ", schemaId=" + hdr.SchemaId + ']');
            }

            return(fieldIds);
        }
Esempio n. 14
0
        /// <summary>
        /// Writes collected schema to the stream and pops it.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="schemaOffset">The schema offset.</param>
        /// <param name="schemaId">The schema identifier.</param>
        /// <param name="flags">Flags according to offset sizes.</param>
        /// <returns>
        /// True if current schema was non empty; false otherwise.
        /// </returns>
        public bool WriteSchema(IBinaryStream stream, int schemaOffset, out int schemaId,
                                ref BinaryObjectHeader.Flag flags)
        {
            schemaId = Fnv1Hash.Basis;

            var count = _idx - schemaOffset;

            if (count == 0)
            {
                return(false);
            }

            flags |= BinaryObjectHeader.WriteSchema(_fields, stream, schemaOffset, count);

            for (var i = schemaOffset; i < _idx; i++)
            {
                schemaId = Fnv1Hash.Update(schemaId, _fields[i].Id);
            }

            return(true);
        }
Esempio n. 15
0
        /// <summary>
        /// Write object.
        /// </summary>
        /// <param name="obj">Object.</param>
        public void Write <T>(T obj)
        {
            // Handle special case for null.
            // ReSharper disable once CompareNonConstrainedGenericWithNull
            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;
            }

            // Are we dealing with a well-known type?
            var handler = BinarySystemHandlers.GetWriteHandler(type);

            if (handler != null)
            {
                if (handler.SupportsHandles && WriteHandle(_stream.Position, obj))
                {
                    return;
                }

                handler.Write(this, obj);

                return;
            }

            // Wrap objects as required.
            if (WrapperFunc != null && type != WrapperFunc.Method.ReturnType)
            {
                if (_isInWrapper)
                {
                    _isInWrapper = false;
                }
                else
                {
                    _isInWrapper = true;
                    Write(WrapperFunc(obj));

                    return;
                }
            }

            // Suppose that we faced normal object and perform descriptor lookup.
            var desc = _marsh.GetDescriptor(type);

            // Writing normal object.
            var pos = _stream.Position;

            // Dealing with handles.
            if (desc.Serializer.SupportsHandles && WriteHandle(pos, obj))
            {
                return;
            }

            // Skip header length as not everything is known now
            _stream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);

            // Write type name for unregistered types
            if (!desc.IsRegistered)
            {
                WriteString(Marshaller.GetTypeName(type));
            }

            var headerSize = _stream.Position - pos;

            // Preserve old frame.
            var oldFrame = _frame;

            // Push new frame.
            _frame.RawPos            = 0;
            _frame.Pos               = pos;
            _frame.Struct            = new BinaryStructureTracker(desc, desc.WriterTypeStructure);
            _frame.HasCustomTypeData = false;

            var schemaIdx = _schema.PushSchema();

            try
            {
                // Write object fields.
                desc.Serializer.WriteBinary(obj, this);
                var dataEnd = _stream.Position;

                // Write schema
                var schemaOffset = dataEnd - pos;

                int schemaId;

                var flags = desc.UserType
                    ? BinaryObjectHeader.Flag.UserType
                    : BinaryObjectHeader.Flag.None;

                if (_frame.HasCustomTypeData)
                {
                    flags |= BinaryObjectHeader.Flag.CustomDotNetType;
                }

                if (Marshaller.CompactFooter && desc.UserType)
                {
                    flags |= BinaryObjectHeader.Flag.CompactFooter;
                }

                var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags);

                if (hasSchema)
                {
                    flags |= BinaryObjectHeader.Flag.HasSchema;

                    // Calculate and write header.
                    if (_frame.RawPos > 0)
                    {
                        _stream.WriteInt(_frame.RawPos - pos); // raw offset is in the last 4 bytes
                    }
                    // Update schema in type descriptor
                    if (desc.Schema.Get(schemaId) == null)
                    {
                        desc.Schema.Add(schemaId, _schema.GetSchema(schemaIdx));
                    }
                }
                else
                {
                    schemaOffset = headerSize;
                }

                if (_frame.RawPos > 0)
                {
                    flags |= BinaryObjectHeader.Flag.HasRaw;
                }

                var len = _stream.Position - pos;

                var hashCode = BinaryArrayEqualityComparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size,
                                                                       dataEnd - pos - BinaryObjectHeader.Size);

                var header = new BinaryObjectHeader(desc.IsRegistered ? desc.TypeId : BinaryTypeId.Unregistered,
                                                    hashCode, len, schemaId, schemaOffset, 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.
            _frame.Struct.UpdateWriterStructure(this);

            // Restore old frame.
            _frame = oldFrame;
        }
Esempio n. 16
0
        /// <summary>
        /// Reads the schema according to this header data.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="position">The position.</param>
        /// <param name="hdr">The header.</param>
        /// <param name="fieldIdsFunc">The field ids function.</param>
        /// <returns>
        /// Schema.
        /// </returns>
        public static unsafe BinaryObjectSchemaField[] ReadSchema(IBinaryStream stream, int position,
                                                                  BinaryObjectHeader hdr, Func <int[]> fieldIdsFunc)
        {
            Debug.Assert(stream != null);
            Debug.Assert(fieldIdsFunc != null);

            var schemaSize = hdr.SchemaFieldCount;

            if (schemaSize == 0)
            {
                return(null);
            }

            stream.Seek(position + hdr.SchemaOffset, SeekOrigin.Begin);

            var res = new BinaryObjectSchemaField[schemaSize];

            var offsetSize = hdr.SchemaFieldOffsetSize;

            if (hdr.IsCompactFooter)
            {
                var fieldIds = fieldIdsFunc();

                Debug.Assert(fieldIds.Length == schemaSize);

                if (offsetSize == 1)
                {
                    for (var i = 0; i < schemaSize; i++)
                    {
                        res[i] = new BinaryObjectSchemaField(fieldIds[i], stream.ReadByte());
                    }
                }
                else if (offsetSize == 2)
                {
                    for (var i = 0; i < schemaSize; i++)
                    {
                        res[i] = new BinaryObjectSchemaField(fieldIds[i], (ushort)stream.ReadShort());
                    }
                }
                else
                {
                    for (var i = 0; i < schemaSize; i++)
                    {
                        res[i] = new BinaryObjectSchemaField(fieldIds[i], stream.ReadInt());
                    }
                }
            }
            else
            {
                if (offsetSize == 1)
                {
                    for (var i = 0; i < schemaSize; i++)
                    {
                        res[i] = new BinaryObjectSchemaField(stream.ReadInt(), stream.ReadByte());
                    }
                }
                else if (offsetSize == 2)
                {
                    for (var i = 0; i < schemaSize; i++)
                    {
                        res[i] = new BinaryObjectSchemaField(stream.ReadInt(), (ushort)stream.ReadShort());
                    }
                }
                else
                {
                    if (BitConverter.IsLittleEndian)
                    {
                        fixed(BinaryObjectSchemaField *ptr = &res[0])
                        {
                            stream.Read((byte *)ptr, schemaSize * BinaryObjectSchemaField.Size);
                        }
                    }
                    else
                    {
                        for (var i = 0; i < schemaSize; i++)
                        {
                            res[i] = new BinaryObjectSchemaField(stream.ReadInt(), stream.ReadInt());
                        }
                    }
                }
            }

            return(res);
        }
Esempio n. 17
0
        /// <summary>
        /// Reads the schema according to this header data.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="position">The position.</param>
        /// <param name="hdr">The header.</param>
        /// <param name="schema">The schema.</param>
        /// <param name="ignite">The ignite.</param>
        /// <returns>
        /// Schema.
        /// </returns>
        public static BinaryObjectSchemaField[] ReadSchema(IBinaryStream stream, int position, BinaryObjectHeader hdr,
                                                           BinaryObjectSchema schema, IIgniteInternal ignite)
        {
            Debug.Assert(stream != null);
            Debug.Assert(schema != null);

            return(ReadSchema(stream, position, hdr, () => GetFieldIds(hdr, schema, ignite)));
        }
Esempio n. 18
0
 /// <summary>
 /// Gets the field ids.
 /// </summary>
 private static int[] GetFieldIds(BinaryObjectHeader hdr, BinaryObjectSchema schema, IIgniteInternal ignite)
 {
     return(schema.Get(hdr.SchemaId) ?? GetFieldIds(hdr, ignite));
 }
        /// <summary>
        /// Reads the schema according to this header data.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="position">The position.</param>
        /// <param name="hdr">The header.</param>
        /// <param name="schema">The schema.</param>
        /// <param name="marsh">The marshaller.</param>
        /// <returns>
        /// Schema.
        /// </returns>
        public static BinaryObjectSchemaField[] ReadSchema(IBinaryStream stream, int position, BinaryObjectHeader hdr,
                                                           BinaryObjectSchema schema, Marshaller marsh)
        {
            Debug.Assert(stream != null);
            Debug.Assert(schema != null);
            Debug.Assert(marsh != null);

            return(ReadSchema(stream, position, hdr, () => GetFieldIds(hdr, schema, marsh)));
        }
Esempio n. 20
0
        private T ReadFullObject <T>(int pos)
        {
            var hdr = BinaryObjectHeader.Read(Stream, pos);

            // Validate protocol version.
            BinaryUtils.ValidateProtocolVersion(hdr.Version);

            try
            {
                // Already read this object?
                object hndObj;

                if (_hnds != null && _hnds.TryGetValue(pos, out hndObj))
                {
                    return((T)hndObj);
                }

                if (hdr.IsUserType && _mode == BinaryMode.ForceBinary)
                {
                    BinaryObject portObj;

                    if (_detach)
                    {
                        Stream.Seek(pos, SeekOrigin.Begin);

                        portObj = new BinaryObject(_marsh, Stream.ReadByteArray(hdr.Length), 0, hdr);
                    }
                    else
                    {
                        portObj = new BinaryObject(_marsh, Stream.GetArray(), pos, hdr);
                    }

                    T obj = _builder == null ? TypeCaster <T> .Cast(portObj) : TypeCaster <T> .Cast(_builder.Child(portObj));

                    AddHandle(pos, obj);

                    return(obj);
                }
                else
                {
                    // Find descriptor.
                    var desc = hdr.TypeId == BinaryUtils.TypeUnregistered
                        ? _marsh.GetDescriptor(Type.GetType(ReadString(), true))
                        : _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId, true);

                    // Instantiate object.
                    if (desc.Type == null)
                    {
                        if (desc is BinarySurrogateTypeDescriptor)
                        {
                            throw new BinaryObjectException(string.Format(
                                                                "Unknown type ID: {0}. " +
                                                                "This usually indicates missing BinaryConfiguration. " +
                                                                "Make sure that all nodes have the same BinaryConfiguration.", hdr.TypeId));
                        }

                        throw new BinaryObjectException(string.Format(
                                                            "No matching type found for object [typeId={0}, typeName={1}]. " +
                                                            "This usually indicates that assembly with specified type is not loaded on a node. " +
                                                            "When using Apache.Ignite.exe, make sure to load assemblies with -assembly parameter.",
                                                            desc.TypeId, desc.TypeName));
                    }

                    // Preserve old frame.
                    var oldFrame = _frame;

                    // Set new frame.
                    _frame.Hdr = hdr;
                    _frame.Pos = pos;
                    SetCurSchema(desc);
                    _frame.Struct = new BinaryStructureTracker(desc, desc.ReaderTypeStructure);
                    _frame.Raw    = false;

                    // Read object.
                    var obj = desc.Serializer.ReadBinary <T>(this, desc, pos);

                    _frame.Struct.UpdateReaderStructure();

                    // Restore old frame.
                    _frame = oldFrame;

                    return(obj);
                }
            }
            finally
            {
                // Advance stream pointer.
                Stream.Seek(pos + hdr.Length, SeekOrigin.Begin);
            }
        }
Esempio n. 21
0
        private T ReadFullObject <T>(int pos)
        {
            var hdr = BinaryObjectHeader.Read(Stream, pos);

            // Validate protocol version.
            BinaryUtils.ValidateProtocolVersion(hdr.Version);

            try
            {
                // Already read this object?
                object hndObj;

                if (_hnds != null && _hnds.TryGetValue(pos, out hndObj))
                {
                    return((T)hndObj);
                }

                if (hdr.IsUserType && _mode == BinaryMode.ForceBinary)
                {
                    BinaryObject portObj;

                    if (_detach)
                    {
                        Stream.Seek(pos, SeekOrigin.Begin);

                        portObj = new BinaryObject(_marsh, Stream.ReadByteArray(hdr.Length), 0, hdr);
                    }
                    else
                    {
                        portObj = new BinaryObject(_marsh, Stream.GetArray(), pos, hdr);
                    }

                    T obj = _builder == null ? TypeCaster <T> .Cast(portObj) : TypeCaster <T> .Cast(_builder.Child(portObj));

                    AddHandle(pos, obj);

                    return(obj);
                }
                else
                {
                    // Find descriptor.
                    IBinaryTypeDescriptor desc;

                    if (!_descs.TryGetValue(BinaryUtils.TypeKey(hdr.IsUserType, hdr.TypeId), out desc))
                    {
                        throw new BinaryObjectException("Unknown type ID: " + hdr.TypeId);
                    }

                    // Instantiate object.
                    if (desc.Type == null)
                    {
                        throw new BinaryObjectException("No matching type found for object [typeId=" +
                                                        desc.TypeId + ", typeName=" + desc.TypeName + ']');
                    }

                    // Preserve old frame.
                    var  oldHdr       = _curHdr;
                    int  oldPos       = _curPos;
                    var  oldStruct    = _curStruct;
                    bool oldRaw       = _curRaw;
                    var  oldSchema    = _curSchema;
                    var  oldSchemaMap = _curSchemaMap;

                    // Set new frame.
                    _curHdr = hdr;
                    _curPos = pos;
                    SetCurSchema(desc);
                    _curStruct = new BinaryStructureTracker(desc, desc.ReaderTypeStructure);
                    _curRaw    = false;

                    // Read object.
                    Stream.Seek(pos + BinaryObjectHeader.Size, SeekOrigin.Begin);

                    object obj;

                    var sysSerializer = desc.Serializer as IBinarySystemTypeSerializer;

                    if (sysSerializer != null)
                    {
                        obj = sysSerializer.ReadInstance(this);
                    }
                    else
                    {
                        try
                        {
                            obj = FormatterServices.GetUninitializedObject(desc.Type);

                            // Save handle.
                            AddHandle(pos, obj);
                        }
                        catch (Exception e)
                        {
                            throw new BinaryObjectException("Failed to create type instance: " +
                                                            desc.Type.AssemblyQualifiedName, e);
                        }

                        desc.Serializer.ReadBinary(obj, this);
                    }

                    _curStruct.UpdateReaderStructure();

                    // Restore old frame.
                    _curHdr       = oldHdr;
                    _curPos       = oldPos;
                    _curStruct    = oldStruct;
                    _curRaw       = oldRaw;
                    _curSchema    = oldSchema;
                    _curSchemaMap = oldSchemaMap;

                    // Process wrappers. We could introduce a common interface, but for only 2 if-else is faster.
                    var wrappedSerializable = obj as SerializableObjectHolder;

                    if (wrappedSerializable != null)
                    {
                        return((T)wrappedSerializable.Item);
                    }

                    var wrappedDateTime = obj as DateTimeHolder;

                    if (wrappedDateTime != null)
                    {
                        return(TypeCaster <T> .Cast(wrappedDateTime.Item));
                    }

                    return((T)obj);
                }
            }
            finally
            {
                // Advance stream pointer.
                Stream.Seek(pos + hdr.Length, SeekOrigin.Begin);
            }
        }
Esempio n. 22
0
        /// <summary>
        /// Internal mutation routine.
        /// </summary>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="ctx">Context.</param>
        /// <param name="changeHash">WHether hash should be changed.</param>
        /// <param name="vals">Values to be replaced.</param>
        /// <returns>Mutated object.</returns>
        private void Mutate0(Context ctx, BinaryHeapStream inStream, IBinaryStream outStream,
                             bool changeHash, IDictionary <int, BinaryBuilderField> vals)
        {
            int inStartPos  = inStream.Position;
            int outStartPos = outStream.Position;

            byte inHdr = inStream.ReadByte();

            if (inHdr == BinaryUtils.HdrNull)
            {
                outStream.WriteByte(BinaryUtils.HdrNull);
            }
            else if (inHdr == BinaryUtils.HdrHnd)
            {
                int inHnd = inStream.ReadInt();

                int oldPos = inStartPos - inHnd;
                int newPos;

                if (ctx.OldToNew(oldPos, out newPos))
                {
                    // Handle is still valid.
                    outStream.WriteByte(BinaryUtils.HdrHnd);
                    outStream.WriteInt(outStartPos - newPos);
                }
                else
                {
                    // Handle is invalid, write full object.
                    int inRetPos = inStream.Position;

                    inStream.Seek(oldPos, SeekOrigin.Begin);

                    Mutate0(ctx, inStream, outStream, false, EmptyVals);

                    inStream.Seek(inRetPos, SeekOrigin.Begin);
                }
            }
            else if (inHdr == BinaryUtils.HdrFull)
            {
                var inHeader = BinaryObjectHeader.Read(inStream, inStartPos);

                BinaryUtils.ValidateProtocolVersion(inHeader.Version);

                int hndPos;

                if (ctx.AddOldToNew(inStartPos, outStartPos, out hndPos))
                {
                    // Object could be cached in parent builder.
                    BinaryBuilderField cachedVal;

                    if (_parent._cache != null && _parent._cache.TryGetValue(inStartPos, out cachedVal))
                    {
                        WriteField(ctx, cachedVal);
                    }
                    else
                    {
                        // New object, write in full form.
                        var inSchema = BinaryObjectSchemaSerializer.ReadSchema(inStream, inStartPos, inHeader,
                                                                               _desc.Schema, _binary.Marshaller.Ignite);

                        var outSchema = BinaryObjectSchemaHolder.Current;
                        var schemaIdx = outSchema.PushSchema();

                        try
                        {
                            // Skip header as it is not known at this point.
                            outStream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);

                            if (inSchema != null)
                            {
                                foreach (var inField in inSchema)
                                {
                                    BinaryBuilderField fieldVal;

                                    var fieldFound = vals.TryGetValue(inField.Id, out fieldVal);

                                    if (fieldFound && fieldVal == BinaryBuilderField.RmvMarker)
                                    {
                                        continue;
                                    }

                                    outSchema.PushField(inField.Id, outStream.Position - outStartPos);

                                    if (!fieldFound)
                                    {
                                        fieldFound = _parent._cache != null &&
                                                     _parent._cache.TryGetValue(inField.Offset + inStartPos,
                                                                                out fieldVal);
                                    }

                                    if (fieldFound)
                                    {
                                        WriteField(ctx, fieldVal);

                                        vals.Remove(inField.Id);
                                    }
                                    else
                                    {
                                        // Field is not tracked, re-write as is.
                                        inStream.Seek(inField.Offset + inStartPos, SeekOrigin.Begin);

                                        Mutate0(ctx, inStream, outStream, false, EmptyVals);
                                    }
                                }
                            }

                            // Write remaining new fields.
                            foreach (var valEntry in vals)
                            {
                                if (valEntry.Value == BinaryBuilderField.RmvMarker)
                                {
                                    continue;
                                }

                                outSchema.PushField(valEntry.Key, outStream.Position - outStartPos);

                                WriteField(ctx, valEntry.Value);
                            }

                            var flags = inHeader.IsUserType
                                ? BinaryObjectHeader.Flag.UserType
                                : BinaryObjectHeader.Flag.None;

                            if (inHeader.IsCustomDotNetType)
                            {
                                flags |= BinaryObjectHeader.Flag.CustomDotNetType;
                            }

                            // Write raw data.
                            int outRawOff = outStream.Position - outStartPos;

                            if (inHeader.HasRaw)
                            {
                                var inRawOff = inHeader.GetRawOffset(inStream, inStartPos);
                                var inRawLen = inHeader.SchemaOffset - inRawOff;

                                flags |= BinaryObjectHeader.Flag.HasRaw;

                                outStream.Write(inStream.InternalArray, inStartPos + inRawOff, inRawLen);
                            }

                            // Write schema
                            int outSchemaOff = outRawOff;
                            var schemaPos    = outStream.Position;
                            int outSchemaId;

                            if (inHeader.IsCompactFooter)
                            {
                                flags |= BinaryObjectHeader.Flag.CompactFooter;
                            }

                            var hasSchema = outSchema.WriteSchema(outStream, schemaIdx, out outSchemaId, ref flags);

                            if (hasSchema)
                            {
                                outSchemaOff = schemaPos - outStartPos;

                                flags |= BinaryObjectHeader.Flag.HasSchema;

                                if (inHeader.HasRaw)
                                {
                                    outStream.WriteInt(outRawOff);
                                }

                                if (_desc.Schema.Get(outSchemaId) == null)
                                {
                                    _desc.Schema.Add(outSchemaId, outSchema.GetSchema(schemaIdx));
                                }
                            }

                            var outLen = outStream.Position - outStartPos;

                            var outHash = inHeader.HashCode;

                            if (changeHash)
                            {
                                // Get from identity resolver.
                                outHash = BinaryArrayEqualityComparer.GetHashCode(outStream,
                                                                                  outStartPos + BinaryObjectHeader.Size,
                                                                                  schemaPos - outStartPos - BinaryObjectHeader.Size);
                            }

                            var outHeader = new BinaryObjectHeader(inHeader.TypeId, outHash, outLen,
                                                                   outSchemaId, outSchemaOff, flags);

                            BinaryObjectHeader.Write(outHeader, outStream, outStartPos);

                            outStream.Seek(outStartPos + outLen, SeekOrigin.Begin);  // seek to the end of the object
                        }
                        finally
                        {
                            outSchema.PopSchema(schemaIdx);
                        }
                    }
                }
                else
                {
                    // Object has already been written, write as handle.
                    outStream.WriteByte(BinaryUtils.HdrHnd);
                    outStream.WriteInt(outStartPos - hndPos);
                }

                // Synchronize input stream position.
                inStream.Seek(inStartPos + inHeader.Length, SeekOrigin.Begin);
            }
            else
            {
                // Try writing as well-known type with fixed size.
                outStream.WriteByte(inHdr);

                if (!WriteAsPredefined(inHdr, inStream, outStream, ctx))
                {
                    throw new IgniteException("Unexpected header [position=" + (inStream.Position - 1) +
                                              ", header=" + inHdr + ']');
                }
            }
        }
Esempio n. 23
0
        /// <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 = type.IsEnum ? null : _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;

                    var flags = desc.UserType
                        ? BinaryObjectHeader.Flag.UserType
                        : BinaryObjectHeader.Flag.None;

                    var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags);

                    if (hasSchema)
                    {
                        flags |= BinaryObjectHeader.Flag.HasSchema;

                        // Calculate and write header.
                        if (_curRawPos > 0)
                        {
                            _stream.WriteInt(_curRawPos - pos); // raw offset is in the last 4 bytes
                        }
                    }
                    else
                    {
                        schemaOffset = BinaryObjectHeader.Size;
                    }

                    if (_curRawPos > 0)
                    {
                        flags |= BinaryObjectHeader.Flag.HasRaw;
                    }

                    var len = _stream.Position - pos;

                    var header = new BinaryObjectHeader(desc.TypeId, obj.GetHashCode(), len,
                                                        schemaId, schemaOffset, 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);
            }
        }
Esempio n. 24
0
        private T ReadFullObject <T>(int pos)
        {
            var hdr = BinaryObjectHeader.Read(Stream, pos);

            // Validate protocol version.
            BinaryUtils.ValidateProtocolVersion(hdr.Version);

            try
            {
                // Already read this object?
                object hndObj;

                if (_hnds != null && _hnds.TryGetValue(pos, out hndObj))
                {
                    return((T)hndObj);
                }

                if (hdr.IsUserType && _mode == BinaryMode.ForceBinary)
                {
                    BinaryObject portObj;

                    if (_detach)
                    {
                        Stream.Seek(pos, SeekOrigin.Begin);

                        portObj = new BinaryObject(_marsh, Stream.ReadByteArray(hdr.Length), 0, hdr);
                    }
                    else
                    {
                        portObj = new BinaryObject(_marsh, Stream.GetArray(), pos, hdr);
                    }

                    T obj = _builder == null ? TypeCaster <T> .Cast(portObj) : TypeCaster <T> .Cast(_builder.Child(portObj));

                    AddHandle(pos, obj);

                    return(obj);
                }
                else
                {
                    // Find descriptor.
                    var desc = _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId);

                    // Instantiate object.
                    if (desc.Type == null)
                    {
                        if (desc is BinarySurrogateTypeDescriptor)
                        {
                            throw new BinaryObjectException("Unknown type ID: " + hdr.TypeId);
                        }

                        throw new BinaryObjectException("No matching type found for object [typeId=" +
                                                        desc.TypeId + ", typeName=" + desc.TypeName + ']');
                    }

                    // Preserve old frame.
                    var  oldHdr       = _curHdr;
                    int  oldPos       = _curPos;
                    var  oldStruct    = _curStruct;
                    bool oldRaw       = _curRaw;
                    var  oldSchema    = _curSchema;
                    var  oldSchemaMap = _curSchemaMap;

                    // Set new frame.
                    _curHdr = hdr;
                    _curPos = pos;
                    SetCurSchema(desc);
                    _curStruct = new BinaryStructureTracker(desc, desc.ReaderTypeStructure);
                    _curRaw    = false;

                    // Read object.
                    Stream.Seek(pos + BinaryObjectHeader.Size, SeekOrigin.Begin);

                    var obj = desc.Serializer.ReadBinary <T>(this, desc.Type, pos);

                    _curStruct.UpdateReaderStructure();

                    // Restore old frame.
                    _curHdr       = oldHdr;
                    _curPos       = oldPos;
                    _curStruct    = oldStruct;
                    _curRaw       = oldRaw;
                    _curSchema    = oldSchema;
                    _curSchemaMap = oldSchemaMap;

                    return(obj);
                }
            }
            finally
            {
                // Advance stream pointer.
                Stream.Seek(pos + hdr.Length, SeekOrigin.Begin);
            }
        }