Example #1
0
        /** <inheritDoc /> */
        public T ToPortable <T>(object obj)
        {
            if (obj is IPortableObject)
            {
                return((T)obj);
            }

            IPortableStream stream = new PortableHeapStream(1024);

            // Serialize.
            PortableWriterImpl 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, PortableMode.ForcePortable));
        }
Example #2
0
        /// <summary>
        /// Gets field value on the given object.
        /// </summary>
        /// <param name="pos">Position.</param>
        /// <param name="builder">Builder.</param>
        /// <returns>Field value.</returns>
        private T Field0 <T>(int pos, PortableBuilderImpl builder)
        {
            IPortableStream stream = new PortableHeapStream(_data);

            stream.Seek(pos, SeekOrigin.Begin);

            return(_marsh.Unmarshal <T>(stream, PortableMode.ForcePortable, builder));
        }
Example #3
0
        /// <summary>
        /// Process portable object inverting handles if needed.
        /// </summary>
        /// <param name="outStream">Output stream.</param>
        /// <param name="port">Portable.</param>
        internal void ProcessPortable(IPortableStream outStream, PortableUserObject port)
        {
            // Special case: writing portable object with correct inversions.
            PortableHeapStream inStream = new PortableHeapStream(port.Data);

            inStream.Seek(port.Offset, SeekOrigin.Begin);

            // Use fresh context to ensure correct portable inversion.
            Mutate0(new Context(), inStream, outStream, false, 0, EmptyVals);
        }
Example #4
0
        /// <summary>
        /// Lazy fields initialization routine.
        /// </summary>
        private void InitializeFields()
        {
            if (_fields == null)
            {
                IPortableStream stream = new PortableHeapStream(_data);

                stream.Seek(_offset + 14, SeekOrigin.Begin);

                int rawDataOffset = stream.ReadInt();

                _fields = PortableUtils.ObjectFields(stream, _typeId, rawDataOffset);
            }
        }
Example #5
0
        /// <summary>
        /// Process child builder.
        /// </summary>
        /// <param name="outStream">Output stream.</param>
        /// <param name="builder">Builder.</param>
        internal void ProcessBuilder(IPortableStream outStream, PortableBuilderImpl builder)
        {
            PortableHeapStream inStream = new PortableHeapStream(builder._obj.Data);

            inStream.Seek(builder._obj.Offset, SeekOrigin.Begin);

            // Builder parent context might be null only in one case: if we never met this group of
            // builders before. In this case we set context to their parent and track it. Context
            // cleanup will be performed at the very end of build process.
            if (builder._parent._ctx == null || builder._parent._ctx.Closed)
            {
                builder._parent._ctx = new Context(_parent._ctx);
            }

            builder.Mutate(inStream, outStream as PortableHeapStream, builder._desc,
                           builder._hashCode, builder._vals);
        }
Example #6
0
        /// <summary>
        /// Internal deserialization routine.
        /// </summary>
        /// <param name="mode">The mode.</param>
        /// <returns>
        /// Deserialized object.
        /// </returns>
        private T Deserialize <T>(PortableMode mode)
        {
            if (_deserialized == null)
            {
                IPortableStream stream = new PortableHeapStream(_data);

                stream.Seek(_offset, SeekOrigin.Begin);

                T res = _marsh.Unmarshal <T>(stream, mode);

                IPortableTypeDescriptor desc = _marsh.Descriptor(true, _typeId);

                if (!desc.KeepDeserialized)
                {
                    return(res);
                }

                _deserialized = res;
            }

            return((T)_deserialized);
        }
Example #7
0
        /** <inheritDoc /> */
        public IPortableObject Build()
        {
            PortableHeapStream inStream = new PortableHeapStream(_obj.Data);

            inStream.Seek(_obj.Offset, SeekOrigin.Begin);

            // Assume that resulting length will be no less than header + [fields_cnt] * 12;
            int len = PortableUtils.FullHdrLen + (_vals == null ? 0 : _vals.Count * 12);

            PortableHeapStream outStream = new PortableHeapStream(len);

            PortableWriterImpl writer = _portables.Marshaller.StartMarshal(outStream);

            writer.Builder(this);

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

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

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

                // Create portable object once metadata is processed.
                return(new PortableUserObject(_portables.Marshaller, outStream.InternalArray, 0,
                                              _desc.TypeId, _hashCode));
            }
            finally
            {
                // Cleanup.
                _parent._ctx.Closed = true;
            }
        }
