/// <summary> /// ToString implementation. /// </summary> /// <param name="handled">Already handled objects.</param> /// <returns>Object string.</returns> private string ToString(IDictionary <int, int> handled) { int idHash; bool alreadyHandled = handled.TryGetValue(_offset, out idHash); if (!alreadyHandled) { idHash = RuntimeHelpers.GetHashCode(this); } StringBuilder sb; IBinaryTypeDescriptor desc = _marsh.GetDescriptor(true, _header.TypeId); IBinaryType meta; try { meta = _marsh.GetBinaryType(_header.TypeId); } catch (IgniteException) { meta = null; } if (meta == null) { sb = new StringBuilder("BinaryObject [typeId=").Append(_header.TypeId).Append(", idHash=" + idHash); } else { sb = new StringBuilder(meta.TypeName).Append(" [idHash=" + idHash); if (!alreadyHandled) { handled[_offset] = idHash; InitializeFields(); foreach (string fieldName in meta.Fields) { sb.Append(", "); int fieldId = BinaryUtils.FieldId(_header.TypeId, fieldName, desc.NameMapper, desc.IdMapper); int fieldPos; if (_fields.TryGetValue(fieldId, out fieldPos)) { sb.Append(fieldName).Append('='); ToString0(sb, GetField <object>(fieldPos, null), handled); } } } else { sb.Append(", ..."); } } sb.Append(']'); return(sb.ToString()); }
/** <inheritdoc /> */ public ICollection ReadCollection(Func <int, ICollection> factory, Action <ICollection, object> adder) { return(Read(r => BinaryUtils.ReadCollection(r, factory, adder), BinaryUtils.TypeCollection)); }
/** <inheritdoc /> */ public IDictionary ReadDictionary(Func <int, IDictionary> factory) { return(Read(r => BinaryUtils.ReadDictionary(r, factory), BinaryUtils.TypeDictionary)); }
/** <inheritdoc /> */ public Guid?[] ReadGuidArray() { return(Read(r => BinaryUtils.ReadArray <Guid?>(r, false), BinaryUtils.TypeArrayGuid)); }
/** <inheritdoc /> */ public T[] ReadArray <T>() { return(Read(r => BinaryUtils.ReadArray <T>(r, true), BinaryUtils.TypeArray)); }
/// <summary> /// Generate a bundle, given the specification of embedded files /// </summary> /// <param name="fileSpecs"> /// An enumeration FileSpecs for the files to be embedded. /// /// Files in fileSpecs that are not bundled within the single file bundle, /// and should be published as separate files are marked as "IsExcluded" by this method. /// This doesn't include unbundled files that should be dropped, and not publised as output. /// </param> /// <returns> /// The full path the the generated bundle file /// </returns> /// <exceptions> /// ArgumentException if input is invalid /// IOExceptions and ArgumentExceptions from callees flow to the caller. /// </exceptions> public string GenerateBundle(IReadOnlyList <FileSpec> fileSpecs) { Tracer.Log($"Bundler Version: {BundlerMajorVersion}.{BundlerMinorVersion}"); Tracer.Log($"Bundle Version: {BundleManifest.BundleVersion}"); Tracer.Log($"Target Runtime: {Target}"); Tracer.Log($"Bundler Options: {Options}"); if (fileSpecs.Any(x => !x.IsValid())) { throw new ArgumentException("Invalid input specification: Found entry with empty source-path or bundle-relative-path."); } string hostSource; try { hostSource = fileSpecs.Where(x => x.BundleRelativePath.Equals(HostName)).Single().SourcePath; } catch (InvalidOperationException) { throw new ArgumentException("Invalid input specification: Must specify the host binary"); } var bundleRelativePathCollision = fileSpecs.GroupBy(file => file.BundleRelativePath).FirstOrDefault(g => g.Count() > 1); if (bundleRelativePathCollision != null) { string fileSpecPaths = string.Join(", ", bundleRelativePathCollision.Select(file => "'" + file.SourcePath + "'")); throw new ArgumentException($"Invalid input specification: Found entries {fileSpecPaths} with the same BundleRelativePath '{bundleRelativePathCollision.Key}'"); } string bundlePath = Path.Combine(OutputDir, HostName); if (File.Exists(bundlePath)) { Tracer.Log($"Ovewriting existing File {bundlePath}"); } BinaryUtils.CopyFile(hostSource, bundlePath); long headerOffset = 0; using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(bundlePath))) { Stream bundle = writer.BaseStream; bundle.Position = bundle.Length; foreach (var fileSpec in fileSpecs) { string relativePath = fileSpec.BundleRelativePath; if (IsHost(relativePath)) { continue; } if (ShouldIgnore(relativePath)) { Tracer.Log($"Ignore: {relativePath}"); continue; } FileType type = InferType(fileSpec); if (ShouldExclude(type, relativePath)) { Tracer.Log($"Exclude [{type}]: {relativePath}"); fileSpec.Excluded = true; continue; } using (FileStream file = File.OpenRead(fileSpec.SourcePath)) { FileType targetType = Target.TargetSpecificFileType(type); (long startOffset, long compressedSize) = AddToBundle(bundle, file, targetType); FileEntry entry = BundleManifest.AddEntry(targetType, relativePath, startOffset, file.Length, compressedSize, Target.BundleMajorVersion); Tracer.Log($"Embed: {entry}"); } } // Write the bundle manifest headerOffset = BundleManifest.Write(writer); Tracer.Log($"Header Offset={headerOffset}"); Tracer.Log($"Meta-data Size={writer.BaseStream.Position - headerOffset}"); Tracer.Log($"Bundle: Path={bundlePath}, Size={bundle.Length}"); } HostWriter.SetAsBundle(bundlePath, headerOffset); return(bundlePath); }
/** <inheritdoc /> */ public string[] ReadStringArray() { return(Read(r => BinaryUtils.ReadArray <string>(r, false), BinaryUtils.TypeArrayString)); }
/// <summary> /// Generate a bundle, given the specification of embedded files /// </summary> /// <param name="fileSpecs"> /// An enumeration FileSpecs for the files to be embedded. /// </param> /// <returns> /// The full path the the generated bundle file /// </returns> /// <exceptions> /// ArgumentException if input is invalid /// IOExceptions and ArgumentExceptions from callees flow to the caller. /// </exceptions> public string GenerateBundle(IReadOnlyList <FileSpec> fileSpecs) { trace.Log($"Bundler version {Version}"); if (fileSpecs.Any(x => !x.IsValid())) { throw new ArgumentException("Invalid input specification: Found entry with empty source-path or bundle-relative-path."); } string hostSource; try { hostSource = fileSpecs.Where(x => x.BundleRelativePath.Equals(HostName)).Single().SourcePath; } catch (InvalidOperationException) { throw new ArgumentException("Invalid input specification: Must specify the host binary"); } if (fileSpecs.GroupBy(file => file.BundleRelativePath).Where(g => g.Count() > 1).Any()) { throw new ArgumentException("Invalid input specification: Found multiple entries with the same BundleRelativePath"); } string bundlePath = Path.Combine(OutputDir, HostName); if (File.Exists(bundlePath)) { trace.Log($"Ovewriting existing File {bundlePath}"); } BinaryUtils.CopyFile(hostSource, bundlePath); long headerOffset = 0; using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(bundlePath))) { Stream bundle = writer.BaseStream; bundle.Position = bundle.Length; // Write the files from the specification into the bundle foreach (var fileSpec in fileSpecs) { if (!ShouldEmbed(fileSpec.BundleRelativePath)) { trace.Log($"Skip: {fileSpec.BundleRelativePath}"); continue; } using (FileStream file = File.OpenRead(fileSpec.SourcePath)) { FileType type = InferType(fileSpec.BundleRelativePath, file); long startOffset = AddToBundle(bundle, file, type); FileEntry entry = BundleManifest.AddEntry(type, fileSpec.BundleRelativePath, startOffset, file.Length); trace.Log($"Embed: {entry}"); } } // Write the bundle manifest headerOffset = BundleManifest.Write(writer); trace.Log($"Header Offset={headerOffset}"); trace.Log($"Meta-data Size={writer.BaseStream.Position - headerOffset}"); trace.Log($"Bundle: Path={bundlePath}, Size={bundle.Length}"); } HostWriter.SetAsBundle(bundlePath, headerOffset); return(bundlePath); }
/** <inheritdoc /> */ public Guid?ReadGuid(string fieldName) { return(ReadField <Guid?>(fieldName, r => BinaryUtils.ReadGuid(r), BinaryTypeId.Guid)); }
private long FutureDoubleResult(long futPtr, long res, long unused, void *arg) { return(ProcessFuture <double>(futPtr, fut => { fut.OnResult(BinaryUtils.LongToDoubleBits(res)); })); }
public Msg_0x0301(LogLevel logLevel, string msg, string destClientName = "") : base(P2PCommandType.Msg0x0301) { BinaryUtils.Write(Data, logLevel); BinaryUtils.Write(Data, msg); BinaryUtils.Write(Data, destClientName); }
private long FutureFloatResult(long futPtr, long res, long unused, void *arg) { return(ProcessFuture <float>(futPtr, fut => { fut.OnResult(BinaryUtils.IntToFloatBits((int)res)); })); }
/// <summary> /// Write primitive type. /// </summary> /// <param name="val">Object.</param> /// <param name="type">Type.</param> private unsafe void WritePrimitive <T>(T val, Type type) { // .Net defines 14 primitive types. We support 12 - excluding IntPtr and UIntPtr. // Types check sequence is designed to minimize comparisons for the most frequent types. if (type == typeof(int)) { WriteIntField(TypeCaster <int> .Cast(val)); } else if (type == typeof(long)) { WriteLongField(TypeCaster <long> .Cast(val)); } else if (type == typeof(bool)) { WriteBooleanField(TypeCaster <bool> .Cast(val)); } else if (type == typeof(byte)) { WriteByteField(TypeCaster <byte> .Cast(val)); } else if (type == typeof(short)) { WriteShortField(TypeCaster <short> .Cast(val)); } else if (type == typeof(char)) { WriteCharField(TypeCaster <char> .Cast(val)); } else if (type == typeof(float)) { WriteFloatField(TypeCaster <float> .Cast(val)); } else if (type == typeof(double)) { WriteDoubleField(TypeCaster <double> .Cast(val)); } else if (type == typeof(sbyte)) { var val0 = TypeCaster <sbyte> .Cast(val); WriteByteField(*(byte *)&val0); } else if (type == typeof(ushort)) { var val0 = TypeCaster <ushort> .Cast(val); WriteShortField(*(short *)&val0); } else if (type == typeof(uint)) { var val0 = TypeCaster <uint> .Cast(val); WriteIntField(*(int *)&val0); } else if (type == typeof(ulong)) { var val0 = TypeCaster <ulong> .Cast(val); WriteLongField(*(long *)&val0); } else { throw BinaryUtils.GetUnsupportedTypeException(type, val); } }
/// <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 enums. if (type.IsEnum) { WriteEnum(obj); return; } // Handle special case for builder. if (WriteBuilderSpecials(obj)) { return; } // Suppose that we faced normal object and perform descriptor lookup. IBinaryTypeDescriptor desc = _marsh.GetDescriptor(type); if (desc != null) { // 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); // 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); var dataEnd = _stream.Position; // Write schema var schemaOffset = dataEnd - pos; int schemaId; var flags = desc.UserType ? BinaryObjectHeader.Flag.UserType : BinaryObjectHeader.Flag.None; 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 (_curRawPos > 0) { _stream.WriteInt(_curRawPos - 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 = BinaryObjectHeader.Size; } if (_curRawPos > 0) { flags |= BinaryObjectHeader.Flag.HasRaw; } var len = _stream.Position - pos; var hashCode = desc.EqualityComparer != null ? desc.EqualityComparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size, dataEnd - pos - BinaryObjectHeader.Size, _schema, schemaIdx, _marsh, desc) : obj.GetHashCode(); var header = new BinaryObjectHeader(desc.TypeId, 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. _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 BinaryUtils.GetUnsupportedTypeException(type, obj); } if (handler.SupportsHandles && WriteHandle(_stream.Position, obj)) { return; } handler.Write(this, obj); } }
/// <summary> /// Write object as a predefined type if possible. /// </summary> /// <param name="hdr">Header.</param> /// <param name="inStream">Input stream.</param> /// <param name="outStream">Output stream.</param> /// <param name="ctx">Context.</param> /// <returns><c>True</c> if was written.</returns> private bool WriteAsPredefined(byte hdr, BinaryHeapStream inStream, IBinaryStream outStream, Context ctx) { switch (hdr) { case BinaryUtils.TypeByte: TransferBytes(inStream, outStream, 1); break; case BinaryUtils.TypeShort: TransferBytes(inStream, outStream, 2); break; case BinaryUtils.TypeInt: TransferBytes(inStream, outStream, 4); break; case BinaryUtils.TypeLong: TransferBytes(inStream, outStream, 8); break; case BinaryUtils.TypeFloat: TransferBytes(inStream, outStream, 4); break; case BinaryUtils.TypeDouble: TransferBytes(inStream, outStream, 8); break; case BinaryUtils.TypeChar: TransferBytes(inStream, outStream, 2); break; case BinaryUtils.TypeBool: TransferBytes(inStream, outStream, 1); break; case BinaryUtils.TypeDecimal: TransferBytes(inStream, outStream, 4); // Transfer scale int magLen = inStream.ReadInt(); // Transfer magnitude length. outStream.WriteInt(magLen); TransferBytes(inStream, outStream, magLen); // Transfer magnitude. break; case BinaryUtils.TypeString: BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream); break; case BinaryUtils.TypeGuid: TransferBytes(inStream, outStream, 16); break; case BinaryUtils.TypeTimestamp: TransferBytes(inStream, outStream, 12); break; case BinaryUtils.TypeArrayByte: TransferArray(inStream, outStream, 1); break; case BinaryUtils.TypeArrayShort: TransferArray(inStream, outStream, 2); break; case BinaryUtils.TypeArrayInt: TransferArray(inStream, outStream, 4); break; case BinaryUtils.TypeArrayLong: TransferArray(inStream, outStream, 8); break; case BinaryUtils.TypeArrayFloat: TransferArray(inStream, outStream, 4); break; case BinaryUtils.TypeArrayDouble: TransferArray(inStream, outStream, 8); break; case BinaryUtils.TypeArrayChar: TransferArray(inStream, outStream, 2); break; case BinaryUtils.TypeArrayBool: TransferArray(inStream, outStream, 1); break; case BinaryUtils.TypeArrayDecimal: case BinaryUtils.TypeArrayString: case BinaryUtils.TypeArrayGuid: case BinaryUtils.TypeArrayTimestamp: case BinaryUtils.TypeArrayEnum: case BinaryUtils.TypeArray: int arrLen = inStream.ReadInt(); outStream.WriteInt(arrLen); for (int i = 0; i < arrLen; i++) { Mutate0(ctx, inStream, outStream, false, 0, null); } break; case BinaryUtils.TypeCollection: int colLen = inStream.ReadInt(); outStream.WriteInt(colLen); outStream.WriteByte(inStream.ReadByte()); for (int i = 0; i < colLen; i++) { Mutate0(ctx, inStream, outStream, false, 0, EmptyVals); } break; case BinaryUtils.TypeDictionary: int dictLen = inStream.ReadInt(); outStream.WriteInt(dictLen); outStream.WriteByte(inStream.ReadByte()); for (int i = 0; i < dictLen; i++) { Mutate0(ctx, inStream, outStream, false, 0, EmptyVals); Mutate0(ctx, inStream, outStream, false, 0, EmptyVals); } break; case BinaryUtils.TypeBinary: TransferArray(inStream, outStream, 1); // Data array. TransferBytes(inStream, outStream, 4); // Offset in array. break; case BinaryUtils.TypeEnum: TransferBytes(inStream, outStream, 4); // Integer ordinal. break; default: return(false); } return(true); }
/** <inheritdoc /> */ public Guid?ReadGuid() { return(Read <Guid?>(r => BinaryUtils.ReadGuid(r), BinaryTypeId.Guid)); }
public static SC3String FromHexString(string hexString, SC3Game game) { var bytes = BinaryUtils.HexStrToBytes(hexString); return(FromBytes(bytes, game)); }
/** <inheritdoc /> */ public T[] ReadEnumArray <T>(string fieldName) { return(ReadField(fieldName, r => BinaryUtils.ReadArray <T>(r, true), BinaryTypeId.ArrayEnum)); }
/** <inheritdoc /> */ public string[] ReadStringArray(string fieldName) { return(ReadField(fieldName, r => BinaryUtils.ReadArray <string>(r, false), BinaryUtils.TypeArrayString)); }
/** <inheritdoc /> */ public T[] ReadEnumArray <T>() { return(Read(r => BinaryUtils.ReadArray <T>(r, true), BinaryTypeId.ArrayEnum)); }
/** <inheritdoc /> */ public Guid?[] ReadGuidArray(string fieldName) { return(ReadField(fieldName, r => BinaryUtils.ReadArray <Guid?>(r, false), BinaryUtils.TypeArrayGuid)); }
private T ReadFullObject <T>(int pos, Type typeOverride) { 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.CanGetArray) { 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 == BinaryTypeId.Unregistered ? _marsh.GetDescriptor(ReadUnregisteredType(typeOverride)) : _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId, true, null, typeOverride); if (desc == null) { throw new BinaryObjectException(string.Format( "No matching type found for object [typeId={0}, userType={1}].", hdr.TypeId, hdr.IsUserType)); } if (desc.Type == null) { 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. " + "Alternatively, set IgniteConfiguration.PeerAssemblyLoadingMode to CurrentAppDomain.", 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, typeOverride); _frame.Struct.UpdateReaderStructure(); // Restore old frame. _frame = oldFrame; return(obj); } } finally { // Advance stream pointer. Stream.Seek(pos + hdr.Length, SeekOrigin.Begin); } }
/** <inheritdoc /> */ public T[] ReadArray <T>(string fieldName) { return(ReadField(fieldName, r => BinaryUtils.ReadArray <T>(r, true), BinaryUtils.TypeArray)); }
/** <inheritDoc /> */ public void DestroyCache(string name) { IgniteArgumentCheck.NotNull(name, "name"); DoOutOp(ClientOp.CacheDestroy, ctx => ctx.Stream.WriteInt(BinaryUtils.GetCacheId(name))); }
/** <inheritdoc /> */ public ICollection ReadCollection(string fieldName, Func <int, ICollection> factory, Action <ICollection, object> adder) { return(ReadField(fieldName, r => BinaryUtils.ReadCollection(r, factory, adder), BinaryUtils.TypeCollection)); }
/// <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="hashCode">Hash code.</param> /// <param name="vals">Values.</param> private void Mutate( BinaryHeapStream inStream, BinaryHeapStream outStream, IBinaryTypeDescriptor desc, int?hashCode, 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, hashCode, vals0); // 3. Handle metadata. if (metaHnd != null) { IDictionary <string, int> 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); } }
/** <inheritdoc /> */ public IDictionary ReadDictionary(string fieldName, Func <int, IDictionary> factory) { return(ReadField(fieldName, r => BinaryUtils.ReadDictionary(r, factory), BinaryUtils.TypeDictionary)); }
/// <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, BinaryHeapStream inStream, IBinaryStream outStream, bool changeHash, int?hash, 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, 0, 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); 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, 0, 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; // 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) { if (hash != null) { outHash = hash.Value; } else { // Get from identity resolver. outHash = _desc.EqualityComparer != null ? _desc.EqualityComparer.GetHashCode(outStream, outStartPos + BinaryObjectHeader.Size, schemaPos - outStartPos - BinaryObjectHeader.Size, outSchema, outSchemaId, _binary.Marshaller, _desc) : 0; } } 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. 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; _curSchema = desc.Schema.Get(hdr.SchemaId); if (_curSchema == null) { _curSchema = ReadSchema(); desc.Schema.Add(hdr.SchemaId, _curSchema); } _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); } }
/// <summary> /// Gets the Ignite-specific hash code for the provided value. /// </summary> public static unsafe int GetHashCode <T>(T val, Marshaller marsh, IDictionary <int, int> affinityKeyFieldIds) { Debug.Assert(marsh != null); Debug.Assert(val != null); var type = val.GetType(); if (type == typeof(int)) { return(TypeCaster <int> .Cast(val)); } if (type == typeof(long)) { return(GetLongHashCode(TypeCaster <long> .Cast(val))); } if (type == typeof(string)) { return(BinaryUtils.GetStringHashCode((string)(object)val)); } if (type == typeof(Guid)) { return(GetGuidHashCode(TypeCaster <Guid> .Cast(val))); } if (type == typeof(uint)) { var val0 = TypeCaster <uint> .Cast(val); return(*(int *)&val0); } if (type == typeof(ulong)) { var val0 = TypeCaster <ulong> .Cast(val); return(GetLongHashCode(*(long *)&val0)); } if (type == typeof(bool)) { return(TypeCaster <bool> .Cast(val) ? 1231 : 1237); } if (type == typeof(byte)) { return(unchecked ((sbyte)TypeCaster <byte> .Cast(val))); } if (type == typeof(short)) { return(TypeCaster <short> .Cast(val)); } if (type == typeof(char)) { return(TypeCaster <char> .Cast(val)); } if (type == typeof(float)) { var floatVal = TypeCaster <float> .Cast(val); return(*(int *)&floatVal); } if (type == typeof(double)) { var doubleVal = TypeCaster <double> .Cast(val); return(GetLongHashCode(*(long *)&doubleVal)); } if (type == typeof(sbyte)) { return(TypeCaster <sbyte> .Cast(val)); } if (type == typeof(ushort)) { var val0 = TypeCaster <ushort> .Cast(val); return(*(short *)&val0); } if (type == typeof(IntPtr)) { var val0 = TypeCaster <IntPtr> .Cast(val).ToInt64(); return(GetLongHashCode(val0)); } if (type == typeof(UIntPtr)) { var val0 = TypeCaster <UIntPtr> .Cast(val).ToUInt64(); return(GetLongHashCode(*(long *)&val0)); } if (type.IsArray) { return(GetArrayHashCode(val, marsh, affinityKeyFieldIds)); } if (type == typeof(BinaryObject)) { return(val.GetHashCode()); } // DateTime, when used as key, is always written as BinaryObject. return(GetComplexTypeHashCode(val, marsh, affinityKeyFieldIds)); }