Skip to content

Commit

Permalink
Use RecyclableMemoryStream
Browse files Browse the repository at this point in the history
Fix #16946

Related Work Items: #169
  • Loading branch information
MikeAlhayek committed Nov 4, 2024
1 parent 8dcefad commit a1b7fa9
Show file tree
Hide file tree
Showing 30 changed files with 67 additions and 34 deletions.
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
See https://github.com/OrchardCMS/OrchardCore/pull/16057 for more information.
-->
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.1.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="MimeKit" Version="4.8.0" />
<PackageVersion Include="MiniProfiler.AspNetCore.Mvc" Version="4.3.8" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private async Task<XRpcStruct> MetaWeblogNewMediaObjectAsync(string userName, st
Stream stream = null;
try
{
stream = new MemoryStream(bits);
stream = MemoryStreamFactory.GetStream(bits);
filePath = await _mediaFileStore.CreateFileFromStreamAsync(filePath, stream);
}
finally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

<ItemGroup>
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Indexing.Abstractions\OrchardCore.Indexing.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Infrastructure.Abstractions\OrchardCore.Infrastructure.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Media.Abstractions\OrchardCore.Media.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Module.Targets\OrchardCore.Module.Targets.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.ResourceManagement\OrchardCore.ResourceManagement.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public async Task<string> GetTextAsync(string path, Stream fileStream)
{
// Since fileStream.Length might not be supported either, we can't preconfigure the capacity of the
// MemoryStream.
seekableStream = new MemoryStream();
seekableStream = MemoryStreamFactory.GetStream();
// While this involves loading the file into memory, we don't really have a choice.
await fileStream.CopyToAsync(seekableStream);
seekableStream.Position = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ protected override async Task HandleAsync(RecipeExecutionContext context)

if (!string.IsNullOrWhiteSpace(file.Base64))
{
stream = new MemoryStream(Convert.FromBase64String(file.Base64));
stream = MemoryStreamFactory.GetStream(Convert.FromBase64String(file.Base64));
}
else if (!string.IsNullOrWhiteSpace(file.SourcePath))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public override async Task<IDisplayResult> UpdateAsync(ISite site, ElasticSettin
section.DefaultQuery = jsonObject.ToJsonString(JOptions.Indented);
try
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(model.DefaultQuery));
using var stream = MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(model.DefaultQuery));
var searchRequest = await _elasticClient.RequestResponseSerializer.DeserializeAsync<SearchRequest>(stream);
}
catch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public async Task<SearchResult> SearchAsync(string indexName, string term, int s

try
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(tokenizedContent));
using var stream = MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(tokenizedContent));

