repository: don't hang when copying using a single connection

This commit is contained in:
Michael Eischer 2022-08-28 11:40:31 +02:00
parent 1b233c4e2e
commit b03277ead5
3 changed files with 24 additions and 1 deletions

View file

@ -0,0 +1,7 @@
Bugfix: Fix stuck `copy` command when setting backend connections to 1
When calling the copy command using `copy -o <backend>.connections=1` this
caused the command to be stuck permanently. This has been fixed.
https://github.com/restic/restic/issues/3897
https://github.com/restic/restic/pull/3898

View file

@ -114,6 +114,10 @@ func repack(ctx context.Context, repo restic.Repository, dstRepo restic.Reposito
// as packs are streamed the concurrency is limited by IO // as packs are streamed the concurrency is limited by IO
// reduce by one to ensure that uploading is always possible // reduce by one to ensure that uploading is always possible
repackWorkerCount := int(repo.Connections() - 1) repackWorkerCount := int(repo.Connections() - 1)
if repo != dstRepo {
// no need to share the upload and download connections for different repositories
repackWorkerCount = int(repo.Connections())
}
for i := 0; i < repackWorkerCount; i++ { for i := 0; i < repackWorkerCount; i++ {
wg.Go(worker) wg.Go(worker)
} }

View file

@ -292,12 +292,24 @@ func TestRepackCopy(t *testing.T) {
repository.TestAllVersions(t, testRepackCopy) repository.TestAllVersions(t, testRepackCopy)
} }
type oneConnectionRepo struct {
restic.Repository
}
func (r oneConnectionRepo) Connections() uint {
return 1
}
func testRepackCopy(t *testing.T, version uint) { func testRepackCopy(t *testing.T, version uint) {
repo, cleanup := repository.TestRepositoryWithVersion(t, version) repo, cleanup := repository.TestRepositoryWithVersion(t, version)
defer cleanup() defer cleanup()
dstRepo, dstCleanup := repository.TestRepositoryWithVersion(t, version) dstRepo, dstCleanup := repository.TestRepositoryWithVersion(t, version)
defer dstCleanup() defer dstCleanup()
// test with minimal possible connection count
repoWrapped := &oneConnectionRepo{repo}
dstRepoWrapped := &oneConnectionRepo{dstRepo}
seed := time.Now().UnixNano() seed := time.Now().UnixNano()
rand.Seed(seed) rand.Seed(seed)
t.Logf("rand seed is %v", seed) t.Logf("rand seed is %v", seed)
@ -308,7 +320,7 @@ func testRepackCopy(t *testing.T, version uint) {
_, keepBlobs := selectBlobs(t, repo, 0.2) _, keepBlobs := selectBlobs(t, repo, 0.2)
copyPacks := findPacksForBlobs(t, repo, keepBlobs) copyPacks := findPacksForBlobs(t, repo, keepBlobs)
_, err := repository.Repack(context.TODO(), repo, dstRepo, copyPacks, keepBlobs, nil) _, err := repository.Repack(context.TODO(), repoWrapped, dstRepoWrapped, copyPacks, keepBlobs, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }