Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document byte slice immutability #262

Merged
merged 2 commits into from
Jun 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions immutable_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
// ImmutableTree contains the immutable tree at a given version. It is typically created by calling
// MutableTree.GetImmutable(), in which case the returned tree is safe for concurrent access as
// long as the version is not deleted via DeleteVersion() or the tree's pruning settings.
//
// Returned key/value byte slices must not be modified, since they may point to data located inside
// IAVL which would also be modified.
type ImmutableTree struct {
root *Node
ndb *nodeDB
Expand Down Expand Up @@ -148,8 +151,9 @@ func (t *ImmutableTree) Export() *Exporter {
return newExporter(t)
}

// Get returns the index and value of the specified key if it exists, or nil
// and the next index, if it doesn't.
// Get returns the index and value of the specified key if it exists, or nil and the next index
// otherwise. The returned value must not be modified, since it may point to data stored within
// IAVL.
func (t *ImmutableTree) Get(key []byte) (index int64, value []byte) {
if t.root == nil {
return 0, nil
Expand All @@ -165,7 +169,8 @@ func (t *ImmutableTree) GetByIndex(index int64) (key []byte, value []byte) {
return t.root.getByIndex(t, index)
}

// Iterate iterates over all keys of the tree, in order.
// Iterate iterates over all keys of the tree, in order. The keys and values must not be modified,
// since they may point to data stored within IAVL.
func (t *ImmutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped bool) {
if t.root == nil {
return false
Expand All @@ -179,7 +184,8 @@ func (t *ImmutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped
}

// IterateRange makes a callback for all nodes with key between start and end non-inclusive.
// If either are nil, then it is open on that side (nil, nil is the same as Iterate)
// If either are nil, then it is open on that side (nil, nil is the same as Iterate). The keys and
// values must not be modified, since they may point to data stored within IAVL.
func (t *ImmutableTree) IterateRange(start, end []byte, ascending bool, fn func(key []byte, value []byte) bool) (stopped bool) {
if t.root == nil {
return false
Expand All @@ -193,7 +199,8 @@ func (t *ImmutableTree) IterateRange(start, end []byte, ascending bool, fn func(
}

// IterateRangeInclusive makes a callback for all nodes with key between start and end inclusive.
// If either are nil, then it is open on that side (nil, nil is the same as Iterate)
// If either are nil, then it is open on that side (nil, nil is the same as Iterate). The keys and
// values must not be modified, since they may point to data stored within IAVL.
func (t *ImmutableTree) IterateRangeInclusive(start, end []byte, ascending bool, fn func(key, value []byte, version int64) bool) (stopped bool) {
if t.root == nil {
return false
Expand Down
12 changes: 9 additions & 3 deletions mutable_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ var ErrVersionDoesNotExist = errors.New("version does not exist")
// use, and should be guarded by a Mutex or RWLock as appropriate. An immutable tree at a given
// version can be returned via GetImmutable, which is safe for concurrent access.
//
// Given and returned key/value byte slices must not be modified, since they may point to data
// located inside IAVL which would also be modified.
//
// The inner ImmutableTree should not be used directly by callers.
type MutableTree struct {
*ImmutableTree // The current, working tree.
Expand Down Expand Up @@ -134,7 +137,8 @@ func (tree *MutableTree) prepareOrphansSlice() []*Node {
return make([]*Node, 0, tree.Height()+3)
}

// Set sets a key in the working tree. Nil values are not supported.
// Set sets a key in the working tree. Nil values are invalid. The given key/value byte slices must
// not be modified after this call, since they point to slices stored within IAVL.
func (tree *MutableTree) Set(key, value []byte) bool {
orphaned, updated := tree.set(key, value)
tree.addOrphans(orphaned)
Expand Down Expand Up @@ -218,7 +222,8 @@ func (tree *MutableTree) recursiveSet(node *Node, key []byte, value []byte, orph
}
}

// Remove removes a key from the working tree.
// Remove removes a key from the working tree. The given key byte slice should not be modified
// after this call, since it may point to data stored inside IAVL.
func (tree *MutableTree) Remove(key []byte) ([]byte, bool) {
val, orphaned, removed := tree.remove(key)
tree.addOrphans(orphaned)
Expand Down Expand Up @@ -446,7 +451,8 @@ func (tree *MutableTree) Rollback() {
tree.orphans = map[string]int64{}
}

// GetVersioned gets the value at the specified key and version.
// GetVersioned gets the value at the specified key and version. The returned value must not be
// modified, since it may point to data stored within IAVL.
func (tree *MutableTree) GetVersioned(key []byte, version int64) (
index int64, value []byte,
) {
Expand Down