In code the throttling generally works backwards than what one would expect.
The streams that are throttled are the streams that operate on files from the local machine.
This fixes the download throttling not working and the upload throttling applying to
both uploads and downloads.
When doing a Put operation the stream on the local machine is reading from the
local filesystem and hence the upload throttle bytes per second needs to be
applied to the reading of the stream, not the writing.
Similarly when doing a Get operation the download throttle bytes per second needs
to be applied to the writing of the stream.
Fixes#4115
According to the current implementation, the progress bar does not advance
when files are skipped by FilePreFilterProcess. This causes users'
confusion since the web frontend will get stuck at a certain stage for a
long time. This commit addresses this issue.
Changed AddBackendEvent() in ResultClasses to allow the option to not update
the backend progress. This allows the BackendUploader to log the act of starting
an upload without changing the backend progress. The backend progress is now
handled by a new class, FileProgressThrottler, which will determine the transfer
rate of all uploads currently in progress.
This class also handles throttling the upload streams. The algorithm will try
to decrease or increase the streams throttle rates as appropriate by changing
the value based on the over/under amount or based on a percentage to prevent
throttling one stream directly to zero.
Encrypting, hashing, and creating index volumes are now done
in the DataBlockProcessor and the SpillCollectorProcess. This allows
uploads to always be transferring data and not have to stop to create
a file, encrypt data, etc.
When the code following the await can be executed on any thread, it's
recommended to use ConfigureAwait(false) to avoid unnecessary context
switching and potential deadlocks.
This simplifies things and speeds up database query queuing, at the expense of not guaranteeing that the same thread will access the database, but just guaranteeing single threaded database access.
A method marked async that does not use await will run synchronously.
By removing the async modifiers, we make it more explicit that these are
synchronous methods. This also addresses some compiler warnings, and
avoids the creation of the state machine used to handle asynchronous
operations.
When the code following the await can be executed on any thread, it's
recommended to use ConfigureAwait(false) to avoid unnecessary context
switching and potential deadlocks.
Changed a few things on the way, removing the log process
# Conflicts:
# Duplicati/Library/Main/Controller.cs
# Duplicati/Library/Main/Database/ExtensionMethods.cs
# Duplicati/Library/Main/Database/LocalBackupDatabase.cs
# Duplicati/Library/Main/Duplicati.Library.Main.csproj
# Duplicati/Library/Main/Operation/BackupHandler.cs
# Duplicati/Library/Main/Operation/FilelistProcessor.cs
# Duplicati/Library/Main/Operation/PurgeBrokenFilesHandler.cs
# Duplicati/Library/Main/Operation/TestFilterHandler.cs
# Duplicati/Library/Main/Options.cs
# Duplicati/Library/Main/ResultClasses.cs
# Duplicati/UnitTest/BasicSetupHelper.cs