static public void WriteBlockHeader(TrackingPipeWriter writer, NettraceType type) { /* * [open tag] * [nullreference tag] * [type version] * [minReader Version] * [length of block name] * [block name] * [close tag] */ writer.WriteByte((byte)Tags.BeginPrivateObject); writer.WriteByte((byte)Tags.NullReference); writer.WriteInt(type.Version); writer.WriteInt(type.MinimumReaderVersion); if (type.Name == KnownTypeNames.EventBlock) { writer.WriteInt(KnownTypeNames.EventBlockCompressed.Length); Encoding.UTF8.GetBytes(KnownTypeNames.EventBlockCompressed, writer); } else if (type.Name == KnownTypeNames.StackBlock) { writer.WriteInt(KnownTypeNames.StackBlockCompressed.Length); Encoding.UTF8.GetBytes(KnownTypeNames.StackBlockCompressed, writer); } else { writer.WriteInt(type.Name.Length); Encoding.UTF8.GetBytes(type.Name, writer); } writer.WriteByte((byte)Tags.EndObject); }
private static void WriteBlockHeader(TrackingPipeWriter writer, NettraceType type) { if (compress) { CompressBlockHelper.WriteBlockHeader(writer, type); } else if (decompress) { DecompressBlockHelper.WriteBlockHeader(writer, type); } else { /* * [open tag] * [nullreference tag] * [type version] * [minReader Version] * [length of block name] * [block name] * [close tag] */ writer.WriteByte((byte)Tags.BeginPrivateObject); writer.WriteByte((byte)Tags.NullReference); writer.WriteInt(type.Version); writer.WriteInt(type.MinimumReaderVersion); writer.WriteInt(type.Name.Length); Encoding.UTF8.GetBytes(type.Name, writer); writer.WriteByte((byte)Tags.EndObject); } }
public static ValueTask <FlushResult> ProcessBlock(TrackingPipeWriter writer, NettraceBlock block, CancellationToken token) { // Write opening tag writer.WriteByte((byte)Tags.BeginPrivateObject); WriteBlockHeader(writer, block.Type); var written = compress && CompressBlockHelper.WriteBlockAndPreamble(writer, block); if (!written) { written = decompress && DecompressBlockHelper.WriteBlockAndPreamble(writer, block); } if (!written) { WriteBlockBodyPreamble(writer, block); WriteBlockBody(writer, block.BlockBody); } // Write closing tag writer.WriteByte((byte)Tags.EndObject); return(writer.FlushAsync(token)); }
private static void WriteBlockBody(TrackingPipeWriter writer, ReadOnlySequence <byte> blockSequence) { foreach (var memory in blockSequence) { writer.Write(memory.Span); } }
public static int GetPadding(TrackingPipeWriter writer, NettraceBlock block) { // Get padding size var offset = (writer.WrittenCount + sizeof(int)) % 4; var padding = (int)((4 - offset) % 4); return(padding); }
public static void WriteInitialFileContext(TrackingPipeWriter writer) { // Write Preamble Encoding.UTF8.GetBytes("Nettrace", writer); // Write StreamHeader writer.WriteInt(20); Encoding.UTF8.GetBytes("!FastSerialization.1", writer); }
private static void WriteBlockBodyPreamble(TrackingPipeWriter writer, NettraceBlock block) { if (block.Type.Name == KnownTypeNames.Trace) { return; } // padding should run before writing block size var padding = GetPadding(writer, block); // Write block size writer.WriteInt(block.Size); // Write padding Span <byte> span = stackalloc byte[padding]; writer.Write(span); }
public static bool WriteBlockAndPreamble(TrackingPipeWriter writer, NettraceBlock block) { if (block.Type.Name != KnownTypeNames.EventBlockCompressed && block.Type.Name != KnownTypeNames.StackBlockCompressed) { return(false); } var padding = BlockHelpers.GetPadding(writer, block); var prefixLength = padding + sizeof(int); using var decoder = new BrotliDecoder(); var source = ArrayPool <byte> .Shared.Rent((int)block.BlockBody.Length); block.BlockBody.CopyTo(source); var written = 0; Memory <byte> memory; try { var length = prefixLength + (int)block.BlockBody.Length; memory = writer.GetMemory(length); while (!BrotliDecoder.TryDecompress(source.AsSpan(0, (int)block.BlockBody.Length), memory.Slice(prefixLength).Span, out written)) { length = memory.Length * 2; memory = writer.GetMemory(length); } } finally { ArrayPool <byte> .Shared.Return(source); } // Write size BitConverter.TryWriteBytes(memory.Span, written); // clear padding bits memory.Slice(sizeof(int), padding).Span.Clear(); writer.Advance(written + prefixLength); return(true); }
public static bool WriteBlockAndPreamble(TrackingPipeWriter writer, NettraceBlock block) { if (block.Type.Name != KnownTypeNames.EventBlock && block.Type.Name != KnownTypeNames.StackBlock) { return(false); } var blockSequence = block.BlockBody; var maxLength = BrotliEncoder.GetMaxCompressedLength((int)blockSequence.Length); var padding = BlockHelpers.GetPadding(writer !, block); var prefixLength = padding + sizeof(int); var memory = writer !.GetMemory(maxLength + prefixLength); // clear padding bits memory.Slice(0, prefixLength).Span.Clear(); using var encoder = new BrotliEncoder(quality: 9, window: 10); var slicedMemory = memory.Slice(prefixLength); var totalWritten = 0; OperationStatus status; foreach (var sequence in blockSequence) { status = encoder.Compress(sequence.Span, slicedMemory.Span, out var consumed, out var written, false); Debug.Assert(consumed == sequence.Span.Length); Debug.Assert(status == OperationStatus.Done); slicedMemory = slicedMemory.Slice(written); totalWritten += written; } status = encoder.Compress(ReadOnlySpan <byte> .Empty, slicedMemory.Span, out var _, out var written2, true); Debug.Assert(status == OperationStatus.Done); totalWritten += written2; // Write size BitConverter.TryWriteBytes(memory.Span, totalWritten); writer.Advance(totalWritten + prefixLength); return(true); }