operations: add method to real time account server side copy

Before this change server side copies would show at 0% until they were
done then show at 100%.

With support from the backend, server side copies can now be accounted
in real time. This will only work for backends which have been
modified and themselves get feedback about how copies are going.

If the transfer fails, the bytes accounted will be reversed.
This commit is contained in:
Nick Craig-Wood
2026-03-03 14:01:11 +00:00
parent a7a3bee488
commit 307f1edaf4
5 changed files with 204 additions and 2 deletions
+21
View File
@@ -11,6 +11,7 @@ import (
"unicode/utf8"
"github.com/rclone/rclone/fs/rc"
"github.com/rclone/rclone/lib/transferaccounter"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/asyncreader"
@@ -312,6 +313,15 @@ func (acc *Account) serverSideEnd(n int64) {
}
}
// NewServerSideCopyAccounter returns a TransferAccounter for a server
// side copy and a new ctx with it embedded
func (acc *Account) NewServerSideCopyAccounter(ctx context.Context) (context.Context, *transferaccounter.TransferAccounter) {
return transferaccounter.New(ctx, func(n int64) {
acc.stats.AddServerSideCopyBytes(n)
acc.accountReadNoNetwork(n)
})
}
// ServerSideCopyEnd accounts for a read of n bytes in a server-side copy
func (acc *Account) ServerSideCopyEnd(n int64) {
acc.stats.AddServerSideCopy(n)
@@ -363,6 +373,17 @@ func (acc *Account) accountRead(n int) {
acc.limitPerFileBandwidth(n)
}
// Account the read if not using network (eg for server side copies)
func (acc *Account) accountReadNoNetwork(n int64) {
// Update Stats
acc.values.mu.Lock()
acc.values.lpBytes += n
acc.values.bytes += n
acc.values.mu.Unlock()
acc.stats.BytesNoNetwork(n)
}
// read bytes from the io.Reader passed in and account them
func (acc *Account) read(in io.Reader, p []byte) (n int, err error) {
bytesUntilLimit, err := acc.checkReadBefore()