2
2
mirror of https://github.com/octoleo/restic.git synced 2024-06-01 16:40:50 +00:00

Merge pull request #4166 from MichaelEischer/cache-mkdirall

cache: Create missing intermediate directories when caching a file
This commit is contained in:
Michael Eischer 2023-04-23 11:44:18 +02:00 committed by GitHub
commit 41cc320145
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 16 deletions

View File

@ -0,0 +1,7 @@
Enhancement: Cancel current command if cache becomes unusable
If the cache directory was removed or ran out of space while restic was
running, this caused further caching attempts to fail and drastically slow down
the command execution. Now, the currently running command is canceled instead.
https://github.com/restic/restic/pull/4166

View File

@ -83,7 +83,7 @@ func (b *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRea
if err != nil { if err != nil {
debug.Log("unable to save %v to cache: %v", h, err) debug.Log("unable to save %v to cache: %v", h, err)
_ = b.Cache.remove(h) _ = b.Cache.remove(h)
return nil return err
} }
return nil return nil
@ -106,20 +106,7 @@ func (b *Backend) cacheFile(ctx context.Context, h restic.Handle) error {
return nil return nil
} }
// test again, maybe the file was cached in the meantime defer func() {
if !b.Cache.Has(h) {
// nope, it's still not in the cache, pull it from the repo and save it
err := b.Backend.Load(ctx, h, 0, 0, func(rd io.Reader) error {
return b.Cache.Save(h, rd)
})
if err != nil {
// try to remove from the cache, ignore errors
_ = b.Cache.remove(h)
}
}
// signal other waiting goroutines that the file may now be cached // signal other waiting goroutines that the file may now be cached
close(finish) close(finish)
@ -127,6 +114,20 @@ func (b *Backend) cacheFile(ctx context.Context, h restic.Handle) error {
b.inProgressMutex.Lock() b.inProgressMutex.Lock()
delete(b.inProgress, h) delete(b.inProgress, h)
b.inProgressMutex.Unlock() b.inProgressMutex.Unlock()
}()
// test again, maybe the file was cached in the meantime
if !b.Cache.Has(h) {
// nope, it's still not in the cache, pull it from the repo and save it
err := b.Backend.Load(ctx, h, 0, 0, func(rd io.Reader) error {
return b.Cache.Save(h, rd)
})
if err != nil {
// try to remove from the cache, ignore errors
_ = b.Cache.remove(h)
}
return err
}
return nil return nil
} }
@ -178,12 +179,14 @@ func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
debug.Log("auto-store %v in the cache", h) debug.Log("auto-store %v in the cache", h)
err = b.cacheFile(ctx, h) err = b.cacheFile(ctx, h)
if err == nil { if err != nil {
return err
}
inCache, err = b.loadFromCache(ctx, h, length, offset, consumer) inCache, err = b.loadFromCache(ctx, h, length, offset, consumer)
if inCache { if inCache {
return err return err
} }
}
debug.Log("error caching %v: %v, falling back to backend", h, err) debug.Log("error caching %v: %v, falling back to backend", h, err)
return b.Backend.Load(ctx, h, length, offset, consumer) return b.Backend.Load(ctx, h, length, offset, consumer)

View File

@ -11,8 +11,10 @@ import (
"time" "time"
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/fs"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/test" "github.com/restic/restic/internal/test"
rtest "github.com/restic/restic/internal/test"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@ -266,3 +268,19 @@ func TestFileSaveConcurrent(t *testing.T) {
saved := load(t, c, h) saved := load(t, c, h)
test.Equals(t, data, saved) test.Equals(t, data, saved)
} }
func TestFileSaveAfterDamage(t *testing.T) {
c := TestNewCache(t)
rtest.OK(t, fs.RemoveAll(c.path))
// save a few bytes of data in the cache
data := test.Random(123456789, 42)
id := restic.Hash(data)
h := restic.Handle{
Type: restic.PackFile,
Name: id.String(),
}
if err := c.Save(h, bytes.NewReader(data)); err == nil {
t.Fatal("Missing error when saving to deleted cache directory")
}
}