Example #8
0
        /** <inheritdoc /> */
        public override bool Equals(object obj)
        {
            if (this == obj)
            {
                return(true);
            }

            PortableUserObject that = obj as PortableUserObject;

            if (that != null)
            {
                if (_data == that._data && _offset == that._offset)
                {
                    return(true);
                }

                // 1. Check hash code and type IDs.
                if (_hashCode == that._hashCode && _typeId == that._typeId)
                {
                    // 2. Check if objects have the same field sets.
                    InitializeFields();
                    that.InitializeFields();

                    if (_fields.Keys.Count != that._fields.Keys.Count)
                    {
                        return(false);
                    }

                    foreach (int id in _fields.Keys)
                    {
                        if (!that._fields.Keys.Contains(id))
                        {
                            return(false);
                        }
                    }

                    // 3. Check if objects have the same field values.
                    foreach (KeyValuePair <int, int> field in _fields)
                    {
                        object fieldVal     = Field0 <object>(field.Value, null);
                        object thatFieldVal = that.Field0 <object>(that._fields[field.Key], null);

                        if (!Equals(fieldVal, thatFieldVal))
                        {
                            return(false);
                        }
                    }

                    // 4. Check if objects have the same raw data.
                    IPortableStream stream = new PortableHeapStream(_data);
                    stream.Seek(_offset + 10, SeekOrigin.Begin);
                    int len       = stream.ReadInt();
                    int rawOffset = stream.ReadInt();

                    IPortableStream thatStream = new PortableHeapStream(that._data);
                    thatStream.Seek(_offset + 10, SeekOrigin.Begin);
                    int thatLen       = thatStream.ReadInt();
                    int thatRawOffset = thatStream.ReadInt();

                    return(PortableUtils.CompareArrays(_data, _offset + rawOffset, len - rawOffset, that._data,
                                                       that._offset + thatRawOffset, thatLen - thatRawOffset));
                }
            }

            return(false);
        }
Example #9
0
        /// <summary>
        /// Transfer bytes from one stream to another.
        /// </summary>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="cnt">Bytes count.</param>
        private static void TransferBytes(PortableHeapStream inStream, IPortableStream outStream, int cnt)
        {
            outStream.Write(inStream.InternalArray, inStream.Position, cnt);

            inStream.Seek(cnt, SeekOrigin.Current);
        }
Example #10
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="hash">New hash.</param>
        /// <param name="vals">Values to be replaced.</param>
        /// <returns>Mutated object.</returns>
        private void Mutate0(Context ctx, PortableHeapStream inStream, IPortableStream outStream,
                             bool changeHash, int hash, IDictionary <int, object> vals)
        {
            int inStartPos  = inStream.Position;
            int outStartPos = outStream.Position;

            byte inHdr = inStream.ReadByte();

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

                int oldPos = inStartPos - inHnd;
                int newPos;

                if (ctx.OldToNew(oldPos, out newPos))
                {
                    // Handle is still valid.
                    outStream.WriteByte(PortableUtils.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, 0, EmptyVals);

                    inStream.Seek(inRetPos, SeekOrigin.Begin);
                }
            }
            else if (inHdr == PortableUtils.HdrFull)
            {
                byte inUsrFlag = inStream.ReadByte();
                int  inTypeId  = inStream.ReadInt();
                int  inHash    = inStream.ReadInt();
                int  inLen     = inStream.ReadInt();
                int  inRawOff  = inStream.ReadInt();

                int hndPos;

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

                    if (_parent._cache != null && _parent._cache.TryGetValue(inStartPos, out cachedVal))
                    {
                        ctx.Writer.Write(cachedVal, null);
                    }
                    else
                    {
                        // New object, write in full form.
                        outStream.WriteByte(PortableUtils.HdrFull);
                        outStream.WriteByte(inUsrFlag);
                        outStream.WriteInt(inTypeId);
                        outStream.WriteInt(changeHash ? hash : inHash);

                        // Skip length and raw offset as they are not known at this point.
                        outStream.Seek(8, SeekOrigin.Current);

                        // Write regular fields.
                        while (inStream.Position < inStartPos + inRawOff)
                        {
                            int inFieldId      = inStream.ReadInt();
                            int inFieldLen     = inStream.ReadInt();
                            int inFieldDataPos = inStream.Position;

                            object fieldVal;

                            bool fieldFound = vals.TryGetValue(inFieldId, out fieldVal);

                            if (!fieldFound || fieldVal != PortableBuilderField.RmvMarkerObj)
                            {
                                outStream.WriteInt(inFieldId);

                                int fieldLenPos = outStream.Position; // Here we will write length later.

                                outStream.Seek(4, SeekOrigin.Current);

                                if (fieldFound)
                                {
                                    // Replace field with new value.
                                    if (fieldVal != PortableBuilderField.RmvMarkerObj)
                                    {
                                        ctx.Writer.Write(fieldVal, null);
                                    }

                                    vals.Remove(inFieldId);
                                }
                                else
                                {
                                    // If field was requested earlier, then we must write tracked value
                                    if (_parent._cache != null && _parent._cache.TryGetValue(inFieldDataPos, out fieldVal))
                                    {
                                        ctx.Writer.Write(fieldVal, null);
                                    }
                                    else
                                    {
                                        // Filed is not tracked, re-write as is.
                                        Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                                    }
                                }

                                int fieldEndPos = outStream.Position;

                                outStream.Seek(fieldLenPos, SeekOrigin.Begin);
                                outStream.WriteInt(fieldEndPos - fieldLenPos - 4);
                                outStream.Seek(fieldEndPos, SeekOrigin.Begin);
                            }

                            // Position intput stream pointer after the field.
                            inStream.Seek(inFieldDataPos + inFieldLen, SeekOrigin.Begin);
                        }

                        // Write remaining new fields.
                        foreach (KeyValuePair <int, object> valEntry in vals)
                        {
                            if (valEntry.Value != PortableBuilderField.RmvMarkerObj)
                            {
                                outStream.WriteInt(valEntry.Key);

                                int fieldLenPos = outStream.Position; // Here we will write length later.

                                outStream.Seek(4, SeekOrigin.Current);

                                ctx.Writer.Write(valEntry.Value, null);

                                int fieldEndPos = outStream.Position;

                                outStream.Seek(fieldLenPos, SeekOrigin.Begin);
                                outStream.WriteInt(fieldEndPos - fieldLenPos - 4);
                                outStream.Seek(fieldEndPos, SeekOrigin.Begin);
                            }
                        }

                        // Write raw data.
                        int rawPos = outStream.Position;

                        outStream.Write(inStream.InternalArray, inStartPos + inRawOff, inLen - inRawOff);

                        // Write length and raw data offset.
                        int outResPos = outStream.Position;

                        outStream.Seek(outStartPos + OffsetLen, SeekOrigin.Begin);

                        outStream.WriteInt(outResPos - outStartPos); // Length.
                        outStream.WriteInt(rawPos - outStartPos);    // Raw offset.

                        outStream.Seek(outResPos, SeekOrigin.Begin);
                    }
                }
                else
                {
                    // Object has already been written, write as handle.
                    outStream.WriteByte(PortableUtils.HdrHnd);
                    outStream.WriteInt(outStartPos - hndPos);
                }

                // Synchronize input stream position.
                inStream.Seek(inStartPos + inLen, 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 + ']');
                }
            }
        }
