Merged PR 785202: Make TempFileStreamFactory async

Make TempFileStreamFactory async
This commit is contained in:
Julian Bayardo 2024-05-15 21:55:38 +00:00
Родитель 8e7874240d
Коммит 78684e203e
4 изменённых файлов: 23 добавлений и 41 удалений

Просмотреть файл

@ -206,7 +206,7 @@ namespace BuildXL.Cache.ContentStore.Interfaces.FileSystem
return null; return null;
} }
if (expectingLength != null) if (expectingLength != null && expectingLength.Value >= 0)
{ {
stream.Value.Stream.SetLength(expectingLength.Value); stream.Value.Stream.SetLength(expectingLength.Value);
} }

Просмотреть файл

@ -1,13 +1,9 @@
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using BuildXL.Cache.ContentStore.Exceptions;
using BuildXL.Cache.ContentStore.Hashing;
using BuildXL.Cache.ContentStore.Interfaces.Extensions; using BuildXL.Cache.ContentStore.Interfaces.Extensions;
using BuildXL.Cache.ContentStore.Interfaces.FileSystem;
namespace BuildXL.Cache.ContentStore.Extensions namespace BuildXL.Cache.ContentStore.Extensions
{ {
@ -35,35 +31,5 @@ namespace BuildXL.Cache.ContentStore.Extensions
return content.ToArray(); return content.ToArray();
} }
} }
/// <summary>
/// Copy all or some bytes from one stream to another.
/// </summary>
public static void CopyTo(this Stream sourceStream, Stream destinationStream, int bufferSize, long size)
{
if (size < 0)
{
sourceStream.CopyTo(destinationStream, bufferSize);
return;
}
var buffer = new byte[bufferSize];
var bytesLeft = size;
while (bytesLeft > 0)
{
var bytesToRead = (int)Math.Min(bytesLeft, bufferSize);
var bytesRead = sourceStream.Read(buffer, 0, bytesToRead);
if (bytesRead == 0)
{
throw new CacheException($"Read {bytesRead} bytes from ClientStream, but expected to read {bytesToRead} bytes");
}
destinationStream.Write(buffer, 0, bytesRead);
bytesLeft -= bytesRead;
}
}
} }
} }

Просмотреть файл

@ -4,10 +4,12 @@
using System; using System;
using System.Diagnostics.ContractsLight; using System.Diagnostics.ContractsLight;
using System.IO; using System.IO;
using System.Threading.Tasks;
using BuildXL.Cache.ContentStore.Extensions; using BuildXL.Cache.ContentStore.Extensions;
using BuildXL.Cache.ContentStore.Interfaces.FileSystem; using BuildXL.Cache.ContentStore.Interfaces.FileSystem;
using BuildXL.Cache.ContentStore.Interfaces.Tracing; using BuildXL.Cache.ContentStore.Interfaces.Tracing;
using BuildXL.Cache.ContentStore.Tracing; using BuildXL.Cache.ContentStore.Tracing;
using BuildXL.Cache.ContentStore.Tracing.Internal;
using BuildXL.Utilities.Core; using BuildXL.Utilities.Core;
namespace BuildXL.Cache.ContentStore.FileSystem namespace BuildXL.Cache.ContentStore.FileSystem
@ -41,20 +43,34 @@ namespace BuildXL.Cache.ContentStore.FileSystem
/// <summary> /// <summary>
/// Create a new instance from content in the given input stream. /// Create a new instance from content in the given input stream.
/// </summary> /// </summary>
public FileStream Create(Context context, Stream stream, long size = -1) public async Task<FileStream> CreateAsync(OperationContext context, Stream stream, long? size = null)
{ {
const int bufSize = FileSystemConstants.FileIOBufferSize; Contract.RequiresNotNull(stream);
var path = _directory.CreateRandomFileName(); var path = _directory.CreateRandomFileName();
try try
{ {
using (var fileStream = new FileStream(path.Path, FileMode.Create, FileAccess.Write, FileShare.None, bufSize)) using (var fileStream = _fileSystem.TryOpenForWrite(
path,
size,
FileMode.Create,
FileShare.None,
FileOptions.SequentialScan | FileOptions.Asynchronous,
AbsFileSystemExtension.DefaultFileStreamBufferSize))
{ {
stream.CopyTo(fileStream, bufSize, size); Contract.AssertNotNull(fileStream);
await stream.CopyToAsync(fileStream.Value.Stream, AbsFileSystemExtension.DefaultFileStreamBufferSize, context.Token);
} }
// Please note, this temporary file will be deleted once it's closed (i.e., even if the program
// crashes!)
return new FileStream( return new FileStream(
path.Path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, bufSize, FileOptions.DeleteOnClose); path.Path,
FileMode.Open,
FileAccess.Read,
FileShare.Read | FileShare.Delete,
AbsFileSystemExtension.DefaultFileStreamBufferSize,
FileOptions.DeleteOnClose);
} }
catch (Exception exception) catch (Exception exception)
{ {

Просмотреть файл

@ -324,7 +324,7 @@ namespace BuildXL.Cache.ContentStore.Sessions
Stream? disposableStream = null; Stream? disposableStream = null;
if (!stream.CanSeek) if (!stream.CanSeek)
{ {
putStream = TempFileStreamFactory.Create(operationContext, stream); putStream = await TempFileStreamFactory.CreateAsync(operationContext, stream);
disposableStream = putStream; disposableStream = putStream;
} }