/// <summary>
        /// Forwards all bytes coming from a <see cref="PipeReader"/> to the specified <see cref="PipeWriter"/>.
        /// </summary>
        /// <param name="reader">The reader to get bytes from.</param>
        /// <param name="writer">The writer to copy bytes to.</param>
        /// <param name="propagateSuccessfulCompletion"><c>true</c> to complete the <paramref name="writer"/> when <paramref name="reader"/> completes.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <returns>
        /// A <see cref="Task"/> that completes when the <paramref name="reader"/> has finished producing bytes, or an error occurs.
        /// This <see cref="Task"/> never faults, since any exceptions are used to complete the <paramref name="writer"/>.
        /// </returns>
        /// <remarks>
        /// If an error occurs during reading or writing, the <paramref name="writer"/> is completed with the exception.
        /// </remarks>
        internal static Task LinkToAsync(this PipeReader reader, PipeWriter writer, bool propagateSuccessfulCompletion, CancellationToken cancellationToken = default)
        {
            Requires.NotNull(reader, nameof(reader));
            Requires.NotNull(writer, nameof(writer));

            return(Task.Run(async delegate
            {
                try
                {
                    while (!cancellationToken.IsCancellationRequested)
                    {
                        var result = await reader.ReadAsync(cancellationToken).ConfigureAwait(false);
                        writer.Write(result.Buffer);
                        reader.AdvanceTo(result.Buffer.End);
                        result.ScrubAfterAdvanceTo();
                        await writer.FlushAsync(cancellationToken).ConfigureAwait(false);
                        if (result.IsCompleted)
                        {
                            if (propagateSuccessfulCompletion)
                            {
                                await writer.CompleteAsync().ConfigureAwait(false);
                            }

                            break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    await writer.CompleteAsync(ex).ConfigureAwait(false);
                }
            }));
        }
        public async Task StopAsync()
        {
            _channel.Writer.TryComplete();
            await _pipeWriter.CompleteAsync().ConfigureAwait(false);

            _disposable.Dispose();
        }
Пример #3
0
        public async Task FillPipeAsync(Stream sourceStream, PipeWriter writer, CancellationToken cancellationToken)
        {
            await using var statsStream = new BufferCopyStream(sourceStream);
            await using var gzipStream  = new GZipStream(statsStream, CompressionMode.Decompress);
            try
            {
                int         read;
                FlushResult flushed;
                do
                {
                    var memory = writer.GetMemory(Config.MinimumBufferSize);
                    read = await gzipStream.ReadAsync(memory, cancellationToken);

                    writer.Advance(read);
                    SourcePosition = statsStream.Position;
                    flushed        = await writer.FlushAsync(cancellationToken).ConfigureAwait(false);
                } while (read > 0 && !(flushed.IsCompleted || flushed.IsCanceled || cancellationToken.IsCancellationRequested));

                var buf = statsStream.GetBufferedBytes();
                if (buf.Length > 3)
                {
                    LogSize = BitConverter.ToInt32(buf.AsSpan(buf.Length - 4, 4));
                }
            }
            catch (Exception e)
            {
                Config.Log.Error(e, "Error filling the log pipe");
                await writer.CompleteAsync(e);

                return;
            }
            await writer.CompleteAsync();
        }
Пример #4
0
        private async Task FillBuffer(PipeWriter writer, CancellationToken cancellationToken)
        {
            long offset = 0;

            try
            {
                while (offset < fileEntry.Size)
                {
                    var pipeBuffer = writer.GetMemory(maxMessageSize);

                    try
                    {
                        using var readSegmentCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                        readSegmentCts.CancelAfter(segmentFetchTimeout);

                        var length = (int)Math.Min(maxMessageSize, fileEntry.Size - offset);
                        var base64 = await jsRunner.ReadDataAsync(cancellationToken, elementRef, fileEntry.Id, offset, length);

                        var bytes = Convert.FromBase64String(base64);

                        if (bytes is null || bytes.Length != length)
                        {
                            throw new InvalidOperationException(
                                      $"A segment with size {bytes?.Length ?? 0} bytes was received, but {length} bytes were expected.");
                        }

                        bytes.CopyTo(pipeBuffer);
                        writer.Advance(length);
                        offset += length;

                        var result = await writer.FlushAsync(cancellationToken);

                        await Task.WhenAll(
                            fileEdit.UpdateFileWrittenAsync(fileEntry, offset, bytes),
                            fileEdit.UpdateFileProgressAsync(fileEntry, bytes.Length));

                        if (result.IsCompleted)
                        {
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        await writer.CompleteAsync(e);

                        return;
                    }
                }
            }
            finally
            {
                await fileEdit.UpdateFileEndedAsync(fileEntry, offset == fileEntry.Size);
            }

            await writer.CompleteAsync();
        }
Пример #5
0
        private async Task FillBuffer(PipeWriter writer, CancellationToken cancellationToken)
        {
            long offset = 0;

            while (offset < File.Size)
            {
                var pipeBuffer  = writer.GetMemory(_maxSegmentSize);
                var segmentSize = (int)Math.Min(_maxSegmentSize, File.Size - offset);

                try
                {
                    using var readSegmentCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                    readSegmentCts.CancelAfter(_segmentFetchTimeout);

                    var bytes = await _jsRuntime.InvokeAsync <byte[]>(
                        InputFileInterop.ReadFileData,
                        readSegmentCts.Token,
                        _inputFileElement,
                        File.Id,
                        offset,
                        segmentSize);

                    if (bytes is null || bytes.Length != segmentSize)
                    {
                        throw new InvalidOperationException(
                                  $"A segment with size {bytes?.Length ?? 0} bytes was received, but {segmentSize} bytes were expected.");
                    }

                    bytes.CopyTo(pipeBuffer);
                    writer.Advance(segmentSize);
                    offset += segmentSize;

                    var result = await writer.FlushAsync(cancellationToken);

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    await writer.CompleteAsync(e);

                    return;
                }
            }

            await writer.CompleteAsync();
        }
Пример #6
0
        /// <summary>
        /// Processes incoming data from the socket.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task FillPipeAsync(PipeWriter writer, CancellationToken cancellationToken)
        {
            try
            {
                while (cancellationToken.IsCancellationRequested == false)
                {
                    var memory = writer.GetMemory(512);

                    // socket is no longer connected, we're done
                    if (socket.Connected == false)
                    {
                        await writer.CompleteAsync();

                        break;
                    }

                    var bytesRead = await socket.ReceiveAsync(memory, SocketFlags.None, cancellationToken);

                    if (bytesRead == 0)
                    {
                        break;
                    }

                    writer.Advance(bytesRead);

                    // push successfully read data
                    var result = await writer.FlushAsync(cancellationToken);

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // ignore
            }
            catch (Exception e)
            {
                await writer.CompleteAsync(e);

                return;
            }

            // socket is complete for other reasons
            await writer.CompleteAsync();
        }
        private async Task RunReceiveAsync(PipeWriter writer,
                                           CancellationToken cancellationToken = default)
        {
            FlushResult flushResult = default;

            try
            {
                while (!flushResult.IsCompleted)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    ValueWebSocketReceiveResult readResult = default;
                    while (!readResult.EndOfMessage)
                    {
                        var memory = writer.GetMemory();
                        readResult = await _websocket.ReceiveAsync(memory,
                                                                   cancellationToken);

                        writer.Advance(readResult.Count);
                    }

                    flushResult = await writer
                                  .FlushAsync(cancellationToken);
                }
            }
            finally
            {
                await writer.CompleteAsync();
            }
        }
Пример #8
0
        private async Task WriteToPipeAsync(PipeWriter writer)
        {
            while (true)
            {
                var buffer = writer.GetMemory(14);
                try
                {
                    var bytesCount = await channel.ReceiveAsync(buffer);

                    if (bytesCount == 0)
                    {
                        break;
                    }

                    writer.Advance(bytesCount);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"[{nameof(WriteToPipeAsync)}] Exception: {ex.Message}");
                    break;
                }

                var flushResult = await writer.FlushAsync();

                if (flushResult.IsCompleted)
                {
                    break;
                }
            }
            await writer.CompleteAsync();

            //client is disconnected
        }
Пример #9
0
        private async Task FillPipe(PipeWriter writer, Stream stream)
        {
            const int minimalSize = 1024 * 1024;

            while (!_cancellationToken.IsCancellationRequested)
            {
                Memory <byte> buffer = writer.GetMemory(minimalSize);

                int bytesRead = await stream.ReadAsync(buffer, _cancellationToken);

                if (bytesRead == 0)
                {
                    break;
                }

                writer.Advance(bytesRead);

                FlushResult flushResult = await writer.FlushAsync(_cancellationToken);

                if (flushResult.IsCompleted)
                {
                    break;
                }
            }
            await writer.CompleteAsync();
        }
Пример #10
0
        private async Task ProcessLines()
        {
            while (true)
            {
                ReadResult result = await _reader.ReadAsync();

                ReadOnlySequence <byte> buffer = result.Buffer;

                while (TryReadLine(ref buffer, out ReadOnlySequence <byte> line))
                {
                    // Process the line.
                    ProcessLine(line);
                    await _writer.FlushAsync();
                }

                // Tell the PipeReader how much of the buffer has been consumed.
                _reader.AdvanceTo(buffer.Start, buffer.End);

                // Stop reading if there's no more data coming.
                if (result.IsCompleted)
                {
                    break;
                }
            }
            await _reader.CompleteAsync();

            await _writer.CompleteAsync();
        }
Пример #11
0
        /// <summary>
        /// Feeding the pipeline with data taken from socket.
        /// This code is basically from pipeline manual + the cancellation token.
        /// </summary>
        async Task SocketToPipeAsync(PipeWriter writer)
        {
            const int minimumBufferSize = 512;

            while (true)
            {
                Memory <byte> memory = writer.GetMemory(minimumBufferSize);
                try
                {
                    int bytesRead = await lowlevel.ReceiveAsync(memory, SocketFlags.None, farewell.Token);

                    if (bytesRead == 0)
                    {
                        break;
                    }
                    writer.Advance(bytesRead);
                }
                catch (Exception)
                {
                    // Todo: maybe today I'll decide to log something, for the time being I throw everything away.
                    break;
                }

                FlushResult result = await writer.FlushAsync(farewell.Token);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            await writer.CompleteAsync();
        }
Пример #12
0
        private async Task CloseOffCurrentTable()
        {
            var currentLocation = _metaData.BlockCount * FileConsts.PageSize;

            var filterSize = _metaData.Filter.WriteToPipe(_filePipe);

            _metaData.AddTableEntry(currentLocation, filterSize, TableOfContentsEntryType.Filter);
            currentLocation += filterSize;

            var statsSize = _metaData.WriteStats(_filePipe);

            _metaData.AddTableEntry(currentLocation, statsSize, TableOfContentsEntryType.Statistics);
            currentLocation += statsSize;

            var blockOffsetsSize = _metaData.WriteBlockOffsets(_filePipe);

            _metaData.AddTableEntry(currentLocation, blockOffsetsSize, TableOfContentsEntryType.BlockOffsets);

            _metaData.WriteTOC(_filePipe);

            await _filePipe.FlushAsync();

            await _filePipe.CompleteAsync();

            await _fileStream.DisposeAsync();

            if (_loadNewFiles)
            {
                var tf = new TableFile(_fileName, _blockCache);
                _newTableFiles.Add(tf);
                await tf.LoadAsync();
            }
            _lastTableKeyCount = _metaData.Count;
        }
Пример #13
0
        /// <summary>
        /// Fill the pipe with the result.
        /// </summary>
        /// <param name="writer">The pipe writer</param>
        private async Task FillPipeAsync(PipeWriter writer)
        {
            const int minimumBufferSize = 512;

            while (true)
            {
                // Allocate at least 512 bytes from the PipeWriter.
                Memory <byte> memory = writer.GetMemory(minimumBufferSize);
                try {
                    int bytesRead = await _tpsocket.ReceiveAsync(memory);

                    if (bytesRead == 0)
                    {
                        break;
                    }
                    // Tell the PipeWriter how much was read from the Socket.
                    writer.Advance(bytesRead);
                } catch {
                    break;
                }

                // Make the data available to the PipeReader.
                FlushResult result = await writer.FlushAsync();

                if (result.IsCompleted)
                {
                    break;
                }
            }

            // By completing PipeWriter, tell the PipeReader that there's no more data coming.
            await writer.CompleteAsync();
        }
Пример #14
0
        /// <summary>
        /// Processes incoming data from the socket.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task FillPipeAsync(PipeWriter writer, CancellationToken cancellationToken)
        {
            try
            {
                while (cancellationToken.IsCancellationRequested == false)
                {
                    // socket is no longer connected, we're done
                    if (socket.State != WebSocketState.Open)
                    {
                        break;
                    }

                    // receive some data from the web socket
                    var buff = writer.GetMemory(512);
                    var recv = await socket.ReceiveAsync(buff, cancellationToken);

                    writer.Advance(recv.Count);

                    // push successfully read data
                    var result = await writer.FlushAsync(cancellationToken);

                    if (result.IsCompleted)
                    {
                        break;
                    }

                    // received a close message
                    if (recv.MessageType == WebSocketMessageType.Close)
                    {
                        break;
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // ignore
            }
            catch (Exception e)
            {
                await writer.CompleteAsync(e);

                return;
            }

            // socket is complete for other reasons
            await writer.CompleteAsync();
        }
Пример #15
0
        public async Task CompleteAsyncAlwaysCallsDisposeAsync()
        {
            var        stream = new CountsDisposesStream();
            PipeWriter writer = PipeWriter.Create(stream);
            await writer.CompleteAsync();

            Assert.True(stream.DisposeAsyncCalled);
        }
Пример #16
0
        private async Task WriteDataAsync(PipeWriter writer, ReadOnlyMemory <byte> data)
        {
            await writer.WriteAsync(data);

            await writer.FlushAsync();

            await writer.CompleteAsync();
        }
Пример #17
0
    static async Task ProcessMessagesAsync(
        PipeReader reader,
        PipeWriter writer)
    {
        try
        {
            while (true)
            {
                ReadResult readResult = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = readResult.Buffer;

                try
                {
                    if (readResult.IsCanceled)
                    {
                        break;
                    }

                    if (TryParseLines(ref buffer, out string message))
                    {
                        FlushResult flushResult =
                            await WriteMessagesAsync(writer, message);

                        if (flushResult.IsCanceled || flushResult.IsCompleted)
                        {
                            break;
                        }
                    }

                    if (readResult.IsCompleted)
                    {
                        if (!buffer.IsEmpty)
                        {
                            throw new InvalidDataException("Incomplete message.");
                        }
                        break;
                    }
                }
                finally
                {
                    reader.AdvanceTo(buffer.Start, buffer.End);
                }
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
        }
        finally
        {
            await reader.CompleteAsync();

            await writer.CompleteAsync();
        }
    }
Пример #18
0
 public async Task ReceiveAsync(CancellationToken cancellationToken)
 {
     while (!_connection.Closed &&
            !cancellationToken.IsCancellationRequested)
     {
         await _connection.ReceiveAsync(_writer, cancellationToken);
         await WriteMessageDelimiterAsync(cancellationToken);
     }
     await _writer.CompleteAsync();
 }
Пример #19
0
        public async Task FillPipeAsync(Stream sourceStream, PipeWriter writer, CancellationToken cancellationToken)
        {
            try
            {
                using var statsStream = new BufferCopyStream(sourceStream);
                using var zipReader   = ZipReader.Open(statsStream);
                while (zipReader.MoveToNextEntry())
                {
                    if (!zipReader.Entry.IsDirectory &&
                        zipReader.Entry.Key.EndsWith(".log", StringComparison.InvariantCultureIgnoreCase) &&
                        !zipReader.Entry.Key.Contains("tty.log", StringComparison.InvariantCultureIgnoreCase))
                    {
                        LogSize             = zipReader.Entry.Size;
                        using var rarStream = zipReader.OpenEntryStream();
                        int         read;
                        FlushResult flushed;
                        do
                        {
                            var memory = writer.GetMemory(Config.MinimumBufferSize);
                            read = await rarStream.ReadAsync(memory, cancellationToken);

                            writer.Advance(read);
                            SourcePosition = statsStream.Position;
                            flushed        = await writer.FlushAsync(cancellationToken).ConfigureAwait(false);

                            SourcePosition = statsStream.Position;
                        } while (read > 0 && !(flushed.IsCompleted || flushed.IsCanceled || cancellationToken.IsCancellationRequested));
                        await writer.CompleteAsync();

                        return;
                    }
                    SourcePosition = statsStream.Position;
                }
                Config.Log.Warn("No rar entries that match the log criteria");
            }
            catch (Exception e)
            {
                Config.Log.Error(e, "Error filling the log pipe");
            }
            await writer.CompleteAsync();
        }
Пример #20
0
        public async Task FillPipeAsync(Stream sourceStream, PipeWriter writer, CancellationToken cancellationToken)
        {
            try
            {
                await using var fileStream = new FileStream(Path.GetTempFileName(), FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 16384, FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose);
                await sourceStream.CopyToAsync(fileStream, 16384, cancellationToken).ConfigureAwait(false);

                fileStream.Seek(0, SeekOrigin.Begin);
                using var zipArchive = SevenZipArchive.Open(fileStream);
                using var zipReader  = zipArchive.ExtractAllEntries();
                while (zipReader.MoveToNextEntry())
                {
                    if (!zipReader.Entry.IsDirectory &&
                        zipReader.Entry.Key.EndsWith(".log", StringComparison.InvariantCultureIgnoreCase) &&
                        !zipReader.Entry.Key.Contains("tty.log", StringComparison.InvariantCultureIgnoreCase))
                    {
                        LogSize = zipReader.Entry.Size;
                        await using var entryStream = zipReader.OpenEntryStream();
                        int         read;
                        FlushResult flushed;
                        do
                        {
                            var memory = writer.GetMemory(Config.MinimumBufferSize);
                            read = await entryStream.ReadAsync(memory, cancellationToken);

                            writer.Advance(read);
                            flushed = await writer.FlushAsync(cancellationToken).ConfigureAwait(false);
                        } while (read > 0 && !(flushed.IsCompleted || flushed.IsCanceled || cancellationToken.IsCancellationRequested));
                        await writer.CompleteAsync();

                        return;
                    }
                }
                Config.Log.Warn("No 7z entries that match the log criteria");
            }
            catch (Exception e)
            {
                Config.Log.Error(e, "Error filling the log pipe");
            }
            await writer.CompleteAsync();
        }
Пример #21
0
        private async Task CopyDataAsync(List <byte[]> segments, PipeWriter writer, CancellationToken cancellationToken)
        {
            foreach (var segment in segments)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Copy(segment, writer);

                await writer.FlushAsync();
            }
            await writer.CompleteAsync();
        }
Пример #22
0
        private async Task DoReceive()
        {
            Exception error = null;

            try
            {
                await ProcessReceives().ConfigureAwait(false);
            }
            catch (SocketException ex) when(ex.SocketErrorCode == SocketError.ConnectionReset)
            {
                error = new Exception(ex.Message, ex);
                //error = new ConnectionResetException(ex.Message, ex);
            }
            catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted ||
                                            ex.SocketErrorCode == SocketError.ConnectionAborted ||
                                            ex.SocketErrorCode == SocketError.Interrupted ||
                                            ex.SocketErrorCode == SocketError.InvalidArgument)
            {
                if (!_aborted)
                {
                    // Calling Dispose after ReceiveAsync can cause an "InvalidArgument" error on *nix.
                    error = new Exception();
                    //error = new ConnectionAbortedException();
                }
            }
            catch (ObjectDisposedException)
            {
                if (!_aborted)
                {
                    error = new Exception();
                    //error = new ConnectionAbortedException();
                }
            }
            catch (IOException ex)
            {
                error = ex;
            }
            catch (Exception ex)
            {
                error = new IOException(ex.Message, ex);
            }
            finally
            {
                if (_aborted)
                {
                    error ??= new Exception();
                    //error ??= new ConnectionAbortedException();
                }

                await _writer.CompleteAsync(error).ConfigureAwait(false);
            }
        }
Пример #23
0
        public static async Task CompressAsync(PipeReader reader, PipeWriter writer, CancellationToken cancellationToken = default)
        {
            var fse = new FsePipeCompressor(writer);

            while (true)
            {
                ReadResult readResult = await reader.ReadAsync(cancellationToken).ConfigureAwait(false);

                if (readResult.IsCompleted || readResult.IsCanceled)
                {
                    fse.Flush();
                    await writer.FlushAsync(cancellationToken).ConfigureAwait(false);

                    await writer.CompleteAsync().ConfigureAwait(false);

                    return;
                }

                fse.Process(readResult.Buffer, out SequencePosition consumed, out SequencePosition examined);
                reader.AdvanceTo(consumed, examined);

                switch (fse.State)
                {
                case FseCompressorState.WriteOutput:
                    await writer.FlushAsync(cancellationToken).ConfigureAwait(false);

                    fse.NotifyFlushCompleted();
                    break;

                case FseCompressorState.Completed:
                    fse.Complete();
                    await writer.FlushAsync(cancellationToken).ConfigureAwait(false);

                    await writer.CompleteAsync().ConfigureAwait(false);

                    return;
                }
            }
        }
Пример #24
0
        private static async Task FillPipeAsync(PipeWriter writer)
        {
            CborWriter cborWriter = new CborWriter(writer);
            var        document   = new Document {
                Key = "Hello", Value = "World"
            };
            var formatter = new ComplexClassFormatter <Document>();
            await formatter.SerializeAsync(cborWriter, document).ConfigureAwait(false);

            //await cborWriter.WriteMap(input).ConfigureAwait(false);
            await cborWriter.FlushAsync().ConfigureAwait(false);

            await writer.CompleteAsync().ConfigureAwait(false);
        }
Пример #25
0
        public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
        {
#if (NETCOREAPP2_1 || NETCOREAPP2_2)
            return(Cbor.SerializeAsync(context.Object, context.ObjectType, context.HttpContext.Response.Body, _cborOptions));
#else
            PipeWriter writer = context.HttpContext.Response.BodyWriter;
            Cbor.Serialize(context.Object, context.ObjectType, writer, _cborOptions);

            ValueTask <FlushResult> flushTask = writer.FlushAsync();

            if (flushTask.IsCompleted)
            {
                ValueTask completeTask = writer.CompleteAsync();

                if (completeTask.IsCompleted)
                {
                    return(Task.CompletedTask);
                }

                return(FinishCompleteAsync(completeTask));
            }

            return(FinishFlushAsync(flushTask));

            async Task FinishFlushAsync(ValueTask <FlushResult> localFlushTask)
            {
                await localFlushTask.ConfigureAwait(false);

                await writer.CompleteAsync();
            }

            async Task FinishCompleteAsync(ValueTask localCompleteTask)
            {
                await localCompleteTask.ConfigureAwait(false);
            }
#endif
        }
Пример #26
0
        private async Task FillPipeAsync(PipeWriter writer, CancellationToken cancellationToken)
        {
            const int minimumBufferSize = 512;

            while (true)
            {
                // 从PipeWriter至少分配512字节
                var memory = writer.GetMemory(minimumBufferSize);
                try
                {
                    var reads = await Socket.ReceiveAsync(memory, SocketFlags.None, cancellationToken);

                    if (reads == 0)
                    {
                        break;
                    }

                    Actived = DateTimeOffset.Now;
                    // 告诉PipeWriter从套接字读取了多少
                    writer.Advance(reads);
                }
                catch (SocketException exception)
                {
                    LogError("[{2}] 套接字读取出现错误:{1}({0})", exception.Message, exception.SocketErrorCode, Name);
                    if (!Socket.Connected)
                    {
                        await CloseAsync();

                        return;
                    }
                }
                catch (Exception ex)
                {
                    LogError("[{0}] {1}", Name, ex.Message);
                    break;
                }

                // 标记数据可用,让PipeReader读取
                var result = await writer.FlushAsync(cancellationToken);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            // 告诉PipeReader没有更多的数据
            await writer.CompleteAsync();
        }
Пример #27
0
        private async ValueTask StartFillPipe(PipeWriter pipeWriter, CancellationToken cancellationToken)
        {
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();
                int readBytes;
                try
                {
                    readBytes = await _socket.ReceiveAsync(pipeWriter.GetMemory(), SocketFlags.None, cancellationToken);
                }
                catch (SocketException e)
                {
                    await pipeWriter.CompleteAsync(e);

                    return;
                }

                if (readBytes == 0)
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(50), cancellationToken);

                    continue;
                }

                pipeWriter.Advance(readBytes);

                var result = await pipeWriter.FlushAsync(cancellationToken);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            await pipeWriter.CompleteAsync();
        }
Пример #28
0
        public async Task FillPipeAsync(Stream sourceStream, PipeWriter writer, CancellationToken cancellationToken)
        {
            try
            {
                int         read;
                FlushResult flushed;
                do
                {
                    var memory = writer.GetMemory(Config.MinimumBufferSize);
                    read = await sourceStream.ReadAsync(memory, cancellationToken);

                    writer.Advance(read);
                    flushed = await writer.FlushAsync(cancellationToken).ConfigureAwait(false);
                } while (read > 0 && !(flushed.IsCompleted || flushed.IsCanceled || cancellationToken.IsCancellationRequested));
            }
            catch (Exception e)
            {
                Config.Log.Error(e, "Error filling the log pipe");
                await writer.CompleteAsync(e);

                return;
            }
            await writer.CompleteAsync();
        }
Пример #29
0
        public async Task DataNotFlushedOnCompleteAsyncWithException()
        {
            byte[]     bytes  = Encoding.ASCII.GetBytes("Hello World");
            var        stream = new MemoryStream();
            PipeWriter writer = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));

            bytes.AsSpan().CopyTo(writer.GetSpan(bytes.Length));
            writer.Advance(bytes.Length);

            Assert.Equal(0, stream.Length);

            await writer.CompleteAsync(new Exception());

            Assert.Equal(0, stream.Length);
        }
Пример #30
0
        async Task FillPipeAsync(PipeWriter writer, DirectoryInfo directory)
        {
            foreach (var file in directory.GetFiles("WoWCombatLog*.txt", SearchOption.TopDirectoryOnly))
            {
                if (!file.Exists)
                {
                    continue;
                }
                await using var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                await stream.CopyToAsync(writer, token).ConfigureAwait(false);
            }

            await writer.CompleteAsync().ConfigureAwait(false);
        }