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.
This commit is contained in:
Michael Eischer 2019-07-06 20:01:48 +02:00
parent 36c69e3ca7
commit 7a165f32a9

View file

@ -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