restore: Fix packcache capacity math with failed downloads

Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
This commit is contained in:
Igor Fedorenko 2018-09-12 21:48:58 -04:00 committed by Alexander Neumann
parent e010f3b884
commit 32d5ceba87
2 changed files with 23 additions and 3 deletions

View File

@ -162,14 +162,19 @@ func (c *packCache) get(packID restic.ID, offset int64, length int, load func(of
} }
if pack.data == nil { if pack.data == nil {
releasePack := func() {
delete(c.reservedPacks, pack.id)
c.reservedCapacity -= length
c.allocatedCapacity -= length
}
wr := &bytesWriteSeeker{data: make([]byte, length)} wr := &bytesWriteSeeker{data: make([]byte, length)}
err = load(offset, length, wr) err = load(offset, length, wr)
if err != nil { if err != nil {
releasePack()
return nil, err return nil, err
} }
if wr.pos != length { if wr.pos != length {
delete(c.reservedPacks, pack.id) releasePack()
c.reservedCapacity -= len(pack.data)
return nil, errors.Errorf("invalid read size") return nil, errors.Errorf("invalid read size")
} }
pack.data = wr.data pack.data = wr.data

View File

@ -4,6 +4,7 @@ import (
"io" "io"
"testing" "testing"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test" rtest "github.com/restic/restic/internal/test"
) )
@ -233,20 +234,34 @@ func TestPackCacheDownsizeRecord(t *testing.T) {
rd.Close() rd.Close()
} }
func TestPackCacheWrongLoadSize(t *testing.T) { func TestPackCacheFailedDownload(t *testing.T) {
c := newPackCache(10) 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 { _, 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}) wr.Write([]byte{1})
return nil return nil
}) })
assertNotOK(t, "not enough bytes read", err) assertNotOK(t, "not enough bytes read", err)
assertEmpty()
_, err = c.get(restic.NewRandomID(), 0, 5, func(offset int64, length int, wr io.WriteSeeker) error { _, 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}) wr.Write([]byte{1, 2, 3, 4, 5, 6})
return nil return nil
}) })
assertNotOK(t, "too many bytes read", err) assertNotOK(t, "too many bytes read", err)
assertEmpty()
} }
func TestPackCacheInvalidRequests(t *testing.T) { func TestPackCacheInvalidRequests(t *testing.T) {