Esempio n. 1
0
func (m *RadixMap) walk(f WalkFunc, key data.Hash256, depth uint8, fill bool) error {
	if key.IsZero() {
		return nil
	}
	var node *RadixNode
	if fill {
		var err error
		node = &RadixNode{
			Depth: depth,
		}
		node.Node, err = m.db.Get(key)
		if err != nil {
			return err
		}
		m.nodes[key] = node
	} else {
		var ok bool
		node, ok = m.nodes[key]
		if !ok {
			return fmt.Errorf("Missing hash: %s", key.String())
		}
		if err := f(key, node); err != nil {
			return err
		}
	}
	inner, ok := node.Node.(*data.InnerNode)
	if !ok {
		return nil
	}
	return inner.Each(func(pos int, child data.Hash256) error {
		return m.walk(f, child, depth+1, fill)
	})
}
Esempio n. 2
0
func diff(left, right data.Hash256, db storage.DB, ops *RadixOperations, depth uint8) error {
	var l, r data.Storer
	var err error
	switch {
	case left.IsZero() && right.IsZero():
		return nil
	case left.IsZero():
		r, err = db.Get(left)
		if err != nil {
			return err
		}
		ops.Add(r, Deletion, depth)
		return visitChildren(r, db, ops, depth+1, Deletion)
	case right.IsZero():
		l, err = db.Get(left)
		if err != nil {
			return err
		}
		ops.Add(l, Addition, depth)
		return visitChildren(l, db, ops, depth+1, Addition)
	}
	l, err = db.Get(left)
	if err != nil {
		return err
	}
	r, err = db.Get(right)
	if err != nil {
		return err
	}
	ops.Add(r, Deletion, depth)
	ops.Add(l, Addition, depth)
	leftInner, leftOk := l.(*data.InnerNode)
	rightInner, rightOk := r.(*data.InnerNode)
	switch {
	case !leftOk && !rightOk:
		return nil
	case !leftOk:
		return visitChildren(r, db, ops, depth+1, Deletion)
	case !rightOk:
		return visitChildren(l, db, ops, depth+1, Addition)
	default:
		for i := 0; i < 16; i++ {
			leftChild, rightChild := leftInner.Children[i], rightInner.Children[i]
			switch {
			case leftChild == rightChild:
				continue
			case leftChild.IsZero():
				child, err := db.Get(rightChild)
				if err != nil {
					return err
				}
				if err := visitChildren(child, db, ops, depth+1, Deletion); err != nil {
					return err
				}
			case rightChild.IsZero():
				child, err := db.Get(leftChild)
				if err != nil {
					return err
				}
				if err := visitChildren(child, db, ops, depth+1, Addition); err != nil {
					return err
				}
			default:
				if err := diff(leftChild, rightChild, db, ops, depth+1); err != nil {
					return err
				}
			}
		}
	}
	return nil
}