Skip to content

Commit

Permalink
Merge pull request #26 from ridge/txn-clone
Browse files Browse the repository at this point in the history
Added Clone method to Txn to create an independent copy of a transaction
  • Loading branch information
banks committed Mar 18, 2020
2 parents 0146a9a + 56f5bef commit e47f517
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
14 changes: 14 additions & 0 deletions iradix.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ func (t *Tree) Txn() *Txn {
return txn
}

// Clone makes an independent copy of the transaction. The new transaction
// does not track any nodes and has TrackMutate turned off. The cloned transaction will contain any uncommitted writes in the original transaction but further mutations to either will be independent and result in different radix trees on Commit. A cloned transaction may be passed to another goroutine and mutated there independently however each transaction may only be mutated in a single thread.
func (t *Txn) Clone() *Txn {
// reset the writable node cache to avoid leaking future writes into the clone
t.writable = nil

txn := &Txn{
root: t.root,
snap: t.snap,
size: t.size,
}
return txn
}

// TrackMutate can be used to toggle if mutations are tracked. If this is enabled
// then notifications will be issued for affected internal nodes and leaves when
// the transaction is committed.
Expand Down
30 changes: 30 additions & 0 deletions iradix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1774,3 +1774,33 @@ func TestIterateLowerBoundFuzz(t *testing.T) {
t.Error(err)
}
}

func TestClone(t *testing.T) {
r := New()

t1 := r.Txn()
t1.Insert([]byte("foo"), 7)
t2 := t1.Clone()

t1.Insert([]byte("bar"), 42)
t2.Insert([]byte("baz"), 43)

if val, ok := t1.Get([]byte("foo")); !ok || val != 7 {
t.Fatalf("bad foo in t1")
}
if val, ok := t2.Get([]byte("foo")); !ok || val != 7 {
t.Fatalf("bad foo in t2")
}
if val, ok := t1.Get([]byte("bar")); !ok || val != 42 {
t.Fatalf("bad bar in t1")
}
if _, ok := t2.Get([]byte("bar")); ok {
t.Fatalf("bar found in t2")
}
if _, ok := t1.Get([]byte("baz")); ok {
t.Fatalf("baz found in t1")
}
if val, ok := t2.Get([]byte("baz")); !ok || val != 43 {
t.Fatalf("bad baz in t2")
}
}

0 comments on commit e47f517

Please sign in to comment.