2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-23 11:28:54 +00:00

fuse: correctly handle snapshots

The fuse code kept adding snapshots to the top-level dir "snapshots". In
addition, snapshots with the same timestamp (same second) were not added
correctly, they will now be suffixed by an incrementing counter, e.g.:

    dr-xr-xr-x 1 fd0 users 0 Sep 18 15:01 2016-09-18T15:01:44+02:00
    dr-xr-xr-x 1 fd0 users 0 Sep 18 15:01 2016-09-18T15:01:48+02:00
    dr-xr-xr-x 1 fd0 users 0 Sep 18 15:01 2016-09-18T15:01:48+02:00-1

Closes #624
This commit is contained in:
Alexander Neumann 2016-09-18 15:03:14 +02:00
parent c5763e59d5
commit 5494c1858e

View File

@ -36,6 +36,7 @@ type SnapshotsDir struct {
// knownSnapshots maps snapshot timestamp to the snapshot
sync.RWMutex
knownSnapshots map[string]SnapshotWithId
processed restic.IDSet
}
// NewSnapshotsDir returns a new dir object for the snapshots.
@ -45,6 +46,7 @@ func NewSnapshotsDir(repo restic.Repository, ownerIsRoot bool) *SnapshotsDir {
repo: repo,
knownSnapshots: make(map[string]SnapshotWithId),
ownerIsRoot: ownerIsRoot,
processed: restic.NewIDSet(),
}
}
@ -66,6 +68,11 @@ func (sn *SnapshotsDir) updateCache(ctx context.Context) error {
defer sn.Unlock()
for id := range sn.repo.List(restic.SnapshotFile, ctx.Done()) {
if sn.processed.Has(id) {
debug.Log("SnapshotsDir.List", "skipping snapshot %v, already in list", id.Str())
continue
}
debug.Log("SnapshotsDir.List", "found snapshot id %v", id.Str())
snapshot, err := restic.LoadSnapshot(sn.repo, id)
if err != nil {
@ -73,7 +80,6 @@ func (sn *SnapshotsDir) updateCache(ctx context.Context) error {
}
timestamp := snapshot.Time.Format(time.RFC3339)
for i := 1; ; i++ {
if _, ok := sn.knownSnapshots[timestamp]; !ok {
break
@ -84,6 +90,7 @@ func (sn *SnapshotsDir) updateCache(ctx context.Context) error {
debug.Log("SnapshotsDir.List", " add %v as dir %v", id.Str(), timestamp)
sn.knownSnapshots[timestamp] = SnapshotWithId{snapshot, id}
sn.processed.Insert(id)
}
return nil
}
@ -107,11 +114,11 @@ func (sn *SnapshotsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
defer sn.RUnlock()
ret := make([]fuse.Dirent, 0)
for _, snapshot := range sn.knownSnapshots {
for timestamp, snapshot := range sn.knownSnapshots {
ret = append(ret, fuse.Dirent{
Inode: inodeFromBackendID(snapshot.ID),
Type: fuse.DT_Dir,
Name: snapshot.Time.Format(time.RFC3339),
Name: timestamp,
})
}
@ -120,20 +127,20 @@ func (sn *SnapshotsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
}
func (sn *SnapshotsDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
debug.Log("SnapshotsDir.updateCache", "Lookup(%s)", name)
debug.Log("SnapshotsDir.Lookup", "Lookup(%s)", name)
snapshot, ok := sn.get(name)
if !ok {
// We don't know about it, update the cache
err := sn.updateCache(ctx)
if err != nil {
debug.Log("SnapshotsDir.updateCache", " Lookup(%s) -> err %v", name, err)
debug.Log("SnapshotsDir.Lookup", " Lookup(%s) -> err %v", name, err)
return nil, err
}
snapshot, ok = sn.get(name)
if !ok {
// We still don't know about it, this time it really doesn't exist
debug.Log("SnapshotsDir.updateCache", " Lookup(%s) -> not found", name)
debug.Log("SnapshotsDir.Lookup", " Lookup(%s) -> not found", name)
return nil, fuse.ENOENT
}
}