Beispiel #1
0
        /** <inheritDoc /> */
        public T ToBinary <T>(object obj)
        {
            if (obj is IBinaryObject)
            {
                return((T)obj);
            }

            using (var 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));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Handles the notification message, if present in the given stream.
        /// </summary>
        private bool HandleNotification(long requestId, BinaryHeapStream stream)
        {
            if (ServerVersion < Ver160)
            {
                return(false);
            }

            var flags = (ClientFlags)stream.ReadShort();

            stream.Seek(-2, SeekOrigin.Current);

            if ((flags & ClientFlags.Notification) != ClientFlags.Notification)
            {
                return(false);
            }

            var count = Interlocked.Decrement(ref _expectedNotifications);

            if (count < 0)
            {
                throw new IgniteClientException("Unexpected thin client notification: " + requestId);
            }

            _notificationListeners.GetOrAdd(requestId, _ => new ClientNotificationHandler(_logger))
            .Handle(stream, null);

            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// Gets the write action by header.
        /// </summary>
        /// <param name="header">The header.</param>
        /// <param name="pos">Position.</param>
        /// <returns>Write action.</returns>
        private Action <BinaryWriter, object> GetWriteAction(byte header, int pos)
        {
            // We need special actions for all cases where SetField(X) produces different result from SetSpecialField(X)
            // Arrays, Collections, Dates

            switch (header)
            {
            case BinaryTypeId.Array:
                return(WriteArrayAction);

            case BinaryTypeId.Collection:
                return(WriteCollectionAction);

            case BinaryTypeId.Timestamp:
                return(WriteTimestampAction);

            case BinaryTypeId.ArrayTimestamp:
                return(WriteTimestampArrayAction);

            case BinaryTypeId.ArrayEnum:
                using (var stream = new BinaryHeapStream(_obj.Data))
                {
                    stream.Seek(pos, SeekOrigin.Begin + 1);

                    var elementTypeId = stream.ReadInt();

                    return((w, o) => w.WriteEnumArrayInternal((Array)o, elementTypeId));
                }

            default:
                return(null);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Internal deserialization routine.
        /// </summary>
        /// <param name="mode">The mode.</param>
        /// <returns>
        /// Deserialized object.
        /// </returns>
        private T Deserialize <T>(BinaryMode mode)
        {
            if (_deserialized == null)
            {
                T res;

                using (IBinaryStream stream = new BinaryHeapStream(_data))
                {
                    stream.Seek(_offset, SeekOrigin.Begin);

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

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

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

                _deserialized = res;
            }

            return((T)_deserialized);
        }
Beispiel #5
0
        /// <summary>
        /// Gets field value on the given object.
        /// </summary>
        /// <param name="pos">Position.</param>
        /// <param name="builder">Builder.</param>
        /// <returns>Field value.</returns>
        public T GetField <T>(int pos, BinaryObjectBuilder builder)
        {
            IBinaryStream stream = new BinaryHeapStream(_data);

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

            return(_marsh.Unmarshal <T>(stream, BinaryMode.ForceBinary, builder));
        }
 /// <summary>
 /// Serializes and deserializes the config.
 /// </summary>
 private static CacheClientConfiguration SerializeDeserialize(CacheClientConfiguration cfg)
 {
     using (var stream = new BinaryHeapStream(128))
     {
         ClientCacheConfigurationSerializer.Write(stream, cfg);
         stream.Seek(0, SeekOrigin.Begin);
         return(new CacheClientConfiguration(stream));
     }
 }
 /// <summary>
 /// Serializes and deserializes the config.
 /// </summary>
 private static CacheClientConfiguration SerializeDeserialize(CacheClientConfiguration cfg)
 {
     using (var stream = new BinaryHeapStream(128))
     {
         ClientCacheConfigurationSerializer.Write(stream, cfg, ClientSocket.CurrentProtocolVersion, true);
         stream.Seek(0, SeekOrigin.Begin);
         return(new CacheClientConfiguration(stream, ClientSocket.CurrentProtocolVersion));
     }
 }
Beispiel #8
0
        /// <summary>
        /// Process binary object inverting handles if needed.
        /// </summary>
        /// <param name="outStream">Output stream.</param>
        /// <param name="port">Binary object.</param>
        internal void ProcessBinary(IBinaryStream outStream, BinaryObject port)
        {
            // Special case: writing binary object with correct inversions.
            BinaryHeapStream inStream = new BinaryHeapStream(port.Data);

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

            // Use fresh context to ensure correct binary inversion.
            Mutate0(new Context(), inStream, outStream, false, 0, EmptyVals);
        }
        /// <summary>
        /// Serializes and deserializes back an instance.
        /// </summary>
        private static IgniteSessionStateStoreData SerializeDeserialize(IgniteSessionStateStoreData data)
        {
            var marsh = BinaryUtils.Marshaller;

            using (var stream = new BinaryHeapStream(128))
            {
                var writer = marsh.StartMarshal(stream);

                data.WriteBinary(writer.GetRawWriter(), false);

                stream.Seek(0, SeekOrigin.Begin);

                return(new IgniteSessionStateStoreData(marsh.StartUnmarshal(stream)));
            }
        }
Beispiel #10
0
        /// <summary>
        /// Serializes and deserializes back an instance.
        /// </summary>
        private static IgniteSessionStateItemCollection SerializeDeserialize(IgniteSessionStateItemCollection data,
                                                                             bool changesOnly = false)
        {
            var marsh = BinaryUtils.Marshaller;

            using (var stream = new BinaryHeapStream(128))
            {
                var writer = marsh.StartMarshal(stream);

                data.WriteBinary(writer.GetRawWriter(), changesOnly);

                stream.Seek(0, SeekOrigin.Begin);

                return(new IgniteSessionStateItemCollection(marsh.StartUnmarshal(stream)));
            }
        }
Beispiel #11
0
        /// <summary>
        /// Process child builder.
        /// </summary>
        /// <param name="outStream">Output stream.</param>
        /// <param name="builder">Builder.</param>
        internal void ProcessBuilder(IBinaryStream outStream, BinaryObjectBuilder builder)
        {
            BinaryHeapStream inStream = new BinaryHeapStream(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 BinaryHeapStream, builder._desc,
                           builder._hashCode, builder._vals);
        }
        private IBinaryRawReader SetUpRawBinaryReader(byte[] hash)
        {
            var marsh = BinaryUtils.Marshaller;

            using (var stream = new BinaryHeapStream(128))
            {
                var writer = marsh.StartMarshal(stream);

                writer.WriteByte(_defaultVersion.Major);
                writer.WriteByte(_defaultVersion.Minor);
                writer.WriteByte(_defaultVersion.Maintenance);
                writer.WriteString(_defaultVersion.Stage);
                writer.WriteLong(BinaryUtils.DateTimeToJavaTicks(_defaultVersion.ReleaseDate));
                writer.WriteByteArray(hash);

                stream.Seek(0, SeekOrigin.Begin);

                return(marsh.StartUnmarshal(stream));
            }
        }
Beispiel #13
0
        public void TestCustomPosition()
        {
            var stream = new BinaryHeapStream(16);

            stream.WriteLong(54);

            var marsh = new Marshaller(new BinaryConfiguration());

            var writer = new BinaryWriter(marsh, stream);

            writer.WriteChar('x');

            stream.Seek(0, SeekOrigin.Begin);

            Assert.AreEqual(54, stream.ReadLong());

            var reader = new BinaryReader(marsh, stream, BinaryMode.Deserialize, null);

            Assert.AreEqual('x', reader.ReadChar());
        }
Beispiel #14
0
        /// <summary>
        /// Handles the notification message, if present in the given stream.
        /// </summary>
        private bool HandleNotification(long requestId, BinaryHeapStream stream)
        {
            if (ServerVersion < Ver160)
            {
                return(false);
            }

            var flags = (ClientFlags)stream.ReadShort();

            stream.Seek(-2, SeekOrigin.Current);

            if ((flags & ClientFlags.Notification) != ClientFlags.Notification)
            {
                return(false);
            }

            _notificationListeners.GetOrAdd(requestId, _ => new ClientNotificationHandler(_logger))
            .Handle(stream, null);

            return(true);
        }
Beispiel #15
0
        /** <inheritDoc /> */
        public IBinaryObject Build()
        {
            BinaryHeapStream inStream = new BinaryHeapStream(_obj.Data);

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

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

            BinaryHeapStream outStream = new BinaryHeapStream(estimatedCapacity);

            BinaryWriter writer = _igniteBinary.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.
                _igniteBinary.Marshaller.FinishMarshal(writer);

                // Create binary object once metadata is processed.
                return(new BinaryObject(_igniteBinary.Marshaller, outStream.InternalArray, 0,
                                        BinaryObjectHeader.Read(outStream, 0)));
            }
            finally
            {
                // Cleanup.
                _parent._ctx.Closed = true;
            }
        }
        public void TestStructure()
        {
            for (int i = 1; i <= RepeatCnt; i++)
            {
                Console.WriteLine(">>> Iteration started: " + i);

                // 1. Generate and shuffle objects.
                IList <BranchedType> objs = new List <BranchedType>();

                for (int j = 0; j < 6 * ObjectsPerMode; j++)
                {
                    objs.Add(new BranchedType((j % 6) + 1));
                }

                objs = IgniteUtils.Shuffle(objs);

                // 2. Create new marshaller.
                BinaryTypeConfiguration typeCfg = new BinaryTypeConfiguration(typeof(BranchedType));

                BinaryConfiguration cfg = new BinaryConfiguration
                {
                    TypeConfigurations = new List <BinaryTypeConfiguration> {
                        typeCfg
                    }
                };

                Marshaller marsh = new Marshaller(cfg);

                // 3. Marshal all data and ensure deserialized object is fine.
                // Use single stream to test object offsets
                using (var stream = new BinaryHeapStream(128))
                {
                    var writer = marsh.StartMarshal(stream);

                    foreach (var obj in objs)
                    {
                        Console.WriteLine(">>> Write object [mode=" + obj.mode + ']');

                        writer.WriteObject(obj);
                    }

                    stream.Seek(0, SeekOrigin.Begin);

                    var reader = marsh.StartUnmarshal(stream);

                    foreach (var obj in objs)
                    {
                        var other = reader.ReadObject <BranchedType>();

                        Assert.IsTrue(obj.Equals(other));
                    }
                }

                Console.WriteLine();

                // 4. Ensure that all fields are recorded.
                var desc = marsh.GetDescriptor(typeof(BranchedType));

                CollectionAssert.AreEquivalent(new[] { "mode", "f2", "f3", "f4", "f5", "f6", "f7", "f8" },
                                               desc.WriterTypeStructure.FieldTypes.Keys);
            }
        }
Beispiel #17
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 + ']');
                }
            }
        }
