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);
 }
Beispiel #2
0
 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);
     }
 }
Beispiel #3
0
        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));
        }
Beispiel #4
0
 private static void WriteBlockBody(TrackingPipeWriter writer, ReadOnlySequence <byte> blockSequence)
 {
     foreach (var memory in blockSequence)
     {
         writer.Write(memory.Span);
     }
 }
Beispiel #5
0
        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);
        }
Beispiel #6
0
 public static void WriteInitialFileContext(TrackingPipeWriter writer)
 {
     // Write Preamble
     Encoding.UTF8.GetBytes("Nettrace", writer);
     // Write StreamHeader
     writer.WriteInt(20);
     Encoding.UTF8.GetBytes("!FastSerialization.1", writer);
 }
Beispiel #7
0
        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);
        }