From 32d5ceba87fcd105f20d43bb39a1b606c15db2ae Mon Sep 17 00:00:00 2001 From: Igor Fedorenko Date: Wed, 12 Sep 2018 21:48:58 -0400 Subject: [PATCH] restore: Fix packcache capacity math with failed downloads Signed-off-by: Igor Fedorenko --- internal/restorer/packcache.go | 9 +++++++-- internal/restorer/packcache_test.go | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/internal/restorer/packcache.go b/internal/restorer/packcache.go index a40c44482..1eaad63bf 100644 --- a/internal/restorer/packcache.go +++ b/internal/restorer/packcache.go @@ -162,14 +162,19 @@ func (c *packCache) get(packID restic.ID, offset int64, length int, load func(of } if pack.data == nil { + releasePack := func() { + delete(c.reservedPacks, pack.id) + c.reservedCapacity -= length + c.allocatedCapacity -= length + } wr := &bytesWriteSeeker{data: make([]byte, length)} err = load(offset, length, wr) if err != nil { + releasePack() return nil, err } if wr.pos != length { - delete(c.reservedPacks, pack.id) - c.reservedCapacity -= len(pack.data) + releasePack() return nil, errors.Errorf("invalid read size") } pack.data = wr.data diff --git a/internal/restorer/packcache_test.go b/internal/restorer/packcache_test.go index 05a9eca2b..3a5f18cf5 100644 --- a/internal/restorer/packcache_test.go +++ b/internal/restorer/packcache_test.go @@ -4,6 +4,7 @@ import ( "io" "testing" + "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/restic" rtest "github.com/restic/restic/internal/test" ) @@ -233,20 +234,34 @@ func TestPackCacheDownsizeRecord(t *testing.T) { rd.Close() } -func TestPackCacheWrongLoadSize(t *testing.T) { +func TestPackCacheFailedDownload(t *testing.T) { c := newPackCache(10) + assertEmpty := func() { + rtest.Equals(t, 0, len(c.cachedPacks)) + rtest.Equals(t, 10, c.capacity) + rtest.Equals(t, 0, c.reservedCapacity) + rtest.Equals(t, 0, c.allocatedCapacity) + } _, err := c.get(restic.NewRandomID(), 0, 5, func(offset int64, length int, wr io.WriteSeeker) error { + return errors.Errorf("expected induced test error") + }) + assertNotOK(t, "not enough bytes read", err) + assertEmpty() + + _, err = c.get(restic.NewRandomID(), 0, 5, func(offset int64, length int, wr io.WriteSeeker) error { wr.Write([]byte{1}) return nil }) assertNotOK(t, "not enough bytes read", err) + assertEmpty() _, err = c.get(restic.NewRandomID(), 0, 5, func(offset int64, length int, wr io.WriteSeeker) error { wr.Write([]byte{1, 2, 3, 4, 5, 6}) return nil }) assertNotOK(t, "too many bytes read", err) + assertEmpty() } func TestPackCacheInvalidRequests(t *testing.T) {