Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenRead flag to aggressively deliver requested bytes #25293

Closed
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
open read loop
  • Loading branch information
jaschrep-msft committed Nov 4, 2021
commit ceb02083b1ed321a14ecb68caebbe101dc2e075f
Original file line number Diff line number Diff line change
@@ -71,6 +71,15 @@ public delegate Task<Response<IDownloadedContent>> DownloadInternalAsync(
/// </summary>
private readonly int _bufferSize;

/// <summary>
/// Whether to ignore internal stream buffer limitations when
/// filling a large, caller-provided buffer on read requests.
/// Instead, the limitations on filling that buffer are only
/// the caller-provided <c>count</c> parameter or hitting
/// end of resource content.
/// </summary>
private readonly bool _fillReadBuffer;

/// <summary>
/// The backing buffer.
/// </summary>
@@ -118,12 +127,14 @@ public LazyLoadingReadOnlyStream(
bool allowModifications,
long initialLenght,
long position = 0,
int? bufferSize = default)
int? bufferSize = default,
bool fillReadBuffer = false)
{
_downloadInternalFunc = downloadInternalFunc;
_getPropertiesInternalFunc = getPropertiesFunc;
_position = position;
_bufferSize = bufferSize ?? Constants.DefaultStreamingDownloadSize;
_fillReadBuffer = fillReadBuffer;
_buffer = ArrayPool<byte>.Shared.Rent(_bufferSize);
_allowBlobModifications = allowModifications;
_bufferPosition = 0;
@@ -186,27 +197,32 @@ public async Task<int> ReadInternal(byte[] buffer, int offset, int count, bool a
}
}

if (_bufferPosition == 0 || _bufferPosition == _bufferLength || _bufferInvalidated)
int bytesRead = 0;
do
{
int lastDownloadedBytes = await DownloadInternal(async, cancellationToken).ConfigureAwait(false);
if (lastDownloadedBytes == 0)
if (_bufferPosition == 0 || _bufferPosition == _bufferLength || _bufferInvalidated)
{
return 0;
int lastDownloadedBytes = await DownloadInternal(async, cancellationToken).ConfigureAwait(false);
if (lastDownloadedBytes == 0)
{
return bytesRead;
}
_bufferInvalidated = false;
}
_bufferInvalidated = false;
}

int remainingBytesInBuffer = _bufferLength - _bufferPosition;
int remainingBytesInBuffer = _bufferLength - _bufferPosition;

// We will return the minimum of remainingBytesInBuffer and the count provided by the user
int bytesToWrite = Math.Min(remainingBytesInBuffer, count);
// write from internal buffer to caller-provided buffer until count is reached or fully consumed internal buffer
int bytesToWrite = Math.Min(remainingBytesInBuffer, count - bytesRead);

Array.Copy(_buffer, _bufferPosition, buffer, offset, bytesToWrite);
Array.Copy(_buffer, _bufferPosition, buffer, offset + bytesRead, bytesToWrite);

_position += bytesToWrite;
_bufferPosition += bytesToWrite;
_position += bytesToWrite;
_bufferPosition += bytesToWrite;
bytesRead += bytesToWrite;
} while (bytesRead < count);

return bytesToWrite;
return bytesRead;
}

private async Task<int> DownloadInternal(bool async, CancellationToken cancellationToken)