Beispiel #18
0
        /// <summary>
        /// Mutate binary object.
        /// </summary>
        /// <param name="inStream">Input stream with initial object.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="desc">Type descriptor.</param>
        /// <param name="vals">Values.</param>
        private void Mutate(
            BinaryHeapStream inStream,
            BinaryHeapStream outStream,
            IBinaryTypeDescriptor desc,
            IDictionary <string, BinaryBuilderField> vals)
        {
            // Set correct builder to writer frame.
            BinaryObjectBuilder oldBuilder = _parent._ctx.Writer.SetBuilder(_parent);

            int streamPos = inStream.Position;

            try
            {
                // Prepare fields.
                IBinaryTypeHandler metaHnd = _binary.Marshaller.GetBinaryTypeHandler(desc);

                IDictionary <int, BinaryBuilderField> vals0;

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

                    foreach (KeyValuePair <string, BinaryBuilderField> valEntry in vals)
                    {
                        int fieldId = BinaryUtils.FieldId(desc.TypeId, valEntry.Key, desc.NameMapper, desc.IdMapper);

                        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;

                        // 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, valEntry.Value.TypeId);
                        }
                    }
                }

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

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

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

                inStream.Seek(streamPos, SeekOrigin.Begin);
            }
        }
Beispiel #19
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(BinaryHeapStream inStream, IBinaryStream outStream, int cnt)
        {
            outStream.Write(inStream.InternalArray, inStream.Position, cnt);

            inStream.Seek(cnt, SeekOrigin.Current);
        }