var searchRequest = await _elasticClient.RequestResponseSerializer.DeserializeAsync<SearchRequest>(stream);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public async Task<IActionResult> Index(string sitemapId, CancellationToken cance
document.Declaration = new XDeclaration("1.0", "utf-8", null);
var stream = new MemoryStream();
var stream = MemoryStreamFactory.GetStream();
await document.SaveAsync(stream, SaveOptions.None, cancellationToken);
if (stream.Length >= ErrorLength)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task<IActionResult> ServiceEndpoint([ModelBinder(BinderType = typeo
};

// Save to an intermediate MemoryStream to preserve the encoding declaration.
using var stream = new MemoryStream();
using var stream = MemoryStreamFactory.GetStream();
using (var w = XmlWriter.Create(stream, settings))
{
var result = _writer.MapMethodResponse(methodResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Infrastructure.Abstractions\OrchardCore.Infrastructure.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Module.Targets\OrchardCore.Module.Targets.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.XmlRpc.Abstractions\OrchardCore.XmlRpc.Abstractions.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public static class IFileBuilderExtensions
{
public static async Task SetFileAsync(this IFileBuilder fileBuilder, string subpath, byte[] content)
{
using var stream = new MemoryStream(content);
using var stream = MemoryStreamFactory.GetStream(content);
await fileBuilder.SetFileAsync(subpath, stream);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public DateTimeOffset LastModified

public Stream CreateReadStream()
{
return new MemoryStream(_content);
return MemoryStreamFactory.GetStream(_content);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ public class BlobFileStore : IFileStore
private readonly IClock _clock;
private readonly BlobContainerClient _blobContainer;
private readonly IContentTypeProvider _contentTypeProvider;

private readonly string _basePrefix;

public BlobFileStore(BlobStorageOptions options, IClock clock, IContentTypeProvider contentTypeProvider)
public BlobFileStore(
BlobStorageOptions options,
IClock clock,
IContentTypeProvider contentTypeProvider)
{
_options = options;
_clock = clock;
_contentTypeProvider = contentTypeProvider;

_blobContainer = new BlobContainerClient(_options.ConnectionString, _options.ContainerName);

if (!string.IsNullOrEmpty(_options.BasePath))
Expand Down Expand Up @@ -435,7 +438,8 @@ private async Task CreateDirectoryAsync(string path)
var placeholderBlob = GetBlobReference(this.Combine(path, DirectoryMarkerFileName));

// Create a directory marker file to make this directory appear when listing directories.
using var stream = new MemoryStream(MarkerFileContent);
using var stream = MemoryStreamFactory.GetStream(MarkerFileContent);

await placeholderBlob.UploadAsync(stream);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<ItemGroup>
<ProjectReference Include="..\OrchardCore.Abstractions\OrchardCore.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.FileStorage.Abstractions\OrchardCore.FileStorage.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.Infrastructure.Abstractions\OrchardCore.Infrastructure.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.Liquid.Abstractions\OrchardCore.Liquid.Abstractions.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.IO;

namespace OrchardCore;

public static class MemoryStreamFactory
{
private static readonly RecyclableMemoryStreamManager _manager = new();

public static MemoryStream GetStream(byte[] buffer, int offset, int count, string tag = null)
=> _manager.GetStream(tag, buffer, offset, count);

public static MemoryStream GetStream(byte[] buffer, string tag = null)
=> _manager.GetStream(tag, buffer, 0, buffer.Length);

public static MemoryStream GetStream()
=> _manager.GetStream();

public static MemoryStream GetStream(string tag)
=> _manager.GetStream(tag);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\OrchardCore.Abstractions\OrchardCore.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.Data.Abstractions\OrchardCore.Data.Abstractions.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public Task<TDocument> DeserializeAsync<TDocument>(byte[] data)
data = Decompress(data);
}

using var ms = new MemoryStream(data);
using var ms = MemoryStreamFactory.GetStream(data);

var document = JsonSerializer.Deserialize<TDocument>(ms, _serializerOptions);

Expand All @@ -59,8 +59,8 @@ internal static bool IsCompressed(byte[] data)

internal static byte[] Compress(byte[] data)
{
using var input = new MemoryStream(data);
using var output = new MemoryStream();
using var input = MemoryStreamFactory.GetStream(data);
using var output = MemoryStreamFactory.GetStream();
using (var gzip = new GZipStream(output, CompressionMode.Compress))
{
input.CopyTo(gzip);
Expand All @@ -76,8 +76,8 @@ internal static byte[] Compress(byte[] data)

internal static byte[] Decompress(byte[] data)
{
using var input = new MemoryStream(data);
using var output = new MemoryStream();
using var input = MemoryStreamFactory.GetStream(data);
using var output = MemoryStreamFactory.GetStream();
using (var gzip = new GZipStream(input, CompressionMode.Decompress))
{
gzip.CopyTo(output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ public class CommonGeneratorMethods : IGlobalMethodProvider
/// Converts a Base64 encoded gzip stream to an uncompressed Base64 string.
/// See http://www.txtwizard.net/compression.
/// </summary>
private static readonly GlobalMethod _gZip = new()
private readonly GlobalMethod _gZip = new()
{
Name = "gzip",
Method = serviceProvider => (Func<string, string>)(encoded =>
{
var bytes = Convert.FromBase64String(encoded);
using var gzip = new GZipStream(new MemoryStream(bytes), CompressionMode.Decompress);
using var gzip = new GZipStream(MemoryStreamFactory.GetStream(bytes), CompressionMode.Decompress);
var decompressed = new MemoryStream();
var decompressed = MemoryStreamFactory.GetStream();
var buffer = new byte[1024];
int nRead;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public object Evaluate(IScriptingScope scope, string script)
}

using var fileStream = fileInfo.CreateReadStream();
using var ms = new MemoryStream();
using var ms = MemoryStreamFactory.GetStream();
fileStream.CopyTo(ms);
return Convert.ToBase64String(ms.ToArray());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public async Task AddSourcesAsync(string tenant, IConfigurationBuilder builder)
if (configuration is not null)
{
var configurationString = configuration.ToJsonString(JOptions.Default);
builder.AddTenantJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(configurationString)));
builder.AddTenantJsonStream(MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(configurationString)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public async Task AddSourcesAsync(IConfigurationBuilder builder)
if (document.ShellsSettings is not null)
{
var shellsSettingsString = document.ShellsSettings.ToJsonString(JOptions.Default);
builder.AddTenantJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(shellsSettingsString)));
builder.AddTenantJsonStream(MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(shellsSettingsString)));
}
}

Expand All @@ -53,7 +53,7 @@ public async Task AddSourcesAsync(string tenant, IConfigurationBuilder builder)
{
var shellSettings = new JsonObject { [tenant] = document.ShellsSettings[tenant] };
var shellSettingsString = shellSettings.ToJsonString(JOptions.Default);
builder.AddTenantJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(shellSettingsString)));
builder.AddTenantJsonStream(MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(shellSettingsString)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public async Task<ElasticTopDocs> SearchAsync(string indexName, string query)

try
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(query));
using var stream = MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(query));
var deserializedSearchRequest = _elasticClient.RequestResponseSerializer.Deserialize<SearchRequest>(stream);

var searchRequest = new SearchRequest(_elasticIndexManager.GetFullIndexName(indexName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public async Task SaveAsync(string tenant, IDictionary<string, string> data)
}

var configurationString = configData.ToJsonObject().ToJsonString(JOptions.Default);
using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(configurationString));
using var memoryStream = MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(configurationString));

await _shellsFileStore.CreateFileFromStreamAsync(appsettings, memoryStream);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public async Task SaveAsync(string tenant, IDictionary<string, string> data)
tenantsSettings[tenant] = settings;

var tenantsSettingsString = tenantsSettings.ToJsonString(JOptions.Default);
using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(tenantsSettingsString));
using var memoryStream = MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(tenantsSettingsString));

await _shellsFileStore.CreateFileFromStreamAsync(OrchardCoreConstants.Shell.TenantsFileName, memoryStream);
}
Expand All @@ -102,7 +102,7 @@ public async Task RemoveAsync(string tenant)
tenantsSettings.Remove(tenant);

var tenantsSettingsString = tenantsSettings.ToJsonString(JOptions.Default);
using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(tenantsSettingsString));
using var memoryStream = MemoryStreamFactory.GetStream(Encoding.UTF8.GetBytes(tenantsSettingsString));

await _shellsFileStore.CreateFileFromStreamAsync(OrchardCoreConstants.Shell.TenantsFileName, memoryStream);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\OrchardCore.Abstractions\OrchardCore.Abstractions.csproj" />
<ProjectReference Include="..\OrchardCore.FileStorage.AzureBlob\OrchardCore.FileStorage.AzureBlob.csproj" />
<ProjectReference Include="..\OrchardCore.Infrastructure.Abstractions\OrchardCore.Infrastructure.Abstractions.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static JsonObject GetContentStepRecipe(ContentItem contentItem, Action<Js

public async Task<HttpResponseMessage> PostRecipeAsync(JsonObject recipe, bool ensureSuccess = true)
{
using var zipStream = new MemoryStream();
using var zipStream = MemoryStreamFactory.GetStream();
using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
var entry = zip.CreateEntry("Recipe.json");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public void HtmlLocalizerDoesNotFormatTwiceIfFormattedTranslationContainsCurlyBr
{
var htmlLocalizer = new PortableObjectHtmlLocalizer(localizer);
var unformatted = htmlLocalizer["The page (ID:{0}) was deleted.", "{1}"];
var memStream = new MemoryStream();
var memStream = MemoryStreamFactory.GetStream();
var textWriter = new StreamWriter(memStream);
var textReader = new StreamReader(memStream);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public async Task DisposesMediaCreatingStreams()
#pragma warning restore CA1859
try
{
inputStream = new MemoryStream();
inputStream = MemoryStreamFactory.GetStream();
originalStream = inputStream;

// Add original stream to streams to maintain reference to test disposal.
Expand Down Expand Up @@ -78,7 +78,7 @@ public class TestMediaEventHandler : IMediaCreatingEventHandler
{
public async Task<Stream> MediaCreatingAsync(MediaCreatingContext context, Stream inputStream)
{
var outStream = new MemoryStream();
var outStream = MemoryStreamFactory.GetStream();
await inputStream.CopyToAsync(outStream);

return outStream;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private static async Task<string> GetSubResourceIntegrityAsync(HttpClient httpCl
{
var data = await httpClient.GetByteArrayAsync(url);

using var memoryStream = new MemoryStream(data);
using var memoryStream = MemoryStreamFactory.GetStream(data);
var hash = await SHA384.HashDataAsync(memoryStream);

return "sha384-" + Convert.ToBase64String(hash);
Expand Down
2 changes: 1 addition & 1 deletion test/OrchardCore.Tests/Stubs/MemoryFileBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class MemoryFileBuilder

public async Task SetFileAsync(string subpath, Stream stream)
{
using var ms = new MemoryStream();
using var ms = MemoryStreamFactory.GetStream();
await stream.CopyToAsync(ms);
VirtualFiles[subpath] = ms.ToArray();
}
Expand Down

0 comments on commit a1b7fa9

Please sign in to comment.