|
|
@ -63,8 +63,8 @@ var ( |
|
|
|
// ErrMaxVirtualLevel indicates when going down into the tree, the max
|
|
|
|
// virtual level is reached
|
|
|
|
ErrMaxVirtualLevel = fmt.Errorf("max virtual level reached") |
|
|
|
// ErrSnapshotNotEditable indicates when the tree is a snapshot, thus
|
|
|
|
// can not be modified
|
|
|
|
// ErrSnapshotNotEditable indicates when the tree is a non writable
|
|
|
|
// snapshot, thus can not be modified
|
|
|
|
ErrSnapshotNotEditable = fmt.Errorf("snapshot tree can not be edited") |
|
|
|
// ErrTreeNotEmpty indicates when the tree was expected to be empty and
|
|
|
|
// it is not
|
|
|
@ -741,10 +741,10 @@ func bytesToBitmap(b []byte) []bool { |
|
|
|
return bitmap |
|
|
|
} |
|
|
|
|
|
|
|
// Get returns the value for a given key. If the key is not found, will return
|
|
|
|
// the error ErrKeyNotFound, and in the leafK & leafV parameters will be placed
|
|
|
|
// the data found in the tree in the leaf that was on the path going to the
|
|
|
|
// input key.
|
|
|
|
// Get returns the value in the Tree for a given key. If the key is not found,
|
|
|
|
// will return the error ErrKeyNotFound, and in the leafK & leafV parameters
|
|
|
|
// will be placed the data found in the tree in the leaf that was on the path
|
|
|
|
// going to the input key.
|
|
|
|
func (t *Tree) Get(k []byte) ([]byte, []byte, error) { |
|
|
|
rTx := t.db.ReadTx() |
|
|
|
defer rTx.Discard() |
|
|
@ -853,6 +853,39 @@ func (t *Tree) GetNLeafsWithTx(rTx db.ReadTx) (int, error) { |
|
|
|
return int(nLeafs), nil |
|
|
|
} |
|
|
|
|
|
|
|
// SetRoot sets the root to the given root
|
|
|
|
func (t *Tree) SetRoot(root []byte) error { |
|
|
|
wTx := t.db.WriteTx() |
|
|
|
defer wTx.Discard() |
|
|
|
|
|
|
|
if err := t.SetRootWithTx(wTx, root); err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
return wTx.Commit() |
|
|
|
} |
|
|
|
|
|
|
|
// SetRootWithTx sets the root to the given root using the given db.WriteTx
|
|
|
|
func (t *Tree) SetRootWithTx(wTx db.WriteTx, root []byte) error { |
|
|
|
if !t.editable() { |
|
|
|
return ErrSnapshotNotEditable |
|
|
|
} |
|
|
|
|
|
|
|
if root == nil { |
|
|
|
return fmt.Errorf("can not SetRoot with nil root") |
|
|
|
} |
|
|
|
|
|
|
|
// check that the root exists in the db
|
|
|
|
if !bytes.Equal(root, t.emptyHash) { |
|
|
|
if _, err := wTx.Get(root); err == ErrKeyNotFound { |
|
|
|
return fmt.Errorf("can not SetRoot with root %x, as it does not exist in the db", root) |
|
|
|
} else if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return wTx.Set(dbKeyRoot, root) |
|
|
|
} |
|
|
|
|
|
|
|
// Snapshot returns a read-only copy of the Tree from the given root
|
|
|
|
func (t *Tree) Snapshot(fromRoot []byte) (*Tree, error) { |
|
|
|
// allow to define which root to use
|
|
|
@ -863,6 +896,19 @@ func (t *Tree) Snapshot(fromRoot []byte) (*Tree, error) { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
rTx := t.db.ReadTx() |
|
|
|
defer rTx.Discard() |
|
|
|
// check that the root exists in the db
|
|
|
|
if !bytes.Equal(fromRoot, t.emptyHash) { |
|
|
|
if _, err := rTx.Get(fromRoot); err == ErrKeyNotFound { |
|
|
|
return nil, |
|
|
|
fmt.Errorf("can not do a Snapshot with root %x, as it does not exist in the db", |
|
|
|
fromRoot) |
|
|
|
} else if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return &Tree{ |
|
|
|
db: t.db, |
|
|
|
maxLevels: t.maxLevels, |
|
|
|