// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
namespace EpicGames.Horde.Storage
{
///
/// Request for a chunk to be read before being written to disk
///
/// File to read from
/// Offset within the output file
/// Handle to the blob data
record class ChunkReadRequest(OutputFile File, long Offset, IHashedBlobRef Handle) : BlobReadRequest(Handle);
///
/// Implementation of designed for reading leaf chunks of data from storage
///
class BatchChunkReader : BatchBlobReader, IDisposable
{
public const int DefaultMaxBatchSize = 20;
///
/// Maximum number of exports to write in a single request
///
public int MaxBatchSize
{
get => _maxBatchSize;
init
{
if (value > 0)
{
_maxBatchSize = value;
}
}
}
readonly int _maxBatchSize = DefaultMaxBatchSize;
readonly ChannelWriter _writer;
///
/// Constructor
///
public BatchChunkReader(ChannelWriter writer)
{
_writer = writer;
}
///
protected override async ValueTask HandleResponsesAsync(List> responses, CancellationToken cancellationToken)
{
for (int idx = 0; idx < responses.Count;)
{
int firstIdx = idx;
List batch = new List();
for (; idx < responses.Count && batch.Count < MaxBatchSize && responses[idx].Request.File == responses[firstIdx].Request.File; idx++)
{
BlobReadResponse response = responses[idx];
OutputChunk chunk = new OutputChunk(response.Request.File, response.Request.Offset, response.Data.Data, response.Request.Handle, response.Data);
batch.Add(chunk);
}
await _writer.WriteAsync(batch.ToArray(), cancellationToken);
}
}
}
}