diff --git a/internal/cache/backend.go b/internal/cache/backend.go index 824a35753..a58c695f7 100644 --- a/internal/cache/backend.go +++ b/internal/cache/backend.go @@ -40,7 +40,7 @@ func (b *Backend) Remove(ctx context.Context, h restic.Handle) error { return err } - return b.Cache.Remove(h) + return b.Cache.remove(h) } var autoCacheTypes = map[restic.FileType]struct{}{ @@ -77,7 +77,7 @@ func (b *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRea err = b.Cache.Save(h, rd) if err != nil { debug.Log("unable to save %v to cache: %v", h, err) - _ = b.Cache.Remove(h) + _ = b.Cache.remove(h) return nil } @@ -116,7 +116,7 @@ func (b *Backend) cacheFile(ctx context.Context, h restic.Handle) error { }) if err != nil { // try to remove from the cache, ignore errors - _ = b.Cache.Remove(h) + _ = b.Cache.remove(h) } } @@ -134,7 +134,7 @@ func (b *Backend) cacheFile(ctx context.Context, h restic.Handle) error { // loadFromCacheOrDelegate will try to load the file from the cache, and fall // back to the backend if that fails. func (b *Backend) loadFromCacheOrDelegate(ctx context.Context, h restic.Handle, length int, offset int64, consumer func(rd io.Reader) error) error { - rd, err := b.Cache.Load(h, length, offset) + rd, err := b.Cache.load(h, length, offset) if err != nil { debug.Log("error caching %v: %v, falling back to backend", h, err) return b.Backend.Load(ctx, h, length, offset, consumer) @@ -162,7 +162,7 @@ func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset if b.Cache.Has(h) { debug.Log("Load(%v, %v, %v) from cache", h, length, offset) - rd, err := b.Cache.Load(h, length, offset) + rd, err := b.Cache.load(h, length, offset) if err == nil { err = consumer(rd) if err != nil { @@ -216,7 +216,7 @@ func (b *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, e if err != nil { if b.Backend.IsNotExist(err) { // try to remove from the cache, ignore errors - _ = b.Cache.Remove(h) + _ = b.Cache.remove(h) } return fi, err diff --git a/internal/cache/cache.go b/internal/cache/cache.go index 33743c265..07c080b85 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -17,7 +17,7 @@ import ( // Cache manages a local cache. type Cache struct { - Path string + path string Base string Created bool PerformReadahead func(restic.Handle) bool @@ -46,9 +46,6 @@ func readVersion(dir string) (v uint, err error) { const cacheVersion = 1 -// ensure Cache implements restic.Cache -var _ restic.Cache = &Cache{} - var cacheLayoutPaths = map[restic.FileType]string{ restic.PackFile: "data", restic.SnapshotFile: "snapshots", @@ -151,7 +148,7 @@ func New(id string, basedir string) (c *Cache, err error) { } c = &Cache{ - Path: cachedir, + path: cachedir, Base: basedir, Created: created, PerformReadahead: func(restic.Handle) bool { @@ -253,22 +250,6 @@ func IsOld(t time.Time, maxAge time.Duration) bool { return t.Before(oldest) } -// errNoSuchFile is returned when a file is not cached. -type errNoSuchFile struct { - Type string - Name string -} - -func (e errNoSuchFile) Error() string { - return fmt.Sprintf("file %v (%v) is not cached", e.Name, e.Type) -} - -// IsNotExist returns true if the error was caused by a non-existing file. -func (c *Cache) IsNotExist(err error) bool { - _, ok := errors.Cause(err).(errNoSuchFile) - return ok -} - // Wrap returns a backend with a cache. func (c *Cache) Wrap(be restic.Backend) restic.Backend { return newBackend(be, c) diff --git a/internal/cache/file.go b/internal/cache/file.go index 52a767665..7fa8b3dcd 100644 --- a/internal/cache/file.go +++ b/internal/cache/file.go @@ -17,7 +17,7 @@ func (c *Cache) filename(h restic.Handle) string { panic("Name is empty or too short") } subdir := h.Name[:2] - return filepath.Join(c.Path, cacheLayoutPaths[h.Type], subdir, h.Name) + return filepath.Join(c.path, cacheLayoutPaths[h.Type], subdir, h.Name) } func (c *Cache) canBeCached(t restic.FileType) bool { @@ -40,7 +40,7 @@ type readCloser struct { // Load returns a reader that yields the contents of the file with the // given handle. rd must be closed after use. If an error is returned, the // ReadCloser is nil. -func (c *Cache) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, error) { +func (c *Cache) load(h restic.Handle, length int, offset int64) (io.ReadCloser, error) { debug.Log("Load from cache: %v", h) if !c.canBeCached(h.Type) { return nil, errors.New("cannot be cached") @@ -59,13 +59,13 @@ func (c *Cache) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, if fi.Size() <= crypto.Extension { _ = f.Close() - _ = c.Remove(h) + _ = c.remove(h) return nil, errors.Errorf("cached file %v is truncated, removing", h) } if fi.Size() < offset+int64(length) { _ = f.Close() - _ = c.Remove(h) + _ = c.remove(h) return nil, errors.Errorf("cached file %v is too small, removing", h) } @@ -85,7 +85,7 @@ func (c *Cache) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, } // SaveWriter returns a writer for the cache object h. It must be closed after writing is finished. -func (c *Cache) SaveWriter(h restic.Handle) (io.WriteCloser, error) { +func (c *Cache) saveWriter(h restic.Handle) (io.WriteCloser, error) { debug.Log("Save to cache: %v", h) if !c.canBeCached(h.Type) { return nil, errors.New("cannot be cached") @@ -112,7 +112,7 @@ func (c *Cache) Save(h restic.Handle, rd io.Reader) error { return errors.New("Save() called with nil reader") } - f, err := c.SaveWriter(h) + f, err := c.saveWriter(h) if err != nil { return err } @@ -120,19 +120,19 @@ func (c *Cache) Save(h restic.Handle, rd io.Reader) error { n, err := io.Copy(f, rd) if err != nil { _ = f.Close() - _ = c.Remove(h) + _ = c.remove(h) return errors.Wrap(err, "Copy") } if n <= crypto.Extension { _ = f.Close() - _ = c.Remove(h) + _ = c.remove(h) debug.Log("trying to cache truncated file %v, removing", h) return nil } if err = f.Close(); err != nil { - _ = c.Remove(h) + _ = c.remove(h) return errors.Wrap(err, "Close") } @@ -140,7 +140,7 @@ func (c *Cache) Save(h restic.Handle, rd io.Reader) error { } // Remove deletes a file. When the file is not cache, no error is returned. -func (c *Cache) Remove(h restic.Handle) error { +func (c *Cache) remove(h restic.Handle) error { if !c.Has(h) { return nil } @@ -185,7 +185,7 @@ func (c *Cache) list(t restic.FileType) (restic.IDSet, error) { } list := restic.NewIDSet() - dir := filepath.Join(c.Path, cacheLayoutPaths[t]) + dir := filepath.Join(c.path, cacheLayoutPaths[t]) err := filepath.Walk(dir, func(name string, fi os.FileInfo, err error) error { if err != nil { return errors.Wrap(err, "Walk") diff --git a/internal/cache/file_test.go b/internal/cache/file_test.go index 8c2ec2593..32ec6c36f 100644 --- a/internal/cache/file_test.go +++ b/internal/cache/file_test.go @@ -42,13 +42,13 @@ func randomID(s restic.IDSet) restic.ID { } func load(t testing.TB, c *Cache, h restic.Handle) []byte { - rd, err := c.Load(h, 0, 0) + rd, err := c.load(h, 0, 0) if err != nil { t.Fatal(err) } if rd == nil { - t.Fatalf("Load() returned nil reader") + t.Fatalf("load() returned nil reader") } buf, err := ioutil.ReadAll(rd) @@ -148,7 +148,7 @@ func TestFileSaveWriter(t *testing.T) { Name: id.String(), } - wr, err := c.SaveWriter(h) + wr, err := c.saveWriter(h) if err != nil { t.Fatal(err) } @@ -166,7 +166,7 @@ func TestFileSaveWriter(t *testing.T) { t.Fatal(err) } - rd, err := c.Load(h, 0, 0) + rd, err := c.load(h, 0, 0) if err != nil { t.Fatal(err) } @@ -223,7 +223,7 @@ func TestFileLoad(t *testing.T) { for _, test := range tests { t.Run(fmt.Sprintf("%v/%v", test.length, test.offset), func(t *testing.T) { - rd, err := c.Load(h, test.length, test.offset) + rd, err := c.load(h, test.length, test.offset) if err != nil { t.Fatal(err) } diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 905982cba..a5c6e2d61 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -28,7 +28,8 @@ type Repository struct { key *crypto.Key keyName string idx *MasterIndex - restic.Cache + Cache *cache.Cache + noAutoIndexUpdate bool treePM *packerManager @@ -59,7 +60,7 @@ func (r *Repository) Config() restic.Config { } // UseCache replaces the backend with the wrapped cache. -func (r *Repository) UseCache(c restic.Cache) { +func (r *Repository) UseCache(c *cache.Cache) { if c == nil { return } @@ -552,7 +553,7 @@ func (r *Repository) PrepareCache(indexIDs restic.IDSet) error { // use readahead debug.Log("using readahead") - cache := r.Cache.(*cache.Cache) + cache := r.Cache cache.PerformReadahead = func(h restic.Handle) bool { if h.Type != restic.PackFile { debug.Log("no readahead for %v, is not a pack file", h) diff --git a/internal/restic/cache.go b/internal/restic/cache.go deleted file mode 100644 index 56ed060ac..000000000 --- a/internal/restic/cache.go +++ /dev/null @@ -1,37 +0,0 @@ -package restic - -import "io" - -// Cache manages a local cache. -type Cache interface { - // BaseDir returns the base directory of the cache. - BaseDir() string - - // Wrap returns a backend with a cache. - Wrap(Backend) Backend - - // IsNotExist returns true if the error was caused by a non-existing file. - IsNotExist(err error) bool - - // Load returns a reader that yields the contents of the file with the - // given id if it is cached. rd must be closed after use. If an error is - // returned, the ReadCloser is nil. The files are still encrypted - Load(h Handle, length int, offset int64) (io.ReadCloser, error) - - // SaveIndex saves an index in the cache. - Save(Handle, io.Reader) error - - // SaveWriter returns a writer for the to be cached object h. It must be - // closed after writing is finished. - SaveWriter(Handle) (io.WriteCloser, error) - - // Remove deletes a single file from the cache. If it isn't cached, this - // functions must return no error. - Remove(Handle) error - - // Clear removes all files of type t from the cache that are not contained in the set. - Clear(FileType, IDSet) error - - // Has returns true if the file is cached. - Has(Handle) bool -}