From a8fdcf79b7caae3d80a0ae03307b42264e78b00a Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 1 Oct 2023 23:24:42 +0200 Subject: [PATCH] restorer: Make hardlink index generic This will allow reusing it for the stats command without regressing the memory usage due to storing an unnecessary file path. --- internal/restorer/hardlinks_index.go | 22 +++++++++++----------- internal/restorer/hardlinks_index_test.go | 6 +++--- internal/restorer/restorer.go | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/internal/restorer/hardlinks_index.go b/internal/restorer/hardlinks_index.go index 9cf45975a..208a38ad0 100644 --- a/internal/restorer/hardlinks_index.go +++ b/internal/restorer/hardlinks_index.go @@ -10,20 +10,20 @@ type HardlinkKey struct { } // HardlinkIndex contains a list of inodes, devices these inodes are one, and associated file names. -type HardlinkIndex struct { +type HardlinkIndex[T any] struct { m sync.Mutex - Index map[HardlinkKey]string + Index map[HardlinkKey]T } // NewHardlinkIndex create a new index for hard links -func NewHardlinkIndex() *HardlinkIndex { - return &HardlinkIndex{ - Index: make(map[HardlinkKey]string), +func NewHardlinkIndex[T any]() *HardlinkIndex[T] { + return &HardlinkIndex[T]{ + Index: make(map[HardlinkKey]T), } } // Has checks wether the link already exist in the index. -func (idx *HardlinkIndex) Has(inode uint64, device uint64) bool { +func (idx *HardlinkIndex[T]) Has(inode uint64, device uint64) bool { idx.m.Lock() defer idx.m.Unlock() _, ok := idx.Index[HardlinkKey{inode, device}] @@ -32,25 +32,25 @@ func (idx *HardlinkIndex) Has(inode uint64, device uint64) bool { } // Add adds a link to the index. -func (idx *HardlinkIndex) Add(inode uint64, device uint64, name string) { +func (idx *HardlinkIndex[T]) Add(inode uint64, device uint64, value T) { idx.m.Lock() defer idx.m.Unlock() _, ok := idx.Index[HardlinkKey{inode, device}] if !ok { - idx.Index[HardlinkKey{inode, device}] = name + idx.Index[HardlinkKey{inode, device}] = value } } -// GetFilename obtains the filename from the index. -func (idx *HardlinkIndex) GetFilename(inode uint64, device uint64) string { +// Value obtains the filename from the index. +func (idx *HardlinkIndex[T]) Value(inode uint64, device uint64) T { idx.m.Lock() defer idx.m.Unlock() return idx.Index[HardlinkKey{inode, device}] } // Remove removes a link from the index. -func (idx *HardlinkIndex) Remove(inode uint64, device uint64) { +func (idx *HardlinkIndex[T]) Remove(inode uint64, device uint64) { idx.m.Lock() defer idx.m.Unlock() delete(idx.Index, HardlinkKey{inode, device}) diff --git a/internal/restorer/hardlinks_index_test.go b/internal/restorer/hardlinks_index_test.go index 75a2b83ee..31ce938f9 100644 --- a/internal/restorer/hardlinks_index_test.go +++ b/internal/restorer/hardlinks_index_test.go @@ -10,15 +10,15 @@ import ( // TestHardLinks contains various tests for HardlinkIndex. func TestHardLinks(t *testing.T) { - idx := restorer.NewHardlinkIndex() + idx := restorer.NewHardlinkIndex[string]() idx.Add(1, 2, "inode1-file1-on-device2") idx.Add(2, 3, "inode2-file2-on-device3") - sresult := idx.GetFilename(1, 2) + sresult := idx.Value(1, 2) rtest.Equals(t, sresult, "inode1-file1-on-device2") - sresult = idx.GetFilename(2, 3) + sresult = idx.Value(2, 3) rtest.Equals(t, sresult, "inode2-file2-on-device3") bresult := idx.Has(1, 2) diff --git a/internal/restorer/restorer.go b/internal/restorer/restorer.go index 3c60aca1b..e973316c0 100644 --- a/internal/restorer/restorer.go +++ b/internal/restorer/restorer.go @@ -230,7 +230,7 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error { } } - idx := NewHardlinkIndex() + idx := NewHardlinkIndex[string]() filerestorer := newFileRestorer(dst, res.repo.Backend().Load, res.repo.Key(), res.repo.Index().Lookup, res.repo.Connections(), res.sparse, res.progress) filerestorer.Error = res.Error @@ -319,8 +319,8 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error { return res.restoreEmptyFileAt(node, target, location) } - if idx.Has(node.Inode, node.DeviceID) && idx.GetFilename(node.Inode, node.DeviceID) != location { - return res.restoreHardlinkAt(node, filerestorer.targetPath(idx.GetFilename(node.Inode, node.DeviceID)), target, location) + if idx.Has(node.Inode, node.DeviceID) && idx.Value(node.Inode, node.DeviceID) != location { + return res.restoreHardlinkAt(node, filerestorer.targetPath(idx.Value(node.Inode, node.DeviceID)), target, location) } return res.restoreNodeMetadataTo(node, target, location)