mirror of
https://github.com/kopia/kopia.git
synced 2025-12-23 22:57:50 -05:00
feat(snapshots): Flush after restoring each file (#4825)
Signed-off-by: Lyndon-Li <lyonghui@vmware.com>
This commit is contained in:
@@ -125,6 +125,7 @@ type commandRestore struct {
|
||||
restoreIncremental bool
|
||||
restoreDeleteExtra bool
|
||||
restoreIgnoreErrors bool
|
||||
flushFiles bool
|
||||
restoreShallowAtDepth int32
|
||||
minSizeForPlaceholder int32
|
||||
snapshotTime string
|
||||
@@ -158,6 +159,7 @@ func (c *commandRestore) setup(svc appServices, parent commandParent) {
|
||||
cmd.Flag("shallow", "Shallow restore the directory hierarchy starting at this level (default is to deep restore the entire hierarchy.)").Int32Var(&c.restoreShallowAtDepth)
|
||||
cmd.Flag("shallow-minsize", "When doing a shallow restore, write actual files instead of placeholders smaller than this size.").Int32Var(&c.minSizeForPlaceholder)
|
||||
cmd.Flag("snapshot-time", "When using a path as the source, use the latest snapshot available before this date. Default is latest").Default("latest").StringVar(&c.snapshotTime)
|
||||
cmd.Flag("flush-files", "Specifies whether or not to flush files after restore completes").Default("false").BoolVar(&c.flushFiles)
|
||||
cmd.Action(svc.repositoryReaderAction(c.run))
|
||||
}
|
||||
|
||||
@@ -269,6 +271,7 @@ func (c *commandRestore) restoreOutput(ctx context.Context, rep repo.Repository)
|
||||
SkipPermissions: c.restoreSkipPermissions,
|
||||
SkipTimes: c.restoreSkipTimes,
|
||||
WriteSparseFiles: c.restoreWriteSparseFiles,
|
||||
FlushFiles: c.flushFiles,
|
||||
}
|
||||
|
||||
if err := o.Init(ctx); err != nil {
|
||||
|
||||
@@ -109,6 +109,12 @@ type FilesystemOutput struct {
|
||||
// copier is the StreamCopier to use for copying the actual bit stream to output.
|
||||
// It is assigned at runtime based on the target filesystem and restore options.
|
||||
copier streamCopier `json:"-"`
|
||||
|
||||
// Indicate whether or not flush files after restore.
|
||||
// Varying from OS, the copier may write the file data to the system cache,
|
||||
// so the data may not be written to disk when the restore to the file completes.
|
||||
// This flag guarantees the file data is flushed to disk.
|
||||
FlushFiles bool `json:"flushFiles"`
|
||||
}
|
||||
|
||||
// Init initializes the internal members of the filesystem writer output.
|
||||
@@ -373,7 +379,7 @@ func (o *FilesystemOutput) createDirectory(ctx context.Context, path string) err
|
||||
}
|
||||
}
|
||||
|
||||
func write(targetPath string, r fs.Reader, size int64, c streamCopier) error {
|
||||
func write(targetPath string, r fs.Reader, size int64, flush bool, c streamCopier) error {
|
||||
f, err := os.OpenFile(targetPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600) //nolint:gosec,mnd
|
||||
if err != nil {
|
||||
return err //nolint:wrapcheck
|
||||
@@ -391,6 +397,12 @@ func write(targetPath string, r fs.Reader, size int64, c streamCopier) error {
|
||||
return errors.Wrapf(err, "cannot write data to file %q", f.Name())
|
||||
}
|
||||
|
||||
if flush {
|
||||
if err := f.Sync(); err != nil {
|
||||
return errors.Wrapf(err, "cannot flush file %q", f.Name())
|
||||
}
|
||||
}
|
||||
|
||||
if err := f.Close(); err != nil {
|
||||
return err //nolint:wrapcheck
|
||||
}
|
||||
@@ -430,7 +442,7 @@ func (o *FilesystemOutput) copyFileContent(ctx context.Context, targetPath strin
|
||||
return atomicfile.Write(targetPath, rr)
|
||||
}
|
||||
|
||||
return write(targetPath, rr, f.Size(), o.copier)
|
||||
return write(targetPath, rr, f.Size(), o.FlushFiles, o.copier)
|
||||
}
|
||||
|
||||
func isEmptyDirectory(name string) (bool, error) {
|
||||
|
||||
Reference in New Issue
Block a user