Skip to content
This repository has been archived by the owner on Apr 24, 2023. It is now read-only.

fix: should use copied value of iterator #33

Merged
merged 2 commits into from
Dec 2, 2021
Merged
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
40 changes: 21 additions & 19 deletions rocksdb/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package rocksdb
import (
"github.com/line/gorocksdb"
tmdb "github.com/line/tm-db/v2"
"github.com/line/tm-db/v2/internal/util"
)

type rocksDBIterator struct {
source *gorocksdb.Iterator
opts *gorocksdb.ReadOptions
isReverse bool
isInvalid bool
key *gorocksdb.Slice
value *gorocksdb.Slice
key []byte
value []byte
}

var _ tmdb.Iterator = (*rocksDBIterator)(nil)
Expand Down Expand Up @@ -69,25 +70,26 @@ func (itr *rocksDBIterator) invalidate() {
func (itr *rocksDBIterator) Key() []byte {
itr.assertIsValid()
if itr.key == nil {
itr.key = itr.source.Key()
itr.key = moveSliceToBytes(itr.source.Key())
}
return itr.key.Data()
return itr.key
}

// Value implements Iterator.
func (itr *rocksDBIterator) Value() []byte {
itr.assertIsValid()
if itr.value == nil {
itr.value = itr.source.Value()
itr.value = moveSliceToBytes(itr.source.Value())
}
return itr.value.Data()
return itr.value
}

// Next implements Iterator.
func (itr *rocksDBIterator) Next() {
itr.assertIsValid()

itr.freeKeyValue()
itr.key = nil
itr.value = nil

if !itr.isReverse {
itr.source.Next()
Expand All @@ -111,23 +113,23 @@ func (itr *rocksDBIterator) Close() error {
itr.opts.Destroy()
itr.opts = nil
}
itr.freeKeyValue()
return nil
}

func (itr *rocksDBIterator) freeKeyValue() {
if itr.key != nil {
itr.key.Free()
itr.key = nil
}
if itr.value != nil {
itr.value.Free()
itr.value = nil
}
}

func (itr *rocksDBIterator) assertIsValid() {
if itr.isInvalid {
panic("iterator is invalid")
}
}

// moveSliceToBytes will free the slice and copy out a go []byte
// This function can be applied on *Slice returned from Key() and Value()
// of an Iterator, because they are marked as freed.
func moveSliceToBytes(s *gorocksdb.Slice) []byte {
var bz []byte
if s.Exists() {
bz = util.Cp(s.Data())
}
s.Free()
return bz
}