diff --git a/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs index 48caf2b23b..27b5978cae 100644 --- a/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs @@ -2,8 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNet.Http; -using Microsoft.AspNet.Http.Internal; +using System.Buffers; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Abstractions; using Microsoft.AspNet.Mvc.ActionConstraints; @@ -18,7 +17,6 @@ using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.AspNet.Mvc.Routing; using Microsoft.AspNet.Routing; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.MemoryPool; using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.PlatformAbstractions; @@ -144,8 +142,8 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); - services.TryAddSingleton, DefaultArraySegmentPool>(); - services.TryAddSingleton, DefaultArraySegmentPool>(); + services.TryAddSingleton(ArrayPool.Shared); + services.TryAddSingleton(ArrayPool.Shared); services.TryAddSingleton(); } diff --git a/src/Microsoft.AspNet.Mvc.Core/HttpResponseStreamWriter.cs b/src/Microsoft.AspNet.Mvc.Core/HttpResponseStreamWriter.cs index 416d3dd2fe..06a9dc6c9b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/HttpResponseStreamWriter.cs +++ b/src/Microsoft.AspNet.Mvc.Core/HttpResponseStreamWriter.cs @@ -2,11 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Buffers; using System.IO; using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Core; -using Microsoft.Extensions.MemoryPool; namespace Microsoft.AspNet.Mvc { @@ -23,13 +23,15 @@ namespace Microsoft.AspNet.Mvc /// public const int DefaultBufferSize = 1024; - private readonly Stream _stream; - private Encoder _encoder; - private LeasedArraySegment _leasedByteBuffer; - private LeasedArraySegment _leasedCharBuffer; - private ArraySegment _byteBuffer; - private ArraySegment _charBuffer; - private int _charBufferSize; + private Stream _stream; + private readonly Encoder _encoder; + private readonly ArrayPool _bytePool; + private readonly ArrayPool _charPool; + private readonly int _charBufferSize; + + private byte[] _byteBuffer; + private char[] _charBuffer; + private int _charBufferCount; public HttpResponseStreamWriter(Stream stream, Encoding encoding) @@ -64,16 +66,16 @@ namespace Microsoft.AspNet.Mvc } _encoder = encoding.GetEncoder(); - _byteBuffer = new ArraySegment(new byte[encoding.GetMaxByteCount(bufferSize)]); - _charBuffer = new ArraySegment(new char[bufferSize]); + _byteBuffer = new byte[encoding.GetMaxByteCount(bufferSize)]; + _charBuffer = new char[bufferSize]; } public HttpResponseStreamWriter( Stream stream, Encoding encoding, int bufferSize, - LeasedArraySegment leasedByteBuffer, - LeasedArraySegment leasedCharBuffer) + ArrayPool bytePool, + ArrayPool charPool) { if (stream == null) { @@ -90,59 +92,71 @@ namespace Microsoft.AspNet.Mvc throw new ArgumentNullException(nameof(encoding)); } - if (leasedByteBuffer == null) + if (bytePool == null) { - throw new ArgumentNullException(nameof(leasedByteBuffer)); + throw new ArgumentNullException(nameof(bytePool)); } - if (leasedCharBuffer == null) + if (charPool == null) { - throw new ArgumentNullException(nameof(leasedCharBuffer)); - } - - if (bufferSize <= 0 || bufferSize > leasedCharBuffer.Data.Count) - { - throw new ArgumentOutOfRangeException(nameof(bufferSize)); - } - - var requiredLength = encoding.GetMaxByteCount(bufferSize); - if (requiredLength > leasedByteBuffer.Data.Count) - { - var message = Resources.FormatHttpResponseStreamWriter_InvalidBufferSize( - requiredLength, - bufferSize, - encoding.EncodingName, - typeof(Encoding).FullName, - nameof(Encoding.GetMaxByteCount)); - throw new ArgumentException(message, nameof(leasedByteBuffer)); + throw new ArgumentNullException(nameof(charPool)); } _stream = stream; Encoding = encoding; _charBufferSize = bufferSize; - _leasedByteBuffer = leasedByteBuffer; - _leasedCharBuffer = leasedCharBuffer; _encoder = encoding.GetEncoder(); - _byteBuffer = leasedByteBuffer.Data; - _charBuffer = leasedCharBuffer.Data; + _bytePool = bytePool; + _charPool = charPool; + + _charBuffer = charPool.Rent(bufferSize); + + try + { + var requiredLength = encoding.GetMaxByteCount(bufferSize); + _byteBuffer = bytePool.Rent(requiredLength); + } + catch + { + charPool.Return(_charBuffer); + _charBuffer = null; + + if (_byteBuffer != null) + { + bytePool.Return(_byteBuffer); + _byteBuffer = null; + } + + throw; + } } public override Encoding Encoding { get; } public override void Write(char value) { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + if (_charBufferCount == _charBufferSize) { FlushInternal(); } - _charBuffer.Array[_charBuffer.Offset + _charBufferCount] = value; + _charBuffer[_charBufferCount] = value; _charBufferCount++; } public override void Write(char[] values, int index, int count) { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + if (values == null) { return; @@ -161,6 +175,11 @@ namespace Microsoft.AspNet.Mvc public override void Write(string value) { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + if (value == null) { return; @@ -181,17 +200,27 @@ namespace Microsoft.AspNet.Mvc public override async Task WriteAsync(char value) { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + if (_charBufferCount == _charBufferSize) { await FlushInternalAsync(); } - _charBuffer.Array[_charBuffer.Offset + _charBufferCount] = value; + _charBuffer[_charBufferCount] = value; _charBufferCount++; } public override async Task WriteAsync(char[] values, int index, int count) { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + if (values == null) { return; @@ -210,6 +239,11 @@ namespace Microsoft.AspNet.Mvc public override async Task WriteAsync(string value) { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + if (value == null) { return; @@ -233,11 +267,21 @@ namespace Microsoft.AspNet.Mvc public override void Flush() { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + FlushInternal(true, true); } public override Task FlushAsync() { + if (_stream == null) + { + throw new ObjectDisposedException("stream"); + } + return FlushInternalAsync(flushStream: true, flushEncoder: true); } @@ -245,7 +289,7 @@ namespace Microsoft.AspNet.Mvc // sent in chunked encoding in case of Helios. protected override void Dispose(bool disposing) { - if (disposing) + if (disposing && _stream != null) { try { @@ -253,14 +297,18 @@ namespace Microsoft.AspNet.Mvc } finally { - if (_leasedByteBuffer != null) + _stream = null; + + if (_bytePool != null) { - _leasedByteBuffer.Owner.Return(_leasedByteBuffer); + _bytePool.Return(_byteBuffer); + _byteBuffer = null; } - if (_leasedCharBuffer != null) + if (_charPool != null) { - _leasedCharBuffer.Owner.Return(_leasedCharBuffer); + _charPool.Return(_charBuffer); + _charBuffer = null; } } } @@ -274,16 +322,16 @@ namespace Microsoft.AspNet.Mvc } var count = _encoder.GetBytes( - _charBuffer.Array, - _charBuffer.Offset, + _charBuffer, + 0, _charBufferCount, - _byteBuffer.Array, - _byteBuffer.Offset, + _byteBuffer, + 0, flushEncoder); if (count > 0) { - _stream.Write(_byteBuffer.Array, _byteBuffer.Offset, count); + _stream.Write(_byteBuffer, 0, count); } _charBufferCount = 0; @@ -302,16 +350,16 @@ namespace Microsoft.AspNet.Mvc } var count = _encoder.GetBytes( - _charBuffer.Array, - _charBuffer.Offset, + _charBuffer, + 0, _charBufferCount, - _byteBuffer.Array, - _byteBuffer.Offset, + _byteBuffer, + 0, flushEncoder); if (count > 0) { - await _stream.WriteAsync(_byteBuffer.Array, _byteBuffer.Offset, count); + await _stream.WriteAsync(_byteBuffer, 0, count); } _charBufferCount = 0; @@ -328,8 +376,8 @@ namespace Microsoft.AspNet.Mvc value.CopyTo( sourceIndex: index, - destination: _charBuffer.Array, - destinationIndex: _charBuffer.Offset + _charBufferCount, + destination: _charBuffer, + destinationIndex: _charBufferCount, count: remaining); _charBufferCount += remaining; @@ -344,8 +392,8 @@ namespace Microsoft.AspNet.Mvc Buffer.BlockCopy( src: values, srcOffset: index * sizeof(char), - dst: _charBuffer.Array, - dstOffset: (_charBuffer.Offset + _charBufferCount) * sizeof(char), + dst: _charBuffer, + dstOffset: _charBufferCount * sizeof(char), count: remaining * sizeof(char)); _charBufferCount += remaining; diff --git a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/HttpRequestStreamReader.cs b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/HttpRequestStreamReader.cs index 2271529780..8923762c40 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/HttpRequestStreamReader.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/HttpRequestStreamReader.cs @@ -2,12 +2,12 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Buffers; using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Core; -using Microsoft.Extensions.MemoryPool; namespace Microsoft.AspNet.Mvc.Infrastructure { @@ -21,12 +21,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure private readonly Encoding _encoding; private readonly Decoder _decoder; - private readonly LeasedArraySegment _leasedByteBuffer; - private readonly LeasedArraySegment _leasedCharBuffer; + private readonly ArrayPool _bytePool; + private readonly ArrayPool _charPool; private readonly int _byteBufferSize; - private readonly ArraySegment _byteBuffer; - private readonly ArraySegment _charBuffer; + private byte[] _byteBuffer; + private char[] _charBuffer; private int _charBufferIndex; private int _charsRead; @@ -66,17 +66,17 @@ namespace Microsoft.AspNet.Mvc.Infrastructure } _byteBufferSize = bufferSize; - _byteBuffer = new ArraySegment(new byte[bufferSize]); + _byteBuffer = new byte[bufferSize]; var maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize); - _charBuffer = new ArraySegment(new char[maxCharsPerBuffer]); + _charBuffer = new char[maxCharsPerBuffer]; } public HttpRequestStreamReader( Stream stream, Encoding encoding, int bufferSize, - LeasedArraySegment leasedByteBuffer, - LeasedArraySegment leasedCharBuffer) + ArrayPool bytePool, + ArrayPool charPool) { if (stream == null) { @@ -93,42 +93,47 @@ namespace Microsoft.AspNet.Mvc.Infrastructure throw new ArgumentNullException(nameof(encoding)); } - if (leasedByteBuffer == null) + if (bytePool == null) { - throw new ArgumentNullException(nameof(leasedByteBuffer)); + throw new ArgumentNullException(nameof(bytePool)); } - if (leasedCharBuffer == null) + if (charPool == null) { - throw new ArgumentNullException(nameof(leasedCharBuffer)); + throw new ArgumentNullException(nameof(charPool)); } - if (bufferSize <= 0 || bufferSize > leasedByteBuffer.Data.Count) + if (bufferSize <= 0) { throw new ArgumentOutOfRangeException(nameof(bufferSize)); } - var requiredLength = encoding.GetMaxCharCount(bufferSize); - if (requiredLength > leasedCharBuffer.Data.Count) - { - var message = Resources.FormatHttpRequestStreamReader_InvalidBufferSize( - requiredLength, - bufferSize, - encoding.EncodingName, - typeof(Encoding).FullName, - nameof(Encoding.GetMaxCharCount)); - throw new ArgumentException(message, nameof(leasedCharBuffer)); - } - _stream = stream; _encoding = encoding; _byteBufferSize = bufferSize; - _leasedByteBuffer = leasedByteBuffer; - _leasedCharBuffer = leasedCharBuffer; + _bytePool = bytePool; + _charPool = charPool; _decoder = encoding.GetDecoder(); - _byteBuffer = _leasedByteBuffer.Data; - _charBuffer = _leasedCharBuffer.Data; + + _byteBuffer = _bytePool.Rent(bufferSize); + + try + { + var requiredLength = encoding.GetMaxCharCount(bufferSize); + _charBuffer = _charPool.Rent(requiredLength); + } + catch + { + _bytePool.Return(_byteBuffer); + _byteBuffer = null; + + if (_charBuffer != null) + { + _charPool.Return(_charBuffer); + _charBuffer = null; + } + } } #if dnx451 @@ -144,14 +149,16 @@ namespace Microsoft.AspNet.Mvc.Infrastructure { _stream = null; - if (_leasedByteBuffer != null) + if (_bytePool != null) { - _leasedByteBuffer.Owner.Return(_leasedByteBuffer); + _bytePool.Return(_byteBuffer); + _byteBuffer = null; } - if (_leasedCharBuffer != null) + if (_charPool != null) { - _leasedCharBuffer.Owner.Return(_leasedCharBuffer); + _charPool.Return(_charBuffer); + _charBuffer = null; } } @@ -173,7 +180,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure } } - return _charBuffer.Array[_charBuffer.Offset + _charBufferIndex]; + return _charBuffer[_charBufferIndex]; } public override int Read() @@ -191,7 +198,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure } } - return _charBuffer.Array[_charBuffer.Offset + _charBufferIndex++]; + return _charBuffer[_charBufferIndex++]; } public override int Read(char[] buffer, int index, int count) @@ -236,8 +243,8 @@ namespace Microsoft.AspNet.Mvc.Infrastructure } Buffer.BlockCopy( - _charBuffer.Array, - (_charBuffer.Offset + _charBufferIndex) * 2, + _charBuffer, + _charBufferIndex * 2, buffer, (index + charsRead) * 2, charsRemaining * 2); @@ -303,8 +310,8 @@ namespace Microsoft.AspNet.Mvc.Infrastructure { Debug.Assert(n == 0); _bytesRead = await _stream.ReadAsync( - _byteBuffer.Array, - _byteBuffer.Offset, + _byteBuffer, + 0, _byteBufferSize); if (_bytesRead == 0) // EOF { @@ -319,12 +326,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure _charBufferIndex = 0; n = _decoder.GetChars( - _byteBuffer.Array, - _byteBuffer.Offset, + _byteBuffer, + 0, _bytesRead, - _charBuffer.Array, - _charBuffer.Offset); - + _charBuffer, + 0); + Debug.Assert(n > 0); _charsRead += n; // Number of chars in StreamReader's buffer. @@ -344,8 +351,8 @@ namespace Microsoft.AspNet.Mvc.Infrastructure } Buffer.BlockCopy( - _charBuffer.Array, - (_charBuffer.Offset + _charBufferIndex) * 2, + _charBuffer, + _charBufferIndex * 2, buffer, (index + charsRead) * 2, n * 2); @@ -375,7 +382,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure do { - _bytesRead = _stream.Read(_byteBuffer.Array, _byteBuffer.Offset, _byteBufferSize); + _bytesRead = _stream.Read(_byteBuffer, 0, _byteBufferSize); if (_bytesRead == 0) // We're at EOF { return _charsRead; @@ -383,11 +390,11 @@ namespace Microsoft.AspNet.Mvc.Infrastructure _isBlocked = (_bytesRead < _byteBufferSize); _charsRead += _decoder.GetChars( - _byteBuffer.Array, - _byteBuffer.Offset, + _byteBuffer, + 0, _bytesRead, - _charBuffer.Array, - _charBuffer.Offset + _charsRead); + _charBuffer, + _charsRead); } while (_charsRead == 0); @@ -404,8 +411,8 @@ namespace Microsoft.AspNet.Mvc.Infrastructure { _bytesRead = await _stream.ReadAsync( - _byteBuffer.Array, - _byteBuffer.Offset, + _byteBuffer, + 0, _byteBufferSize).ConfigureAwait(false); if (_bytesRead == 0) { @@ -417,11 +424,11 @@ namespace Microsoft.AspNet.Mvc.Infrastructure _isBlocked = (_bytesRead < _byteBufferSize); _charsRead += _decoder.GetChars( - _byteBuffer.Array, - _byteBuffer.Offset, + _byteBuffer, + 0, _bytesRead, - _charBuffer.Array, - _charBuffer.Offset + _charsRead); + _charBuffer, + _charsRead); } while (_charsRead == 0); diff --git a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpRequestStreamReaderFactory.cs b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpRequestStreamReaderFactory.cs index 287c2f3c02..55c245a46e 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpRequestStreamReaderFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpRequestStreamReaderFactory.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Buffers; using System.IO; using System.Text; -using Microsoft.Extensions.MemoryPool; namespace Microsoft.AspNet.Mvc.Infrastructure { @@ -18,21 +18,21 @@ namespace Microsoft.AspNet.Mvc.Infrastructure /// public static readonly int DefaultBufferSize = 1024; // 1KB - results in a 4KB byte array for UTF8. - private readonly IArraySegmentPool _bytePool; - private readonly IArraySegmentPool _charPool; + private readonly ArrayPool _bytePool; + private readonly ArrayPool _charPool; /// /// Creates a new . /// /// - /// The for creating buffers. + /// The for creating buffers. /// /// - /// The for creating buffers. + /// The for creating buffers. /// public MemoryPoolHttpRequestStreamReaderFactory( - IArraySegmentPool bytePool, - IArraySegmentPool charPool) + ArrayPool bytePool, + ArrayPool charPool) { if (bytePool == null) { @@ -61,34 +61,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure throw new ArgumentNullException(nameof(encoding)); } - LeasedArraySegment bytes = null; - LeasedArraySegment chars = null; - - try - { - bytes = _bytePool.Lease(DefaultBufferSize); - - // We need to compute the minimum size of the char buffer based on the size of the byte buffer, - // so that we have enough room to encode the buffer in one shot. - var minimumSize = encoding.GetMaxCharCount(DefaultBufferSize); - chars = _charPool.Lease(minimumSize); - - return new HttpRequestStreamReader(stream, encoding, DefaultBufferSize, bytes, chars); - } - catch - { - if (bytes != null) - { - bytes.Owner.Return(bytes); - } - - if (chars != null) - { - chars.Owner.Return(chars); - } - - throw; - } + return new HttpRequestStreamReader(stream, encoding, DefaultBufferSize, _bytePool, _charPool); } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpResponseStreamWriterFactory.cs b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpResponseStreamWriterFactory.cs index 7686c781c5..959c0bdcc7 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpResponseStreamWriterFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/MemoryPoolHttpResponseStreamWriterFactory.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Buffers; using System.IO; using System.Text; -using Microsoft.Extensions.MemoryPool; namespace Microsoft.AspNet.Mvc.Infrastructure { @@ -18,21 +18,21 @@ namespace Microsoft.AspNet.Mvc.Infrastructure /// public static readonly int DefaultBufferSize = 1024; // 1KB - results in a 4KB byte array for UTF8. - private readonly IArraySegmentPool _bytePool; - private readonly IArraySegmentPool _charPool; + private readonly ArrayPool _bytePool; + private readonly ArrayPool _charPool; /// /// Creates a new . /// /// - /// The for creating buffers. + /// The for creating buffers. /// /// - /// The for creating buffers. + /// The for creating buffers. /// public MemoryPoolHttpResponseStreamWriterFactory( - IArraySegmentPool bytePool, - IArraySegmentPool charPool) + ArrayPool bytePool, + ArrayPool charPool) { if (bytePool == null) { @@ -61,34 +61,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure throw new ArgumentNullException(nameof(encoding)); } - LeasedArraySegment bytes = null; - LeasedArraySegment chars = null; - - try - { - chars = _charPool.Lease(DefaultBufferSize); - - // We need to compute the minimum size of the byte buffer based on the size of the char buffer, - // so that we have enough room to encode the buffer in one shot. - var minimumSize = encoding.GetMaxByteCount(DefaultBufferSize); - bytes = _bytePool.Lease(minimumSize); - - return new HttpResponseStreamWriter(stream, encoding, DefaultBufferSize, bytes, chars); - } - catch - { - if (bytes != null) - { - bytes.Owner.Return(bytes); - } - - if (chars != null) - { - chars.Owner.Return(chars); - } - - throw; - } + return new HttpResponseStreamWriter(stream, encoding, DefaultBufferSize, _bytePool, _charPool); } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs index be8aff9c5b..2918a933b4 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs @@ -970,22 +970,6 @@ namespace Microsoft.AspNet.Mvc.Core return string.Format(CultureInfo.CurrentCulture, GetString("ValueProviderResult_NoConverterExists"), p0, p1); } - /// - /// The byte buffer must have a length of at least '{0}' to be used with a char buffer of size '{1}' and encoding '{2}'. Use '{3}.{4}' to compute the correct size for the byte buffer. - /// - internal static string HttpResponseStreamWriter_InvalidBufferSize - { - get { return GetString("HttpResponseStreamWriter_InvalidBufferSize"); } - } - - /// - /// The byte buffer must have a length of at least '{0}' to be used with a char buffer of size '{1}' and encoding '{2}'. Use '{3}.{4}' to compute the correct size for the byte buffer. - /// - internal static string FormatHttpResponseStreamWriter_InvalidBufferSize(object p0, object p1, object p2, object p3, object p4) - { - return string.Format(CultureInfo.CurrentCulture, GetString("HttpResponseStreamWriter_InvalidBufferSize"), p0, p1, p2, p3, p4); - } - /// /// Path '{0}' was not rooted. /// @@ -1018,22 +1002,6 @@ namespace Microsoft.AspNet.Mvc.Core return GetString("UrlNotLocal"); } - /// - /// The char buffer must have a length of at least '{0}' to be used with a byte buffer of size '{1}' and encoding '{2}'. Use '{3}.{4}' to compute the correct size for the char buffer. - /// - internal static string HttpRequestStreamReader_InvalidBufferSize - { - get { return GetString("HttpRequestStreamReader_InvalidBufferSize"); } - } - - /// - /// The char buffer must have a length of at least '{0}' to be used with a byte buffer of size '{1}' and encoding '{2}'. Use '{3}.{4}' to compute the correct size for the char buffer. - /// - internal static string FormatHttpRequestStreamReader_InvalidBufferSize(object p0, object p1, object p2, object p3, object p4) - { - return string.Format(CultureInfo.CurrentCulture, GetString("HttpRequestStreamReader_InvalidBufferSize"), p0, p1, p2, p3, p4); - } - /// /// The stream must support reading. /// diff --git a/src/Microsoft.AspNet.Mvc.Core/Resources.resx b/src/Microsoft.AspNet.Mvc.Core/Resources.resx index 45e61ee6b4..4e9132532f 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Resources.resx +++ b/src/Microsoft.AspNet.Mvc.Core/Resources.resx @@ -306,9 +306,6 @@ The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types. - - The byte buffer must have a length of at least '{0}' to be used with a char buffer of size '{1}' and encoding '{2}'. Use '{3}.{4}' to compute the correct size for the byte buffer. - Path '{0}' was not rooted. {0} is the path which wasn't rooted @@ -316,9 +313,6 @@ The supplied URL is not local. A URL with an absolute path is considered local if it does not have a host/authority part. URLs using virtual paths ('~/') are also local. - - The char buffer must have a length of at least '{0}' to be used with a byte buffer of size '{1}' and encoding '{2}'. Use '{3}.{4}' to compute the correct size for the char buffer. - The stream must support reading. diff --git a/src/Microsoft.AspNet.Mvc.Core/project.json b/src/Microsoft.AspNet.Mvc.Core/project.json index eddf001d5d..e16c385e12 100644 --- a/src/Microsoft.AspNet.Mvc.Core/project.json +++ b/src/Microsoft.AspNet.Mvc.Core/project.json @@ -26,7 +26,6 @@ "type": "build" }, "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", - "Microsoft.Extensions.MemoryPool": "1.0.0-*", "Microsoft.Extensions.PropertyActivator.Sources": { "version": "1.0.0-*", "type": "build" @@ -39,6 +38,7 @@ "version": "1.0.0-*", "type": "build" }, + "System.Buffers": "4.0.0-*", "System.Diagnostics.DiagnosticSource": "4.0.0-*" }, "frameworks": { diff --git a/src/Microsoft.AspNet.Mvc.Razor/project.json b/src/Microsoft.AspNet.Mvc.Razor/project.json index 0d951debbe..58f3b8322a 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/project.json +++ b/src/Microsoft.AspNet.Mvc.Razor/project.json @@ -26,7 +26,8 @@ "type": "build" }, "Microsoft.Dnx.Compilation.CSharp.Common": "1.0.0-*", - "Microsoft.Dnx.Compilation.CSharp.Abstractions": "1.0.0-*" + "Microsoft.Dnx.Compilation.CSharp.Abstractions": "1.0.0-*", + "Microsoft.Extensions.MemoryPool": "1.0.0-*" }, "frameworks": { "net451": { diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs index a75acecf89..c120406825 100644 --- a/src/Microsoft.AspNet.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/DependencyInjection/MvcViewFeaturesMvcCoreBuilderExtensions.cs @@ -13,7 +13,6 @@ using Microsoft.AspNet.Mvc.ViewFeatures; using Microsoft.AspNet.Mvc.ViewFeatures.Buffer; using Microsoft.AspNet.Mvc.ViewFeatures.Internal; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.MemoryPool; using Microsoft.Extensions.OptionsModel; namespace Microsoft.Extensions.DependencyInjection diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/HttpResponseStreamWriterTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/HttpResponseStreamWriterTest.cs index e2ad414991..28913b2005 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/HttpResponseStreamWriterTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/HttpResponseStreamWriterTest.cs @@ -1,12 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Buffers; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Testing; -using Microsoft.Extensions.MemoryPool; using Xunit; namespace Microsoft.AspNet.Mvc @@ -384,98 +384,21 @@ namespace Microsoft.AspNet.Mvc var expectedBytes = encoding.GetBytes("Hello, World!"); - using (var bytePool = new DefaultArraySegmentPool()) + using (var writer = new HttpResponseStreamWriter( + stream, + encoding, + 1024, + ArrayPool.Shared, + ArrayPool.Shared)) { - using (var charPool = new DefaultArraySegmentPool()) - { - LeasedArraySegment bytes = null; - LeasedArraySegment chars = null; - HttpResponseStreamWriter writer; - - try - { - bytes = bytePool.Lease(4096); - chars = charPool.Lease(1024); - - writer = new HttpResponseStreamWriter(stream, encoding, 1024, bytes, chars); - } - catch - { - if (bytes != null) - { - bytes.Owner.Return(bytes); - } - - if (chars != null) - { - chars.Owner.Return(chars); - } - - throw; - } - - // Act - using (writer) - { - writer.Write("Hello, World!"); - } - } + // Act + writer.Write("Hello, World!"); } // Assert Assert.Equal(expectedBytes, stream.ToArray()); } - // This covers the error case where the byte buffer is too small. This is a safeguard, and shouldn't happen - // if we're using the writer factory. - [Fact] - public void HttpResponseStreamWriter_UsingPooledBuffers_SmallByteBuffer() - { - // Arrange - var encoding = Encoding.UTF8; - var stream = new MemoryStream(); - - var message = - "The byte buffer must have a length of at least '12291' to be used with a char buffer of " + - "size '4096' and encoding 'Unicode (UTF-8)'. Use 'System.Text.Encoding.GetMaxByteCount' " + - "to compute the correct size for the byte buffer."; - - using (var bytePool = new DefaultArraySegmentPool()) - { - using (var charPool = new DefaultArraySegmentPool()) - { - LeasedArraySegment bytes = null; - LeasedArraySegment chars = null; - HttpResponseStreamWriter writer = null; - - try - { - bytes = bytePool.Lease(1024); - chars = charPool.Lease(4096); - - // Act & Assert - ExceptionAssert.ThrowsArgument( - () => writer = new HttpResponseStreamWriter(stream, encoding, chars.Data.Count, bytes, chars), - "byteBuffer", - message); - writer.Dispose(); - } - catch - { - if (bytes != null) - { - bytes.Owner.Return(bytes); - } - - if (chars != null) - { - chars.Owner.Return(chars); - } - } - } - } - } - private class TestMemoryStream : MemoryStream { private int _flushCallCount; diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/MemoryPoolHttpResponseStreamWriterFactoryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/MemoryPoolHttpResponseStreamWriterFactoryTest.cs deleted file mode 100644 index e368ce6691..0000000000 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/MemoryPoolHttpResponseStreamWriterFactoryTest.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Text; -using Microsoft.Extensions.MemoryPool; -using Moq; -using Xunit; - -namespace Microsoft.AspNet.Mvc.Infrastructure -{ - public class MemoryPoolHttpResponseStreamWriterFactoryTest - { - [Fact] - public void CreateWriter_BuffersReturned_OnException() - { - // Arrange - var bytePool = new Mock>(MockBehavior.Strict); - bytePool - .Setup(p => p.Lease(It.IsAny())) - .Returns(new LeasedArraySegment(new ArraySegment(new byte[4096]), bytePool.Object)); - bytePool - .Setup(p => p.Return(It.IsAny>())) - .Verifiable(); - - var charPool = new Mock>(MockBehavior.Strict); - charPool - .Setup(p => p.Lease(MemoryPoolHttpResponseStreamWriterFactory.DefaultBufferSize)) - .Returns(new LeasedArraySegment(new ArraySegment(new char[4096]), charPool.Object)); - charPool - .Setup(p => p.Return(It.IsAny>())) - .Verifiable(); - - var encoding = new Mock(); - encoding - .Setup(e => e.GetEncoder()) - .Throws(new InvalidOperationException()); - - var factory = new MemoryPoolHttpResponseStreamWriterFactory(bytePool.Object, charPool.Object); - - // Act - Assert.Throws(() => factory.CreateWriter(new MemoryStream(), encoding.Object)); - - // Assert - bytePool.Verify(); - charPool.Verify(); - } - } -}