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