Nit: Explicitly pass flag indicating if parity repair is allowed

This commit is contained in:
Kenneth Skovhede
2026-07-12 11:47:26 +02:00
parent 1470b05a4b
commit 094579b352
14 changed files with 56 additions and 51 deletions
@@ -309,9 +309,10 @@ internal partial class BackendManager : IBackendManager
/// <param name="remotename">The name of the remote file</param>
/// <param name="hash">The hash of the remote file, for verification</param>
/// <param name="size">The size of the remote file, for verification</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>A temporary file with the contents of the remote file</returns>
public async Task<TempFile> GetAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true)
public async Task<TempFile> GetAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken)
{
var op = new GetOperation(remotename, size, context, cancelToken)
{
@@ -331,9 +332,10 @@ internal partial class BackendManager : IBackendManager
/// <param name="remotename">The name of the remote file</param>
/// <param name="hash">The hash of the remote file, for verification</param>
/// <param name="size">The size of the remote file, for verification</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>A temporary file with the contents of the remote file</returns>
public async Task<TempFile> GetDirectAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true)
public async Task<TempFile> GetDirectAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken)
{
var op = new GetOperation(remotename, size, context, cancelToken)
{
@@ -365,9 +367,10 @@ internal partial class BackendManager : IBackendManager
/// <param name="remotename">The name of the remote file</param>
/// <param name="hash">The hash of the remote file, or null if not known</param>
/// <param name="size">The size of the remote file, or -1 if not known</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>A tuple containing the temporary file, the hash of the file, and the size of the file</returns>
public async Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true)
public async Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken)
{
var op = new GetOperation(remotename, size, context, cancelToken)
{
@@ -557,22 +560,23 @@ internal partial class BackendManager : IBackendManager
/// Performs a download of the files specified, with pre-fetch to overlap the download and processing
/// </summary>
/// <param name="volumes">The volumes to download</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>The downloaded files and the volume they came from</returns>
public async IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable<IRemoteVolume> volumes, [EnumeratorCancellation] CancellationToken cancelToken, bool allowParityRepair = true)
public async IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, [EnumeratorCancellation] CancellationToken cancelToken)
{
var prevVolume = volumes.FirstOrDefault();
if (prevVolume == null)
yield break;
// Get the first volume, so we do not have pending parallel transfers
var prevResult = await GetWithInfoAsync(prevVolume.Name, prevVolume.Hash, prevVolume.Size, cancelToken, allowParityRepair)
var prevResult = await GetWithInfoAsync(prevVolume.Name, prevVolume.Hash, prevVolume.Size, allowParityRepair, cancelToken)
.ConfigureAwait(false);
foreach (var volume in volumes.Skip(1))
{
// Prepare the next volume, while processing the previous one
var nextTask = GetWithInfoAsync(volume.Name, volume.Hash, volume.Size, cancelToken, allowParityRepair);
var nextTask = GetWithInfoAsync(volume.Name, volume.Hash, volume.Size, allowParityRepair, cancelToken);
// Assuming we do not throw while yielding, otherwise we would need to dispose nextTask
yield return (prevResult.File, prevResult.Hash, prevResult.Size, prevVolume.Name);
@@ -592,22 +596,23 @@ internal partial class BackendManager : IBackendManager
/// Performs a direct download of the files specified, with pre-fetch to overlap the download and processing
/// </summary>
/// <param name="volumes">The volumes to download</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>The downloaded files and the volume they came from</returns>
public async IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(IEnumerable<IRemoteVolume> volumes, [EnumeratorCancellation] CancellationToken cancelToken, bool allowParityRepair = true)
public async IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, [EnumeratorCancellation] CancellationToken cancelToken)
{
var prevVolume = volumes.FirstOrDefault();
if (prevVolume == null)
yield break;
// Get the first volume, so we do not have pending parallel transfers
var prevResult = await GetDirectAsync(prevVolume.Name, prevVolume.Hash, prevVolume.Size, cancelToken, allowParityRepair)
var prevResult = await GetDirectAsync(prevVolume.Name, prevVolume.Hash, prevVolume.Size, allowParityRepair, cancelToken)
.ConfigureAwait(false);
foreach (var volume in volumes.Skip(1))
{
// Prepare the next volume, while processing the previous one
var nextTask = GetDirectAsync(volume.Name, volume.Hash, volume.Size, cancelToken, allowParityRepair);
var nextTask = GetDirectAsync(volume.Name, volume.Hash, volume.Size, allowParityRepair, cancelToken);
// Assuming we do not throw while yielding, otherwise we would need to dispose nextTask
yield return (prevResult, prevVolume.Name);
+10 -10
View File
@@ -144,10 +144,10 @@ internal interface IBackendManager : IDisposable
/// <param name="remotename">The name of the file to get</param>
/// <param name="hash">The hash of the file to get, or <c>null</c> if not known</param>
/// <param name="size">The size of the file to get, or -1 if not known</param>
/// <param name="cancelToken">The cancellation token</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data. Disable for the test/verification flow so damaged files are reported.</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>The file, hash, and size</returns>
Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true);
Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken);
/// <summary>
/// Gets a file from the backend
@@ -155,10 +155,10 @@ internal interface IBackendManager : IDisposable
/// <param name="remotename">The name of the file to get</param>
/// <param name="hash">The hash of the file to get, or <c>null</c> if not known</param>
/// <param name="size">The size of the file to get, or -1 if not known</param>
/// <param name="cancelToken">The cancellation token</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data. Disable for the test/verification flow so damaged files are reported.</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>The downloaded file</returns>
Task<TempFile> GetAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true);
Task<TempFile> GetAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken);
/// <summary>
/// Gets a file from the backend without decrypting it
@@ -166,28 +166,28 @@ internal interface IBackendManager : IDisposable
/// <param name="remotename">The name of the remote volume</param>
/// <param name="hash">The hash of the volume</param>
/// <param name="size">The size of the volume</param>
/// <param name="cancelToken">The cancellation token</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data. Disable for the test/verification flow so damaged files are reported.</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>The downloaded file</returns>
Task<TempFile> GetDirectAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true);
Task<TempFile> GetDirectAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken);
/// <summary>
/// Performs a download of the files specified, with pre-fetch to overlap the download and processing
/// </summary>
/// <param name="volumes">The volumes to download</param>
/// <param name="cancelToken">The cancellation token</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data. Disable for the test/verification flow so damaged files are reported.</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>The downloaded files, hash, size, and name</returns>
IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable<IRemoteVolume> volumes, CancellationToken cancelToken, bool allowParityRepair = true);
IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, CancellationToken cancelToken);
/// <summary>
/// Performs a direct download of the files specified, with pre-fetch to overlap the download and processing
/// </summary>
/// <param name="volumes">The volumes to download</param>
/// <param name="cancelToken">The cancellation token</param>
/// <param name="allowParityRepair">Whether a failed download may be repaired using parity data. Disable for the test/verification flow so damaged files are reported.</param>
/// <param name="cancelToken">The cancellation token</param>
/// <returns>The downloaded files and the volume they came from</returns>
IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(IEnumerable<IRemoteVolume> volumes, CancellationToken cancelToken, bool allowParityRepair = true);
IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, CancellationToken cancelToken);
/// <summary>
/// Flushes the database messages to the database
@@ -194,7 +194,7 @@ namespace Duplicati.Library.Main.Operation
using (var q = await db.CreateBlockQueryHelperAsync(m_result.TaskControl.ProgressToken).ConfigureAwait(false))
{
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(volumesToDownload, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(volumesToDownload, allowParityRepair: true, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
{
using (tmpfile)
{
@@ -146,7 +146,7 @@ namespace Duplicati.Library.Main.Operation
return;
using (new Logging.Timer(LOGTAG, "InsertBaseFiles", "Inserting base files into database"))
using (var tmpfile = await backendManager.GetAsync(baseFile.File.Name, null, baseFile.File.Size, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var tmpfile = await backendManager.GetAsync(baseFile.File.Name, null, baseFile.File.Size, allowParityRepair: true, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var rd = new Volumes.FilesetVolumeReader(RestoreHandler.GetCompressionModule(baseFile.File.Name), tmpfile, m_options))
foreach (var f in rd.Files)
if (FilterExpression.Matches(filter, f.Path))
@@ -158,7 +158,7 @@ namespace Duplicati.Library.Main.Operation
return;
using (new Logging.Timer(LOGTAG, "InsertCompareFiles", "Inserting compare files into database"))
using (var tmpfile = await backendManager.GetAsync(compareFile.File.Name, null, compareFile.File.Size, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var tmpfile = await backendManager.GetAsync(compareFile.File.Name, null, compareFile.File.Size, allowParityRepair: true, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var rd = new Volumes.FilesetVolumeReader(RestoreHandler.GetCompressionModule(compareFile.File.Name), tmpfile, m_options))
foreach (var f in rd.Files)
if (FilterExpression.Matches(filter, f.Path))
@@ -66,7 +66,7 @@ namespace Duplicati.Library.Main.Operation
.ConfigureAwait(false);
var files = new List<Library.Interface.IListResultFile>();
using (var tmpfile = await backendManager.GetAsync(file.Name, entry.Hash, entry.Size < 0 ? file.Size : entry.Size, cancellationToken).ConfigureAwait(false))
using (var tmpfile = await backendManager.GetAsync(file.Name, entry.Hash, entry.Size < 0 ? file.Size : entry.Size, allowParityRepair: true, cancellationToken).ConfigureAwait(false))
using (var tmp = new Volumes.FilesetVolumeReader(RestoreHandler.GetCompressionModule(file.Name), tmpfile, m_options))
foreach (var cf in tmp.ControlFiles)
if (Library.Utility.FilterExpression.Matches(filter, cf.Key))
@@ -160,7 +160,7 @@ namespace Duplicati.Library.Main.Operation
if (!await m_result.TaskControl.ProgressRendevouzAsync().ConfigureAwait(false))
return;
using (var tmpfile = await backendManager.GetAsync(firstEntry.File.Name, null, firstEntry.File.Size, cancellationToken).ConfigureAwait(false))
using (var tmpfile = await backendManager.GetAsync(firstEntry.File.Name, null, firstEntry.File.Size, allowParityRepair: true, cancellationToken).ConfigureAwait(false))
{
VolumeReaderBase.UpdateOptionsFromManifest(RestoreHandler.GetCompressionModule(firstEntry.File.Name), tmpfile, m_options);
using (var rd = new FilesetVolumeReader(RestoreHandler.GetCompressionModule(firstEntry.File.Name), tmpfile, m_options))
@@ -196,7 +196,7 @@ namespace Duplicati.Library.Main.Operation
long flindex = 1;
var filteredListMap = filteredList.ToDictionary(x => x.Value.File.Name, x => x.Value);
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(filteredList.Select(x => new RemoteVolumeMapper(x.Value)), cancellationToken).ConfigureAwait(false))
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(filteredList.Select(x => new RemoteVolumeMapper(x.Value)), allowParityRepair: true, cancellationToken).ConfigureAwait(false))
{
var flentry = filteredListMap[name];
using (tmpfile)
@@ -256,7 +256,7 @@ namespace Duplicati.Library.Main.Operation
{
var list = new List<IListResultFileset>();
var map = filteredList.ToDictionary(x => x.Value.File.Name, x => x);
await foreach (var (file, hash, size, name) in backendManager.GetFilesOverlappedAsync(filteredList.Select(x => new RemoteVolumeMapper(x.Value)), cancelToken).ConfigureAwait(false))
await foreach (var (file, hash, size, name) in backendManager.GetFilesOverlappedAsync(filteredList.Select(x => new RemoteVolumeMapper(x.Value)), allowParityRepair: true, cancelToken).ConfigureAwait(false))
{
// We must obtain the partial/full status from the fileset file in the dlist files.
// Without this, the restore dialog will show all versions as full, or all versions
@@ -237,7 +237,7 @@ namespace Duplicati.Library.Main.Operation
var isFirstFilelist = true;
// At this point, we do not know the hashing used to verify the files, so we need to use direct download, and manually decrypt the files
// so we can calculate the hash AFTER we have read the manifest content and updated the options
await foreach (var (tmpencfile, name) in backendManager.GetFilesOverlappedDirectAsync(filelistWork, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
await foreach (var (tmpencfile, name) in backendManager.GetFilesOverlappedDirectAsync(filelistWork, allowParityRepair: true, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
{
try
{
@@ -364,7 +364,7 @@ namespace Duplicati.Library.Main.Operation
progress = 0;
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(indexfiles, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(indexfiles, allowParityRepair: true, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
{
try
{
@@ -546,7 +546,7 @@ namespace Duplicati.Library.Main.Operation
}
progress = 0;
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(lst, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(lst, allowParityRepair: true, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
{
try
{
@@ -776,7 +776,7 @@ namespace Duplicati.Library.Main.Operation
// Download all required block volumes and extract metadata blocks.
var volumesToDownload = volumeInfo.Values.Cast<IRemoteVolume>().ToList();
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(volumesToDownload, cancellationToken).ConfigureAwait(false))
await foreach (var (tmpfile, hash, size, name) in backendManager.GetFilesOverlappedAsync(volumesToDownload, allowParityRepair: true, cancellationToken).ConfigureAwait(false))
{
using (tmpfile)
{
@@ -265,7 +265,7 @@ namespace Duplicati.Library.Main.Operation
m_result.OperationProgressUpdater.UpdateProgress((float)progress / targetProgess);
KeyValuePair<string, IEnumerable<KeyValuePair<TestEntryStatus, string>>> res;
var (tf, hash, size) = await backendManager.GetWithInfoAsync(n.Name, n.Hash, n.Size, cancellationToken).ConfigureAwait(false);
var (tf, hash, size) = await backendManager.GetWithInfoAsync(n.Name, n.Hash, n.Size, allowParityRepair: true, cancellationToken).ConfigureAwait(false);
using (tf)
res =
await TestHandler.TestVolumeInternalsAsync(testdb, n, tf, m_options, 1, cancellationToken)
@@ -322,7 +322,7 @@ namespace Duplicati.Library.Main.Operation
{
try
{
(var tf, var hash, var size) = await backendManager.GetWithInfoAsync(n.File.Name, null, n.File.Size, cancellationToken).ConfigureAwait(false);
(var tf, var hash, var size) = await backendManager.GetWithInfoAsync(n.File.Name, null, n.File.Size, allowParityRepair: true, cancellationToken).ConfigureAwait(false);
using (tf)
using (var ifr = new IndexVolumeReader(n.CompressionModule, tf, m_options, m_options.BlockhashSize))
{
@@ -479,7 +479,7 @@ namespace Duplicati.Library.Main.Operation
var remoteVolume = await db
.GetRemoteVolumeAsync(volumename, cancellationToken)
.ConfigureAwait(false);
using var tmpfile = await backendManager.GetAsync(remoteVolume.Name, remoteVolume.Hash, remoteVolume.Size, cancellationToken).ConfigureAwait(false);
using var tmpfile = await backendManager.GetAsync(remoteVolume.Name, remoteVolume.Hash, remoteVolume.Size, allowParityRepair: true, cancellationToken).ConfigureAwait(false);
var parsed = VolumeBase.ParseFilename(remoteVolume.Name);
using var stream = new FileStream(tmpfile, FileMode.Open, FileAccess.Read, FileShare.Read);
using var compressor = DynamicLoader.CompressionLoader.GetModule(parsed.CompressionModule, stream, ArchiveMode.Read, m_options.RawOptions);
@@ -1245,7 +1245,7 @@ namespace Duplicati.Library.Main.Operation
await EmitBlockListBlock().ConfigureAwait(false);
//Then we grab all remote volumes that have the missing blocks
await foreach (var (tmpfile, _, _, name) in backendManager.GetFilesOverlappedAsync(await mbl.GetMissingBlockSourcesAsync(cancellationToken).ToListAsync(cancellationToken: cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false))
await foreach (var (tmpfile, _, _, name) in backendManager.GetFilesOverlappedAsync(await mbl.GetMissingBlockSourcesAsync(cancellationToken).ToListAsync(cancellationToken: cancellationToken).ConfigureAwait(false), allowParityRepair: true, cancellationToken).ConfigureAwait(false))
{
try
{
@@ -1357,7 +1357,7 @@ namespace Duplicati.Library.Main.Operation
.GetRemoteVolumeFromFilesetIDAsync(entry.Key, m_result.TaskControl.ProgressToken)
.ConfigureAwait(false);
var parsed = VolumeBase.ParseFilename(volume.Name);
using var tmpfile = await backendManager.GetAsync(volume.Name, volume.Hash, volume.Size, CancellationToken.None).ConfigureAwait(false);
using var tmpfile = await backendManager.GetAsync(volume.Name, volume.Hash, volume.Size, allowParityRepair: true, CancellationToken.None).ConfigureAwait(false);
using var stream = new FileStream(tmpfile, FileMode.Open, FileAccess.Read, FileShare.Read);
using var compressor = DynamicLoader.CompressionLoader.GetModule(parsed.CompressionModule, stream, ArchiveMode.Read, m_options.RawOptions);
if (compressor == null)
@@ -83,7 +83,7 @@ namespace Duplicati.Library.Main.Operation.Restore
.ConfigureAwait(false);
try
{
f = await backend.GetDirectAsync(volume_name, hash, size, results.TaskControl.TransferToken).ConfigureAwait(false);
f = await backend.GetDirectAsync(volume_name, hash, size, allowParityRepair: true, results.TaskControl.TransferToken).ConfigureAwait(false);
}
catch (Exception)
{
@@ -77,7 +77,7 @@ namespace Duplicati.Library.Main.Operation
.ConfigureAwait(false);
var res = new List<string>();
using (var tmpfile = await backendManager.GetAsync(file.Name, entry.Hash, entry.Size < 0 ? file.Size : entry.Size, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var tmpfile = await backendManager.GetAsync(file.Name, entry.Hash, entry.Size < 0 ? file.Size : entry.Size, allowParityRepair: true, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var tmp = new Volumes.FilesetVolumeReader(RestoreHandler.GetCompressionModule(file.Name), tmpfile, m_options))
foreach (var cf in tmp.ControlFiles)
if (FilterExpression.Matches(filter, cf.Key))
@@ -1174,7 +1174,7 @@ namespace Duplicati.Library.Main.Operation
var brokenFiles = new List<string>();
using (new Logging.Timer(LOGTAG, "PatchWithBlocklist", "PatchWithBlocklist"))
await foreach (var (tmpfile, _, _, name) in backendManager.GetFilesOverlappedAsync(volumes, cancellationToken).ConfigureAwait(false))
await foreach (var (tmpfile, _, _, name) in backendManager.GetFilesOverlappedAsync(volumes, allowParityRepair: true, cancellationToken).ConfigureAwait(false))
{
try
{
@@ -87,7 +87,7 @@ namespace Duplicati.Library.Main.Operation
var faultyIndexFiles = new List<IRemoteVolume>();
// Do not repair with parity during verification: a repairable download would
// otherwise mask that the remote copy is actually damaged.
await foreach (var (tf, hash, size, name) in backend.GetFilesOverlappedAsync(files, m_result.TaskControl.ProgressToken, allowParityRepair: false).ConfigureAwait(false))
await foreach (var (tf, hash, size, name) in backend.GetFilesOverlappedAsync(files, allowParityRepair: false, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
{
var vol = new RemoteVolume(name, hash, size);
try
@@ -200,7 +200,7 @@ namespace Duplicati.Library.Main.Operation
Logging.Log.WriteInformationMessage(LOGTAG, "MissingRemoteHash", LC.L("No hash or size recorded for {0}, performing full verification", f.Name));
KeyValuePair<string, IEnumerable<KeyValuePair<TestEntryStatus, string>>> res;
(var tf, var hash, var size) = await backend.GetWithInfoAsync(f.Name, f.Hash, f.Size, m_result.TaskControl.ProgressToken, allowParityRepair: false).ConfigureAwait(false);
(var tf, var hash, var size) = await backend.GetWithInfoAsync(f.Name, f.Hash, f.Size, allowParityRepair: false, m_result.TaskControl.ProgressToken).ConfigureAwait(false);
using (tf)
res = await TestVolumeInternalsAsync(db, f, tf, m_options, 1, m_result.TaskControl.ProgressToken)
@@ -227,7 +227,7 @@ namespace Duplicati.Library.Main.Operation
}
else
{
using (var tf = await backend.GetAsync(f.Name, f.Hash, f.Size, m_result.TaskControl.ProgressToken, allowParityRepair: false).ConfigureAwait(false))
using (var tf = await backend.GetAsync(f.Name, f.Hash, f.Size, allowParityRepair: false, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
{ }
}
@@ -64,11 +64,11 @@ namespace Duplicati.UnitTest
public TempFile DecryptFile(TempFile volume, string volume_name, Options options, bool dispose) => throw new NotImplementedException();
public Task DeleteAsync(string remotename, long size, bool waitForComplete, CancellationToken cancelToken) => throw new NotImplementedException();
public Task<IQuotaInfo?> GetQuotaInfoAsync(CancellationToken cancelToken) => throw new NotImplementedException();
public Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public Task<TempFile> GetAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public Task<TempFile> GetDirectAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public System.Collections.Generic.IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(System.Collections.Generic.IEnumerable<IRemoteVolume> volumes, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public System.Collections.Generic.IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(System.Collections.Generic.IEnumerable<IRemoteVolume> volumes, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public Task<TempFile> GetAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public Task<TempFile> GetDirectAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public System.Collections.Generic.IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(System.Collections.Generic.IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public System.Collections.Generic.IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(System.Collections.Generic.IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public Task FlushPendingMessagesAsync(IBackendManagerDatabase database, CancellationToken cancellationToken) => Task.CompletedTask;
public void UpdateThrottleValues(long maxUploadPrSecond, long maxDownloadPrSecond) => throw new NotImplementedException();
#endregion
+5 -5
View File
@@ -96,11 +96,11 @@ namespace Duplicati.UnitTest
public TempFile DecryptFile(TempFile volume, string volume_name, Options options, bool dispose) => throw new NotImplementedException();
public Task DeleteAsync(string remotename, long size, bool waitForComplete, CancellationToken cancelToken) => throw new NotImplementedException();
public Task<IQuotaInfo?> GetQuotaInfoAsync(CancellationToken cancelToken) => throw new NotImplementedException();
public Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public Task<TempFile> GetAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public Task<TempFile> GetDirectAsync(string remotename, string hash, long size, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable<IRemoteVolume> volumes, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(IEnumerable<IRemoteVolume> volumes, CancellationToken cancelToken, bool allowParityRepair = true) => throw new NotImplementedException();
public Task<(TempFile File, string Hash, long Size)> GetWithInfoAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public Task<TempFile> GetAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public Task<TempFile> GetDirectAsync(string remotename, string hash, long size, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public IAsyncEnumerable<(TempFile File, string Name)> GetFilesOverlappedDirectAsync(IEnumerable<IRemoteVolume> volumes, bool allowParityRepair, CancellationToken cancelToken) => throw new NotImplementedException();
public Task FlushPendingMessagesAsync(IBackendManagerDatabase database, CancellationToken cancellationToken) => Task.CompletedTask;
public void UpdateThrottleValues(long maxUploadPrSecond, long maxDownloadPrSecond) => throw new NotImplementedException();
#endregion