internal Task Ensure(int count, bool async, bool dontBreakOnTimeouts) { return(count <= ReadBytesLeft ? PGUtil.CompletedTask : EnsureLong()); async Task EnsureLong() { Debug.Assert(count <= Size); Debug.Assert(count > ReadBytesLeft); count -= ReadBytesLeft; if (count <= 0) { return; } if (ReadPosition == FilledBytes) { Clear(); } else if (count > Size - FilledBytes) { Array.Copy(Buffer, ReadPosition, Buffer, 0, ReadBytesLeft); FilledBytes = ReadBytesLeft; ReadPosition = 0; } try { while (count > 0) { var toRead = Size - FilledBytes; int read; if (async) { if (AwaitableSocket == null) // SSL { read = await Underlying.ReadAsync(Buffer, FilledBytes, toRead); } else // Non-SSL async I/O, optimized { AwaitableSocket.SetBuffer(Buffer, FilledBytes, toRead); await AwaitableSocket.ReceiveAsync(); read = AwaitableSocket.BytesTransferred; } } else // Sync I/O { read = Underlying.Read(Buffer, FilledBytes, toRead); } if (read == 0) { throw new EndOfStreamException(); } count -= read; FilledBytes += read; } } // We have a special case when reading async notifications - a timeout may be normal // shouldn't be fatal // Note that mono throws SocketException with the wrong error (see #1330) catch (IOException e) when( dontBreakOnTimeouts && (e.InnerException as SocketException)?.SocketErrorCode == (Type.GetType("Mono.Runtime") == null ? SocketError.TimedOut : SocketError.WouldBlock) ) { throw new TimeoutException("Timeout while reading from stream"); } catch (Exception e) { Connector.Break(); throw new NpgsqlException("Exception while reading from stream", e); } } }
public async Task Flush(bool async) { if (_copyMode) { // In copy mode, we write CopyData messages. The message code has already been // written to the beginning of the buffer, but we need to go back and write the // length. if (WritePosition == 1) { return; } var pos = WritePosition; WritePosition = 1; WriteInt32(pos - 1); WritePosition = pos; } else if (WritePosition == 0) { return; } try { if (async) { if (AwaitableSocket == null) // SSL { await Underlying.WriteAsync(Buffer, 0, WritePosition); } else // Non-SSL async I/O, optimized { AwaitableSocket.SetBuffer(Buffer, 0, WritePosition); await AwaitableSocket.SendAsync(); } } else // Sync I/O { Underlying.Write(Buffer, 0, WritePosition); } } catch (Exception e) { Connector.Break(); throw new NpgsqlException("Exception while writing to stream", e); } try { if (async) { await Underlying.FlushAsync(); } else { Underlying.Flush(); } } catch (Exception e) { Connector.Break(); throw new NpgsqlException("Exception while flushing stream", e); } NpgsqlEventSource.Log.BytesWritten(WritePosition); //NpgsqlEventSource.Log.RequestFailed(); WritePosition = 0; if (CurrentCommand != null) { CurrentCommand.FlushOccurred = true; CurrentCommand = null; } if (_copyMode) { WriteCopyDataHeader(); } }