Cache known snapshots instead of re-traversing the repository every time

This commit is contained in:
Matthieu Rakotojaona 2015-07-18 21:49:08 +02:00
parent c9b3eebc09
commit a8cd74ba7e
1 changed files with 26 additions and 14 deletions

View File

@ -75,7 +75,10 @@ func (cmd CmdMount) Execute(args []string) error {
} }
root := fs.Tree{} root := fs.Tree{}
root.Add("snapshots", &snapshots{repo}) root.Add("snapshots", &snapshots{
repo: repo,
knownSnapshots: make(map[string]*restic.Snapshot),
})
cmd.global.Printf("Now serving %s under %s\n", repo.Backend().Location(), mountpoint) cmd.global.Printf("Now serving %s under %s\n", repo.Backend().Location(), mountpoint)
cmd.global.Printf("Don't forget to umount after quitting !\n") cmd.global.Printf("Don't forget to umount after quitting !\n")
@ -96,6 +99,9 @@ var _ = fs.NodeStringLookuper(&snapshots{})
type snapshots struct { type snapshots struct {
repo *repository.Repository repo *repository.Repository
// snapshot timestamp -> snapshot
knownSnapshots map[string]*restic.Snapshot
} }
func (sn *snapshots) Attr(ctx context.Context, a *fuse.Attr) error { func (sn *snapshots) Attr(ctx context.Context, a *fuse.Attr) error {
@ -111,6 +117,7 @@ func (sn *snapshots) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
sn.knownSnapshots[snapshot.Time.Format(time.RFC3339)] = snapshot
ret = append(ret, fuse.Dirent{ ret = append(ret, fuse.Dirent{
Inode: binary.BigEndian.Uint64(id[:8]), Inode: binary.BigEndian.Uint64(id[:8]),
Type: fuse.DT_Dir, Type: fuse.DT_Dir,
@ -122,24 +129,29 @@ func (sn *snapshots) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
} }
func (sn *snapshots) Lookup(ctx context.Context, name string) (fs.Node, error) { func (sn *snapshots) Lookup(ctx context.Context, name string) (fs.Node, error) {
// This is kind of lame: we reload each snapshot and check the name if _, ok := sn.knownSnapshots[name]; !ok {
// (which is the timestamp) // At least this snapshot is not cached. We use this opportunity to
for id := range sn.repo.List(backend.Snapshot, ctx.Done()) { // load all missing snapshots
snapshot, err := restic.LoadSnapshot(sn.repo, id) for id := range sn.repo.List(backend.Snapshot, ctx.Done()) {
if err != nil { snapshot, err := restic.LoadSnapshot(sn.repo, id)
return nil, err
}
if snapshot.Time.Format(time.RFC3339) == name {
tree, err := restic.LoadTree(sn.repo, snapshot.Tree)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &dir{ snapshotName := snapshot.Time.Format(time.RFC3339)
repo: sn.repo, sn.knownSnapshots[snapshotName] = snapshot
tree: tree, break
}, nil
} }
} }
snapshot := sn.knownSnapshots[name]
tree, err := restic.LoadTree(sn.repo, snapshot.Tree)
if err != nil {
return nil, err
}
return &dir{
repo: sn.repo,
tree: tree,
}, nil
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }