mirror of
https://github.com/octoleo/restic.git
synced 2024-11-30 00:33:57 +00:00
cache: Allow proactive caching of tree packs
This commit adds a function to the cache which can decide to proactively load the complete pack file and store it in the cache. This is helpful for pack files containing only tree blobs, as it is likely that the same file is accessed again in the future.
This commit is contained in:
parent
5436154f0d
commit
e1dfaf5d87
62
internal/cache/backend.go
vendored
62
internal/cache/backend.go
vendored
@ -82,6 +82,25 @@ var autoCacheFiles = map[restic.FileType]bool{
|
|||||||
restic.SnapshotFile: true,
|
restic.SnapshotFile: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Backend) cacheFile(ctx context.Context, h restic.Handle) error {
|
||||||
|
rd, err := b.Backend.Load(ctx, h, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = b.Cache.Save(h, rd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = rd.Close(); err != nil {
|
||||||
|
// try to remove from the cache, ignore errors
|
||||||
|
_ = b.Cache.Remove(h)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Load loads a file from the cache or the backend.
|
// Load loads a file from the cache or the backend.
|
||||||
func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
|
func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
|
||||||
if b.Cache.Has(h) {
|
if b.Cache.Has(h) {
|
||||||
@ -91,41 +110,38 @@ func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
|
|||||||
|
|
||||||
// partial file requested
|
// partial file requested
|
||||||
if offset != 0 || length != 0 {
|
if offset != 0 || length != 0 {
|
||||||
|
if b.Cache.PerformReadahead(h) {
|
||||||
|
debug.Log("performing readahead for %v", h)
|
||||||
|
err := b.cacheFile(ctx, h)
|
||||||
|
if err == nil {
|
||||||
|
return b.Cache.Load(h, length, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.Log("error caching %v: %v", h, err)
|
||||||
|
}
|
||||||
|
|
||||||
debug.Log("Load(%v, %v, %v): partial file requested, delegating to backend", h, length, offset)
|
debug.Log("Load(%v, %v, %v): partial file requested, delegating to backend", h, length, offset)
|
||||||
return b.Backend.Load(ctx, h, length, offset)
|
return b.Backend.Load(ctx, h, length, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
rd, err := b.Backend.Load(ctx, h, length, offset)
|
// if we don't automatically cache this file type, fall back to the backend
|
||||||
if err != nil {
|
|
||||||
if b.Backend.IsNotExist(err) {
|
|
||||||
// try to remove from the cache, ignore errors
|
|
||||||
_ = b.Cache.Remove(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := autoCacheFiles[h.Type]; !ok {
|
if _, ok := autoCacheFiles[h.Type]; !ok {
|
||||||
return rd, nil
|
debug.Log("Load(%v, %v, %v): delegating to backend", h, length, offset)
|
||||||
|
return b.Backend.Load(ctx, h, length, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log("auto-store %v in the cache", h)
|
debug.Log("auto-store %v in the cache", h)
|
||||||
|
err := b.cacheFile(ctx, h)
|
||||||
|
|
||||||
// cache the file, then return cached copy
|
if err == nil {
|
||||||
if err = b.Cache.Save(h, rd); err != nil {
|
// load the cached version
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = rd.Close(); err != nil {
|
|
||||||
// try to remove from the cache, ignore errors
|
|
||||||
_ = b.Cache.Remove(h)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// load from the cache and save in the backend
|
|
||||||
return b.Cache.Load(h, 0, 0)
|
return b.Cache.Load(h, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug.Log("error caching %v: %v, falling back to backend", h, err)
|
||||||
|
return b.Backend.Load(ctx, h, length, offset)
|
||||||
|
}
|
||||||
|
|
||||||
// Stat tests whether the backend has a file. If it does not exist but still
|
// Stat tests whether the backend has a file. If it does not exist but still
|
||||||
// exists in the cache, it is removed from the cache.
|
// exists in the cache, it is removed from the cache.
|
||||||
func (b *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
|
func (b *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user