mirror of https://github.com/restic/restic.git
archiver: Fix intermediate index upload
A user discovered[1] that when the backup finishes during the upload of an intermediate index, the upload is cancelled and the index never fully saved, but the snapshot is saved and the backup finalizes without an error. This lead to a situation where a snapshot references data that is contained in the repo, but not referenced in any index, leading to strange error messages. This commit uses a dedicated context to signal the intermediate index uploading routine to terminate after the last index has been uploaded. This way, an upload running when the backup finishes is completed before the routine terminates and the snapshot is saved. [1] https://forum.restic.net/t/error-loading-tree-check-prune-and-forget-gives-error-b2-backend/406
This commit is contained in:
parent
cccb2fc7e7
commit
f99c95c766
|
@ -620,7 +620,7 @@ func (j archiveJob) Copy() pipe.Job {
|
|||
const saveIndexTime = 30 * time.Second
|
||||
|
||||
// saveIndexes regularly queries the master index for full indexes and saves them.
|
||||
func (arch *Archiver) saveIndexes(ctx context.Context, wg *sync.WaitGroup) {
|
||||
func (arch *Archiver) saveIndexes(saveCtx, shutdownCtx context.Context, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
ticker := time.NewTicker(saveIndexTime)
|
||||
|
@ -628,11 +628,13 @@ func (arch *Archiver) saveIndexes(ctx context.Context, wg *sync.WaitGroup) {
|
|||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-saveCtx.Done():
|
||||
return
|
||||
case <-shutdownCtx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
debug.Log("saving full indexes")
|
||||
err := arch.repo.SaveFullIndex(ctx)
|
||||
err := arch.repo.SaveFullIndex(saveCtx)
|
||||
if err != nil {
|
||||
debug.Log("save indexes returned an error: %v", err)
|
||||
fmt.Fprintf(os.Stderr, "error saving preliminary index: %v\n", err)
|
||||
|
@ -748,16 +750,16 @@ func (arch *Archiver) Snapshot(ctx context.Context, p *restic.Progress, paths, t
|
|||
|
||||
// run index saver
|
||||
var wgIndexSaver sync.WaitGroup
|
||||
indexCtx, indexCancel := context.WithCancel(ctx)
|
||||
shutdownCtx, indexShutdown := context.WithCancel(ctx)
|
||||
wgIndexSaver.Add(1)
|
||||
go arch.saveIndexes(indexCtx, &wgIndexSaver)
|
||||
go arch.saveIndexes(ctx, shutdownCtx, &wgIndexSaver)
|
||||
|
||||
// wait for all workers to terminate
|
||||
debug.Log("wait for workers")
|
||||
wg.Wait()
|
||||
|
||||
// stop index saver
|
||||
indexCancel()
|
||||
indexShutdown()
|
||||
wgIndexSaver.Wait()
|
||||
|
||||
debug.Log("workers terminated")
|
||||
|
|
Loading…
Reference in New Issue