diff --git a/Duplicati/Library/Main/Backend/BackendManager.PendingOperation.cs b/Duplicati/Library/Main/Backend/BackendManager.PendingOperation.cs index 4291f2cce..9efd7830b 100644 --- a/Duplicati/Library/Main/Backend/BackendManager.PendingOperation.cs +++ b/Duplicati/Library/Main/Backend/BackendManager.PendingOperation.cs @@ -21,6 +21,7 @@ partial class BackendManager /// The upload throttle manager /// The download throttle manager /// The task reader + /// Whether throttling is disabled /// The options private sealed record ExecuteContext( ProgressHandler ProgressHandler, @@ -29,6 +30,7 @@ partial class BackendManager ThrottleManager UploadThrottleManager, ThrottleManager DownloadThrottleManager, ITaskReader TaskReader, + bool IsThrottleDisabled, Options Options); /// diff --git a/Duplicati/Library/Main/Backend/BackendManager.cs b/Duplicati/Library/Main/Backend/BackendManager.cs index f888cf6f2..072307bfe 100644 --- a/Duplicati/Library/Main/Backend/BackendManager.cs +++ b/Duplicati/Library/Main/Backend/BackendManager.cs @@ -59,14 +59,17 @@ internal partial class BackendManager : IBackendManager if (string.IsNullOrWhiteSpace(backendUrl)) throw new ArgumentNullException(nameof(backendUrl)); + var isThrottleDisabled = options.DisableThrottle || options.ThrottleDisabledBackends.Contains(Library.Utility.Utility.GuessScheme(backendUrl) ?? string.Empty); + // To avoid excessive parameter passing, the context is captured here context = new ExecuteContext( new ProgressHandler(backendWriter, taskReader), backendWriter ?? throw new ArgumentNullException(nameof(backendWriter)), new DatabaseCollector(), - new ThrottleManager() { Limit = options.MaxUploadPrSecond }, - new ThrottleManager() { Limit = options.MaxDownloadPrSecond }, + new ThrottleManager() { Limit = isThrottleDisabled ? 0 : options.MaxUploadPrSecond }, + new ThrottleManager() { Limit = isThrottleDisabled ? 0 : options.MaxDownloadPrSecond }, taskReader ?? throw new ArgumentNullException(nameof(taskReader)), + isThrottleDisabled, options ?? throw new ArgumentNullException(nameof(options)) ); @@ -393,6 +396,9 @@ internal partial class BackendManager : IBackendManager /// The maximum download speed in bytes per second public void UpdateThrottleValues(long maxUploadPrSecond, long maxDownloadPrSecond) { + if (context.IsThrottleDisabled) + return; + context.UploadThrottleManager.Limit = maxUploadPrSecond; context.DownloadThrottleManager.Limit = maxDownloadPrSecond; } diff --git a/Duplicati/Library/Main/Options.cs b/Duplicati/Library/Main/Options.cs index 8628a5320..59c39a852 100644 --- a/Duplicati/Library/Main/Options.cs +++ b/Duplicati/Library/Main/Options.cs @@ -94,6 +94,11 @@ namespace Duplicati.Library.Main /// private const int DEFAULT_ASYNCHRONOUS_CONCURRENT_UPLOAD_LIMIT = 4; + /// + /// The backends where throttling is disabled by default + /// + private const string DEFAULT_THROTTLE_DISABLED_BACKENDS = "file"; + /// /// The default retry delay /// @@ -375,6 +380,8 @@ namespace Duplicati.Library.Main new CommandLineArgument("throttle-upload", CommandLineArgument.ArgumentType.Size, Strings.Options.ThrottleuploadShort, Strings.Options.ThrottleuploadLong, "0kb"), new CommandLineArgument("throttle-download", CommandLineArgument.ArgumentType.Size, Strings.Options.ThrottledownloadShort, Strings.Options.ThrottledownloadLong, "0kb"), + new CommandLineArgument("throttle-disabled", CommandLineArgument.ArgumentType.Boolean, Strings.Options.DisablethrottleShort, Strings.Options.DisablethrottleLong, "false"), + new CommandLineArgument("throttle-disabled-backends", CommandLineArgument.ArgumentType.String, Strings.Options.DisablethrottlebackendsShort, Strings.Options.DisablethrottlebackendsLong("disable-throttle"), DEFAULT_THROTTLE_DISABLED_BACKENDS), new CommandLineArgument("skip-files-larger-than", CommandLineArgument.ArgumentType.Size, Strings.Options.SkipfileslargerthanShort, Strings.Options.SkipfileslargerthanLong), new CommandLineArgument("upload-unchanged-backups", CommandLineArgument.ArgumentType.Boolean, Strings.Options.UploadUnchangedBackupsShort, Strings.Options.UploadUnchangedBackupsLong, "false"), @@ -871,6 +878,17 @@ namespace Duplicati.Library.Main } } + /// + /// A value indicating if the throttling is disabled + /// + public bool DisableThrottle => GetBool("throttle-disabled"); + + /// + /// The backends where the throttling is disabled + /// + public HashSet ThrottleDisabledBackends + => GetString("throttle-disabled-backends", DEFAULT_THROTTLE_DISABLED_BACKENDS)?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)?.ToHashSet(StringComparer.OrdinalIgnoreCase) ?? new HashSet(); + /// /// A value indicating if the backup is a full backup /// diff --git a/Duplicati/Library/Main/Strings.cs b/Duplicati/Library/Main/Strings.cs index bed53542e..8b29d3dca 100644 --- a/Duplicati/Library/Main/Strings.cs +++ b/Duplicati/Library/Main/Strings.cs @@ -59,6 +59,10 @@ namespace Duplicati.Library.Main.Strings public static string ThrottledownloadShort { get { return LC.L(@"Max number of kilobytes to download pr. second"); } } public static string ThrottleuploadLong { get { return LC.L(@"By setting this value you can limit how much bandwidth Duplicati consumes for uploads. Setting this limit can make the backups take longer, but will make Duplicati less intrusive."); } } public static string ThrottleuploadShort { get { return LC.L(@"Max number of kilobytes to upload pr. second"); } } + public static string DisablethrottleLong { get { return LC.L(@"Disable the throttling of upload and download speeds for this task. If there is a throttle set, it will be ignored when running this task."); } } + public static string DisablethrottleShort { get { return LC.L(@"Disable throttling"); } } + public static string DisablethrottlebackendsLong(string option) { return LC.L(@"Disable the throttling of upload and download speeds for specific backends. If there is a throttle set, it will be ignore when running this task, if the backend is one of the specified backends. Multiple backends can be specified with a comma separator. This option has no effect if there is no throttle or if --{0} is set", option); } + public static string DisablethrottlebackendsShort { get { return LC.L(@"Disable throttling for specific backends"); } } public static string NoencryptionLong { get { return LC.L(@"If you store the backups on a local disk, and prefer that they are kept unencrypted, you can turn of encryption completely by using this switch."); } } public static string NoencryptionShort { get { return LC.L(@"Disable encryption"); } } public static string NumberofretriesLong { get { return LC.L(@"If an upload or download fails, Duplicati will retry a number of times before failing. Use this to handle unstable network connections better."); } }