in dag.go [132:177]
func traverse[T Block](d *Dag, f func(b T) error) error {
var err error
pending := linkedlistqueue.New()
visited := hashset.New()
for _, i := range d.GetRoots() {
pending.Enqueue(i)
}
for !pending.Empty() {
next, _ := pending.Dequeue()
if visited.Contains(next) {
continue
}
nb := next.(Block)
address := nb.Address()
parents, parentErr := d.GetParents(address)
if parentErr != nil {
return parentErr
}
ready := true
for _, p := range parents {
if !visited.Contains(p) {
ready = false
break
}
}
if !ready {
pending.Enqueue(next)
continue
}
visited.Add(next)
if b, ok := nb.(T); ok {
if subError := f(b); subError != nil {
err = multierror.Append(err, subError)
}
}
children, getChildrenErr := d.GetChildren(address)
if getChildrenErr != nil {
return getChildrenErr
}
for _, c := range children {
pending.Enqueue(c)
}
}
return err
}