/// <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(); }
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(); }
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(); }
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(); }
/// <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(); } }
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 }
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(); }
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(); }
/// <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(); }
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; }
/// <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(); }
/// <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(); }
public async Task CompleteAsyncAlwaysCallsDisposeAsync() { var stream = new CountsDisposesStream(); PipeWriter writer = PipeWriter.Create(stream); await writer.CompleteAsync(); Assert.True(stream.DisposeAsyncCalled); }
private async Task WriteDataAsync(PipeWriter writer, ReadOnlyMemory <byte> data) { await writer.WriteAsync(data); await writer.FlushAsync(); await writer.CompleteAsync(); }
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(); } }
public async Task ReceiveAsync(CancellationToken cancellationToken) { while (!_connection.Closed && !cancellationToken.IsCancellationRequested) { await _connection.ReceiveAsync(_writer, cancellationToken); await WriteMessageDelimiterAsync(cancellationToken); } await _writer.CompleteAsync(); }
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(); }
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(); }
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(); }
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); } }
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; } } }
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); }
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 }
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(); }
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(); }
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(); }
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); }
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); }