forked from TrueCloudLab/restic
cache: Drop cache entry if it cannot be processed
Failing to process data requested from the cache usually indicates a problem with the returned data. Assume that the cache entry is somehow damaged and retry downloading it once.
This commit is contained in:
parent
aa3b1925b4
commit
34c1a83340
2 changed files with 41 additions and 1 deletions
7
internal/cache/backend.go
vendored
7
internal/cache/backend.go
vendored
|
@ -161,7 +161,12 @@ func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
|
|||
// try loading from cache without checking that the handle is actually cached
|
||||
inCache, err := b.loadFromCache(ctx, h, length, offset, consumer)
|
||||
if inCache {
|
||||
return err
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// drop from cache and retry once
|
||||
_ = b.Cache.remove(h)
|
||||
}
|
||||
debug.Log("error loading %v from cache: %v", h, err)
|
||||
|
||||
|
|
35
internal/cache/backend_test.go
vendored
35
internal/cache/backend_test.go
vendored
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
|
@ -171,3 +172,37 @@ func TestErrorBackend(t *testing.T) {
|
|||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestBackendRemoveBroken(t *testing.T) {
|
||||
be := mem.New()
|
||||
|
||||
c, cleanup := TestNewCache(t)
|
||||
defer cleanup()
|
||||
|
||||
h, data := randomData(5234142)
|
||||
// save directly in backend
|
||||
save(t, be, h, data)
|
||||
|
||||
// prime cache with broken copy
|
||||
broken := append([]byte{}, data...)
|
||||
broken[0] ^= 0xff
|
||||
err := c.Save(h, bytes.NewReader(broken))
|
||||
test.OK(t, err)
|
||||
|
||||
// loadall retries if broken data was returned
|
||||
buf, err := backend.LoadAll(context.TODO(), nil, c.Wrap(be), h)
|
||||
test.OK(t, err)
|
||||
|
||||
if !bytes.Equal(buf, data) {
|
||||
t.Fatalf("wrong data returned")
|
||||
}
|
||||
|
||||
// check that the cache now contains the correct data
|
||||
rd, err := c.load(h, 0, 0)
|
||||
test.OK(t, err)
|
||||
cached, err := ioutil.ReadAll(rd)
|
||||
test.OK(t, err)
|
||||
if !bytes.Equal(cached, data) {
|
||||
t.Fatalf("wrong data cache")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue