Update DownloadDepotChunkAsync to use array pool

pull/526/head
Pavel Djundik 1 year ago
parent a3fc9c4c45
commit baa64e9e51

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
@ -1199,80 +1200,91 @@ namespace DepotDownloader
UncompressedLength = chunk.UncompressedLength
};
DepotChunk chunkData = null;
var written = 0;
var chunkBuffer = ArrayPool<byte>.Shared.Rent((int)data.UncompressedLength);
do
try
{
cts.Token.ThrowIfCancellationRequested();
do
{
cts.Token.ThrowIfCancellationRequested();
Server connection = null;
Server connection = null;
try
{
connection = cdnPool.GetConnection(cts.Token);
try
{
connection = cdnPool.GetConnection(cts.Token);
DebugLog.WriteLine("ContentDownloader", "Downloading chunk {0} from {1} with {2}", chunkID, connection, cdnPool.ProxyServer != null ? cdnPool.ProxyServer : "no proxy");
chunkData = await cdnPool.CDNClient.DownloadDepotChunkAsync(
depot.DepotId,
data,
connection,
depot.DepotKey,
cdnPool.ProxyServer).ConfigureAwait(false);
DebugLog.WriteLine("ContentDownloader", "Downloading chunk {0} from {1} with {2}", chunkID, connection, cdnPool.ProxyServer != null ? cdnPool.ProxyServer : "no proxy");
written = await cdnPool.CDNClient.DownloadDepotChunkAsync(
depot.DepotId,
data,
connection,
chunkBuffer,
depot.DepotKey,
cdnPool.ProxyServer).ConfigureAwait(false);
cdnPool.ReturnConnection(connection);
}
catch (TaskCanceledException)
{
Console.WriteLine("Connection timeout downloading chunk {0}", chunkID);
}
catch (SteamKitWebRequestException e)
{
cdnPool.ReturnBrokenConnection(connection);
cdnPool.ReturnConnection(connection);
break;
}
catch (TaskCanceledException)
{
Console.WriteLine("Connection timeout downloading chunk {0}", chunkID);
}
catch (SteamKitWebRequestException e)
{
cdnPool.ReturnBrokenConnection(connection);
if (e.StatusCode == HttpStatusCode.Unauthorized || e.StatusCode == HttpStatusCode.Forbidden)
{
Console.WriteLine("Encountered {1} for chunk {0}. Aborting.", chunkID, (int)e.StatusCode);
break;
}
if (e.StatusCode == HttpStatusCode.Unauthorized || e.StatusCode == HttpStatusCode.Forbidden)
Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, e.StatusCode);
}
catch (OperationCanceledException)
{
Console.WriteLine("Encountered {1} for chunk {0}. Aborting.", chunkID, (int)e.StatusCode);
break;
}
catch (Exception e)
{
cdnPool.ReturnBrokenConnection(connection);
Console.WriteLine("Encountered unexpected error downloading chunk {0}: {1}", chunkID, e.Message);
}
} while (written == 0);
Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, e.StatusCode);
}
catch (OperationCanceledException)
{
break;
}
catch (Exception e)
if (written == 0)
{
cdnPool.ReturnBrokenConnection(connection);
Console.WriteLine("Encountered unexpected error downloading chunk {0}: {1}", chunkID, e.Message);
Console.WriteLine("Failed to find any server with chunk {0} for depot {1}. Aborting.", chunkID, depot.DepotId);
cts.Cancel();
}
} while (chunkData == null);
if (chunkData == null)
{
Console.WriteLine("Failed to find any server with chunk {0} for depot {1}. Aborting.", chunkID, depot.DepotId);
cts.Cancel();
}
// Throw the cancellation exception if requested so that this task is marked failed
cts.Token.ThrowIfCancellationRequested();
// Throw the cancellation exception if requested so that this task is marked failed
cts.Token.ThrowIfCancellationRequested();
try
{
await fileStreamData.fileLock.WaitAsync().ConfigureAwait(false);
try
{
await fileStreamData.fileLock.WaitAsync().ConfigureAwait(false);
if (fileStreamData.fileStream == null)
{
var fileFinalPath = Path.Combine(depot.InstallDir, file.FileName);
fileStreamData.fileStream = File.Open(fileFinalPath, FileMode.Open);
}
if (fileStreamData.fileStream == null)
fileStreamData.fileStream.Seek((long)data.Offset, SeekOrigin.Begin);
await fileStreamData.fileStream.WriteAsync(chunkBuffer.AsMemory(0, written), cts.Token);
}
finally
{
var fileFinalPath = Path.Combine(depot.InstallDir, file.FileName);
fileStreamData.fileStream = File.Open(fileFinalPath, FileMode.Open);
fileStreamData.fileLock.Release();
}
fileStreamData.fileStream.Seek((long)chunkData.ChunkInfo.Offset, SeekOrigin.Begin);
await fileStreamData.fileStream.WriteAsync(chunkData.Data.AsMemory(0, chunkData.Data.Length), cts.Token);
}
finally
{
fileStreamData.fileLock.Release();
ArrayPool<byte>.Shared.Return(chunkBuffer);
}
var remainingChunks = Interlocked.Decrement(ref fileStreamData.chunksToDownload);
@ -1285,7 +1297,7 @@ namespace DepotDownloader
ulong sizeDownloaded = 0;
lock (depotDownloadCounter)
{
sizeDownloaded = depotDownloadCounter.sizeDownloaded + (ulong)chunkData.Data.Length;
sizeDownloaded = depotDownloadCounter.sizeDownloaded + (ulong)written;
depotDownloadCounter.sizeDownloaded = sizeDownloaded;
depotDownloadCounter.depotBytesCompressed += chunk.CompressedLength;
depotDownloadCounter.depotBytesUncompressed += chunk.UncompressedLength;

@ -15,6 +15,6 @@
<ItemGroup>
<PackageReference Include="protobuf-net" Version="3.2.30" />
<PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="SteamKit2" Version="3.0.0-Beta.1" />
<PackageReference Include="SteamKit2" Version="3.0.0-Beta.2" />
</ItemGroup>
</Project>

Loading…
Cancel
Save