Example #11
0
        /// <summary>
        /// Mutate portable object.
        /// </summary>
        /// <param name="inStream">Input stream with initial object.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="desc">Portable type descriptor.</param>
        /// <param name="hashCode">Hash code.</param>
        /// <param name="vals">Values.</param>
        internal void Mutate(
            PortableHeapStream inStream,
            PortableHeapStream outStream,
            IPortableTypeDescriptor desc,
            int hashCode,
            IDictionary <string, PortableBuilderField> vals)
        {
            // Set correct builder to writer frame.
            PortableBuilderImpl oldBuilder = _parent._ctx.Writer.Builder(_parent);

            int streamPos = inStream.Position;

            try
            {
                // Prepare fields.
                IPortableMetadataHandler metaHnd = _portables.Marshaller.MetadataHandler(desc);

                IDictionary <int, object> vals0;

                if (vals == null || vals.Count == 0)
                {
                    vals0 = EmptyVals;
                }
                else
                {
                    vals0 = new Dictionary <int, object>(vals.Count);

                    foreach (KeyValuePair <string, PortableBuilderField> valEntry in vals)
                    {
                        int fieldId = PortableUtils.FieldId(desc.TypeId, valEntry.Key, desc.NameConverter, desc.Mapper);

                        if (vals0.ContainsKey(fieldId))
                        {
                            throw new IgniteException("Collision in field ID detected (change field name or " +
                                                      "define custom ID mapper) [fieldName=" + valEntry.Key + ", fieldId=" + fieldId + ']');
                        }

                        vals0[fieldId] = valEntry.Value.Value;

                        // Write metadata if: 1) it is enabled for type; 2) type is not null (i.e. it is neither
                        // remove marker, nor a field read through "GetField" method.
                        if (metaHnd != null && valEntry.Value.Type != null)
                        {
                            metaHnd.OnFieldWrite(fieldId, valEntry.Key, TypeId(valEntry.Value.Type));
                        }
                    }
                }

                // Actual processing.
                Mutate0(_parent._ctx, inStream, outStream, true, hashCode, vals0);

                // 3. Handle metadata.
                if (metaHnd != null)
                {
                    IDictionary <string, int> meta = metaHnd.OnObjectWriteFinished();

                    if (meta != null)
                    {
                        _parent._ctx.Writer.SaveMetadata(desc.TypeId, desc.TypeName, desc.AffinityKeyFieldName, meta);
                    }
                }
            }
            finally
            {
                // Restore builder frame.
                _parent._ctx.Writer.Builder(oldBuilder);

                inStream.Seek(streamPos, SeekOrigin.Begin);
            }
        }