mirror of
https://github.com/restic/restic.git
synced 2025-12-03 20:51:47 +00:00
restorer: Optimize empty file restore
don't create fileInfo structs for empty files. this saves memory. this also avoids extra serial scan of all fileInfo, which should make restore faster and more consistent. Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
This commit is contained in:
committed by
Alexander Neumann
parent
c2bcb764cd
commit
bda8d7722e
@@ -175,6 +175,19 @@ func (res *Restorer) restoreHardlinkAt(node *restic.Node, target, path, location
|
||||
return res.restoreNodeMetadataTo(node, path, location)
|
||||
}
|
||||
|
||||
func (res *Restorer) restoreEmptyFileAt(node *restic.Node, target, location string) error {
|
||||
wr, err := os.OpenFile(target, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = wr.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return res.restoreNodeMetadataTo(node, target, location)
|
||||
}
|
||||
|
||||
// RestoreTo creates the directories and files in the snapshot below dst.
|
||||
// Before an item is created, res.Filter is called.
|
||||
func (res *Restorer) RestoreTo(ctx context.Context, dst string) error {
|
||||
@@ -215,6 +228,10 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if node.Size == 0 {
|
||||
return nil // deal with empty files later
|
||||
}
|
||||
|
||||
if node.Links > 1 {
|
||||
if idx.Has(node.Inode, node.DeviceID) {
|
||||
return nil
|
||||
@@ -241,14 +258,22 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error {
|
||||
return res.traverseTree(ctx, dst, string(filepath.Separator), *res.sn.Tree, treeVisitor{
|
||||
enterDir: noop,
|
||||
visitNode: func(node *restic.Node, target, location string) error {
|
||||
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 node.Type != "file" {
|
||||
return res.restoreNodeTo(ctx, node, target, location)
|
||||
}
|
||||
|
||||
// create empty files, but not hardlinks to empty files
|
||||
if node.Size == 0 && (node.Links < 2 || !idx.Has(node.Inode, node.DeviceID)) {
|
||||
if node.Links > 1 {
|
||||
idx.Add(node.Inode, node.DeviceID, location)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
return res.restoreNodeMetadataTo(node, target, location)
|
||||
},
|
||||
leaveDir: restoreNodeMetadata,
|
||||
|
||||
Reference in New Issue
Block a user