From 7a165f32a92e39228628467f3296150be7301488 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 6 Jul 2019 20:01:48 +0200 Subject: [PATCH] checker: Traverse trees in depth-first order Backups traverse the file tree in depth-first order and saves trees on the way back up. This results in tree packs filled in a way comparable to the reverse Polish notation. In order to check tree blobs in that order, the treeFilter would have to delay the forwarding of tree nodes until all children of it are processed which would complicate the implementation. Therefore do the next similar thing and traverse the tree in depth-first order, but process trees already on the way down. The tree blob ids are added in reverse order to the backlog, which is once again reverted when removing the ids from the back of the backlog. --- internal/checker/checker.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index c8e6f3f8a..577e6e8e4 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -493,7 +493,9 @@ func (c *Checker) filterTrees(ctx context.Context, backlog restic.IDs, loaderCha for { if loadCh == nil && len(backlog) > 0 { - nextTreeID, backlog = backlog[0], backlog[1:] + // process last added ids first, that is traverse the tree in depth-first order + ln := len(backlog) - 1 + nextTreeID, backlog = backlog[ln], backlog[:ln] // use a separate flag for processed trees to ensure that check still processes trees // even when a file references a tree blob @@ -545,7 +547,9 @@ func (c *Checker) filterTrees(ctx context.Context, backlog restic.IDs, loaderCha } else { subtrees := j.Tree.Subtrees() debug.Log("subtrees for tree %v: %v", j.ID, subtrees) - for _, id := range subtrees { + // iterate backwards over subtree to compensate backwards traversal order of nextTreeID selection + for i := len(subtrees) - 1; i >= 0; i-- { + id := subtrees[i] if id.IsNull() { // We do not need to raise this error here, it is // checked when the tree is checked. Just make sure