forked from TrueCloudLab/restic
backup: hide files from status which are read completely but not saved
As the FileSaver is asynchronously waiting for all blobs of a file to be stored, the number of active files is higher than the number of files from which restic is reading concurrently. Thus to not confuse users, only display files in the status from which restic is currently reading.
This commit is contained in:
parent
a571fc4aa1
commit
c0f34af9db
4 changed files with 50 additions and 20 deletions
|
@ -68,6 +68,9 @@ type Archiver struct {
|
||||||
// be in the snapshot after saving. s contains some statistics about this
|
// be in the snapshot after saving. s contains some statistics about this
|
||||||
// particular file/dir.
|
// particular file/dir.
|
||||||
//
|
//
|
||||||
|
// Once reading a file has completed successfully (but not saving it yet),
|
||||||
|
// CompleteItem will be called with current == nil.
|
||||||
|
//
|
||||||
// CompleteItem may be called asynchronously from several different
|
// CompleteItem may be called asynchronously from several different
|
||||||
// goroutines!
|
// goroutines!
|
||||||
CompleteItem func(item string, previous, current *restic.Node, s ItemStats, d time.Duration)
|
CompleteItem func(item string, previous, current *restic.Node, s ItemStats, d time.Duration)
|
||||||
|
@ -431,6 +434,8 @@ func (arch *Archiver) Save(ctx context.Context, snPath, target string, previous
|
||||||
// Save will close the file, we don't need to do that
|
// Save will close the file, we don't need to do that
|
||||||
fn = arch.fileSaver.Save(ctx, snPath, target, file, fi, func() {
|
fn = arch.fileSaver.Save(ctx, snPath, target, file, fi, func() {
|
||||||
arch.StartFile(snPath)
|
arch.StartFile(snPath)
|
||||||
|
}, func() {
|
||||||
|
arch.CompleteItem(snPath, nil, nil, ItemStats{}, 0)
|
||||||
}, func(node *restic.Node, stats ItemStats) {
|
}, func(node *restic.Node, stats ItemStats) {
|
||||||
arch.CompleteItem(snPath, previous, node, stats, time.Since(start))
|
arch.CompleteItem(snPath, previous, node, stats, time.Since(start))
|
||||||
})
|
})
|
||||||
|
|
|
@ -53,6 +53,8 @@ func saveFile(t testing.TB, repo restic.Repository, filename string, filesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
completeReadingCallback bool
|
||||||
|
|
||||||
completeCallbackNode *restic.Node
|
completeCallbackNode *restic.Node
|
||||||
completeCallbackStats ItemStats
|
completeCallbackStats ItemStats
|
||||||
completeCallback bool
|
completeCallback bool
|
||||||
|
@ -60,6 +62,13 @@ func saveFile(t testing.TB, repo restic.Repository, filename string, filesystem
|
||||||
startCallback bool
|
startCallback bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
completeReading := func() {
|
||||||
|
completeReadingCallback = true
|
||||||
|
if completeCallback {
|
||||||
|
t.Error("callbacks called in wrong order")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
complete := func(node *restic.Node, stats ItemStats) {
|
complete := func(node *restic.Node, stats ItemStats) {
|
||||||
completeCallback = true
|
completeCallback = true
|
||||||
completeCallbackNode = node
|
completeCallbackNode = node
|
||||||
|
@ -80,7 +89,7 @@ func saveFile(t testing.TB, repo restic.Repository, filename string, filesystem
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := arch.fileSaver.Save(ctx, "/", filename, file, fi, start, complete)
|
res := arch.fileSaver.Save(ctx, "/", filename, file, fi, start, completeReading, complete)
|
||||||
|
|
||||||
fnr := res.take(ctx)
|
fnr := res.take(ctx)
|
||||||
if fnr.err != nil {
|
if fnr.err != nil {
|
||||||
|
@ -101,6 +110,10 @@ func saveFile(t testing.TB, repo restic.Repository, filename string, filesystem
|
||||||
t.Errorf("start callback did not happen")
|
t.Errorf("start callback did not happen")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !completeReadingCallback {
|
||||||
|
t.Errorf("completeReading callback did not happen")
|
||||||
|
}
|
||||||
|
|
||||||
if !completeCallback {
|
if !completeCallback {
|
||||||
t.Errorf("complete callback did not happen")
|
t.Errorf("complete callback did not happen")
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,17 +67,21 @@ func (s *FileSaver) TriggerShutdown() {
|
||||||
type CompleteFunc func(*restic.Node, ItemStats)
|
type CompleteFunc func(*restic.Node, ItemStats)
|
||||||
|
|
||||||
// Save stores the file f and returns the data once it has been completed. The
|
// Save stores the file f and returns the data once it has been completed. The
|
||||||
// file is closed by Save.
|
// file is closed by Save. completeReading is only called if the file was read
|
||||||
func (s *FileSaver) Save(ctx context.Context, snPath string, target string, file fs.File, fi os.FileInfo, start func(), complete CompleteFunc) FutureNode {
|
// successfully. complete is always called. If completeReading is called, then
|
||||||
|
// this will always happen before calling complete.
|
||||||
|
func (s *FileSaver) Save(ctx context.Context, snPath string, target string, file fs.File, fi os.FileInfo, start func(), completeReading func(), complete CompleteFunc) FutureNode {
|
||||||
fn, ch := newFutureNode()
|
fn, ch := newFutureNode()
|
||||||
job := saveFileJob{
|
job := saveFileJob{
|
||||||
snPath: snPath,
|
snPath: snPath,
|
||||||
target: target,
|
target: target,
|
||||||
file: file,
|
file: file,
|
||||||
fi: fi,
|
fi: fi,
|
||||||
start: start,
|
|
||||||
complete: complete,
|
|
||||||
ch: ch,
|
ch: ch,
|
||||||
|
|
||||||
|
start: start,
|
||||||
|
completeReading: completeReading,
|
||||||
|
complete: complete,
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
@ -97,12 +101,14 @@ type saveFileJob struct {
|
||||||
file fs.File
|
file fs.File
|
||||||
fi os.FileInfo
|
fi os.FileInfo
|
||||||
ch chan<- futureNodeResult
|
ch chan<- futureNodeResult
|
||||||
complete CompleteFunc
|
|
||||||
start func()
|
start func()
|
||||||
|
completeReading func()
|
||||||
|
complete CompleteFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveFile stores the file f in the repo, then closes it.
|
// saveFile stores the file f in the repo, then closes it.
|
||||||
func (s *FileSaver) saveFile(ctx context.Context, chnker *chunker.Chunker, snPath string, target string, f fs.File, fi os.FileInfo, start func(), finish func(res futureNodeResult)) {
|
func (s *FileSaver) saveFile(ctx context.Context, chnker *chunker.Chunker, snPath string, target string, f fs.File, fi os.FileInfo, start func(), finishReading func(), finish func(res futureNodeResult)) {
|
||||||
start()
|
start()
|
||||||
|
|
||||||
fnr := futureNodeResult{
|
fnr := futureNodeResult{
|
||||||
|
@ -227,6 +233,7 @@ func (s *FileSaver) saveFile(ctx context.Context, chnker *chunker.Chunker, snPat
|
||||||
// after reaching the end of this method
|
// after reaching the end of this method
|
||||||
remaining += idx + 1
|
remaining += idx + 1
|
||||||
lock.Unlock()
|
lock.Unlock()
|
||||||
|
finishReading()
|
||||||
completeBlob()
|
completeBlob()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +253,11 @@ func (s *FileSaver) worker(ctx context.Context, jobs <-chan saveFileJob) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.saveFile(ctx, chnker, job.snPath, job.target, job.file, job.fi, job.start, func(res futureNodeResult) {
|
s.saveFile(ctx, chnker, job.snPath, job.target, job.file, job.fi, job.start, func() {
|
||||||
|
if job.completeReading != nil {
|
||||||
|
job.completeReading()
|
||||||
|
}
|
||||||
|
}, func(res futureNodeResult) {
|
||||||
if job.complete != nil {
|
if job.complete != nil {
|
||||||
job.complete(res.node, res.stats)
|
job.complete(res.node, res.stats)
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ func TestFileSaver(t *testing.T) {
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
startFn := func() {}
|
startFn := func() {}
|
||||||
|
completeReadingFn := func() {}
|
||||||
completeFn := func(*restic.Node, ItemStats) {}
|
completeFn := func(*restic.Node, ItemStats) {}
|
||||||
|
|
||||||
testFs := fs.Local{}
|
testFs := fs.Local{}
|
||||||
|
@ -78,7 +79,7 @@ func TestFileSaver(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ff := s.Save(ctx, filename, filename, f, fi, startFn, completeFn)
|
ff := s.Save(ctx, filename, filename, f, fi, startFn, completeReadingFn, completeFn)
|
||||||
results = append(results, ff)
|
results = append(results, ff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue