Skip to content

Commit cd39e67

Browse files
committed
refactor to use KeyCopy
1 parent 18c0a17 commit cd39e67

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

storage/operation/pebbleimpl/iterator.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ func (i pebbleIterItem) Key() []byte {
6767
return i.iter.Key()
6868
}
6969

70+
// KeyCopy returns a copy of the key of the item, writing it to dst slice.
71+
func (i pebbleIterItem) KeyCopy(dst []byte) []byte {
72+
return append(dst[:0], i.iter.Key()...)
73+
}
74+
7075
func (i pebbleIterItem) Value(fn func([]byte) error) error {
7176
val, err := i.iter.ValueAndErr()
7277
if err != nil {

storage/operation/reads.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ type CreateFunc func() interface{}
2828
type HandleFunc func() error
2929
type IterationFunc func() (CheckFunc, CreateFunc, HandleFunc)
3030

31-
// IterateKeysInPrefixRange will iterate over all keys with prefixes in the range [startPrefix, endPrefix] (both inclusive)
31+
// IterateKeysInPrefixRange will iterate over all entries in the database, where the key starts with a prefixes in
32+
// the range [startPrefix, endPrefix] (both inclusive). We require that startPrefix <= endPrefix (otherwise this
33+
// function errors). On every such key, the `check` function is called. If `check` errors, iteration is aborted.
34+
// No errors expected during normal operations.
3235
func IterateKeysInPrefixRange(startPrefix []byte, endPrefix []byte, check func(key []byte) error) func(storage.Reader) error {
3336
return Iterate(startPrefix, endPrefix, func() (CheckFunc, CreateFunc, HandleFunc) {
3437
return func(key []byte) (bool, error) {
@@ -164,8 +167,10 @@ func Retrieve(key []byte, entity interface{}) func(storage.Reader) error {
164167
}
165168
}
166169

167-
// FindHighestAtOrBelow finds the highest key with the given prefix and
168-
// height equal to or below the given height.
170+
// FindHighestAtOrBelow is for database entries that are indexed by block height. It is suitable to search
171+
// keys with the format prefix` + `height` (where "+" denotes concatenation of binary strings). The height
172+
// is encoded as Big-Endian (entries with numerically smaller height have lexicographically smaller key).
173+
// The function finds the *highest* key with the given prefix and height equal to or below the given height.
169174
func FindHighestAtOrBelow(prefix []byte, height uint64, entity interface{}) func(storage.Reader) error {
170175
return func(r storage.Reader) error {
171176
if len(prefix) == 0 {
@@ -180,9 +185,12 @@ func FindHighestAtOrBelow(prefix []byte, height uint64, entity interface{}) func
180185
defer it.Close()
181186

182187
var highestKey []byte
188+
183189
// find highest value below the given height
184190
for it.First(); it.Valid(); it.Next() {
185-
highestKey = it.IterItem().Key()
191+
// copy the key to avoid the underlying slices of the key
192+
// being modified by the Next() call
193+
highestKey = it.IterItem().KeyCopy(highestKey)
186194
}
187195

188196
if len(highestKey) == 0 {

storage/operations.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ type Iterator interface {
2727
// The next key-value pair might be invalid, so you should call Valid() to check.
2828
Next()
2929

30-
// IterItem returns the current key-value pair, or nil if done.
31-
// A best practice is always to call Valid() before calling IterItem.
30+
// IterItem returns the current key-value pair, or nil if Valid returns false.
31+
// Always to call Valid() before calling IterItem.
32+
// Note, the returned item is only valid until the Next() method is called.
3233
IterItem() IterItem
3334

3435
// Close closes the iterator. Iterator must be closed, otherwise it causes memory leak.
@@ -38,8 +39,16 @@ type Iterator interface {
3839

3940
// IterItem is an interface for iterating over key-value pairs in a storage backend.
4041
type IterItem interface {
42+
// Key returns the key of the current key-value pair
43+
// Key is only valid until the Iterator.Next() method is called
44+
// If you need to use it outside its validity, please use KeyCopy
4145
Key() []byte
4246

47+
// KeyCopy returns a copy of the key of the item, writing it to dst slice.
48+
// If nil is passed, or capacity of dst isn't sufficient, a new slice would be allocated and
49+
// returned.
50+
KeyCopy(dst []byte) []byte
51+
4352
// Value returns the value of the current key-value pair
4453
// The reason it takes a function is to follow badgerDB's API pattern
4554
// No errors expected during normal operation

0 commit comments

Comments
 (0)