accounting: fix totalBytes counting server-side copies and moves twice

When a server-side copy or move finished without reporting progress
along the way, its bytes were added to the stats but not to the
transfer, so until the transfer ended core/stats reported totalBytes as
the bytes done plus the whole size of the transfer still in progress.
A 1 GiB server-side copy on the local backend showed 1 GiB of 2 GiB
while rclone checked the hashes.

The bytes now go on the transfer as well, as they already did for
backends which report progress through NewServerSideCopyAccounter.
This commit is contained in:
ilya lavrenov authored and Nick Craig-Wood committed 2026-10-31 13:17:30 +00:00
1 parent 941f6a7217
commit b44c24cfca
2 files changed
+32 -2

No files matched your search

+3 -2
View File
@@ -307,9 +307,10 @@ func (acc *Account) ServerSideTransferEnd(n int64) {
// serverSideEnd accounts for non specific server-side data
func (acc *Account) serverSideEnd(n int64) {
// Account for bytes unless we are checking
// Account for bytes unless we are checking. The transfer needs
// them as well as the stats or totalBytes counts them twice.
if !acc.checking {
acc.stats.BytesNoNetwork(n)
acc.accountReadNoNetwork(n)
}
}
+29
View File
@@ -256,6 +256,35 @@ func TestAccountAccounter(t *testing.T) {
}
func TestAccountServerSideEnd(t *testing.T) {
for _, test := range []struct {
name string
end func(acc *Account, n int64)
}{
{"Copy", (*Account).ServerSideCopyEnd},
{"Move", (*Account).ServerSideMoveEnd},
} {
t.Run(test.name, func(t *testing.T) {
ctx := context.Background()
stats := NewStats(ctx)
tr := stats.NewTransferRemoteSize("file", 100, nil, nil)
acc := tr.Account(ctx, nil)
acc.ServerSideTransferStart()
test.end(acc, 100)
bytes, size := acc.progress()
assert.Equal(t, int64(100), bytes)
assert.Equal(t, int64(100), size)
assert.Equal(t, int64(100), stats.GetBytes())
// Counted once while the transfer is still in progress
assert.Equal(t, int64(100), stats.calculateTransferStats().totalBytes)
tr.Done(ctx, nil)
assert.Equal(t, int64(100), stats.calculateTransferStats().totalBytes)
})
}
}
func TestAccountMaxTransfer(t *testing.T) {
ctx := context.Background()
ci := fs.GetConfig(ctx)