/** <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)); } }
/// <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); }
/// <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); } }
/// <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); }
/// <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)); } }
/// <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))); } }
/// <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))); } }
/// <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)); } }
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()); }
/// <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); }
/** <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); } }
/// <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 + ']'); } } }
/// <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); } }
/// <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); }