Skip to content

Commit a7a0daf

Browse files
fix(store/v2): fix the pebbledb storage implementation (#21837)
Co-authored-by: Julien Robert <julien@rbrt.fr>
1 parent 06c2fc7 commit a7a0daf

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

store/v2/storage/pebbledb/db.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,27 +68,27 @@ func New(dataDir string) (*Database, error) {
6868
return nil, fmt.Errorf("failed to open PebbleDB: %w", err)
6969
}
7070

71-
pruneHeight, err := getPruneHeight(db)
71+
earliestVersion, err := getEarliestVersion(db)
7272
if err != nil {
73-
return nil, fmt.Errorf("failed to get prune height: %w", err)
73+
return nil, fmt.Errorf("failed to get the earliest version: %w", err)
7474
}
7575

7676
return &Database{
7777
storage: db,
78-
earliestVersion: pruneHeight + 1,
78+
earliestVersion: earliestVersion,
7979
sync: true,
8080
}, nil
8181
}
8282

8383
func NewWithDB(storage *pebble.DB, sync bool) *Database {
84-
pruneHeight, err := getPruneHeight(storage)
84+
earliestVersion, err := getEarliestVersion(storage)
8585
if err != nil {
86-
panic(fmt.Errorf("failed to get prune height: %w", err))
86+
panic(fmt.Errorf("failed to get the earliest version: %w", err))
8787
}
8888

8989
return &Database{
9090
storage: storage,
91-
earliestVersion: pruneHeight + 1,
91+
earliestVersion: earliestVersion,
9292
sync: sync,
9393
}
9494
}
@@ -362,7 +362,10 @@ func prependStoreKey(storeKey, key []byte) []byte {
362362
return []byte(fmt.Sprintf("%s%s", storePrefix(storeKey), key))
363363
}
364364

365-
func getPruneHeight(storage *pebble.DB) (uint64, error) {
365+
// getEarliestVersion returns the earliest version set in the database.
366+
// It is calculated by prune height + 1. If the prune height is not set, it
367+
// returns 0.
368+
func getEarliestVersion(storage *pebble.DB) (uint64, error) {
366369
bz, closer, err := storage.Get([]byte(pruneHeightKey))
367370
if err != nil {
368371
if errors.Is(err, pebble.ErrNotFound) {
@@ -377,7 +380,7 @@ func getPruneHeight(storage *pebble.DB) (uint64, error) {
377380
return 0, closer.Close()
378381
}
379382

380-
return binary.LittleEndian.Uint64(bz), closer.Close()
383+
return binary.LittleEndian.Uint64(bz) + 1, closer.Close()
381384
}
382385

383386
func valTombstoned(value []byte) bool {

store/v2/storage/pebbledb/iterator.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ func newPebbleDBIterator(src *pebble.Iterator, prefix, mvccStart, mvccEnd []byte
8282
// so there exists at least one version of currKey SeekLT may move to.
8383
itr.valid = itr.source.SeekLT(MVCCEncode(currKey, itr.version+1))
8484
}
85+
86+
// The cursor might now be pointing at a key/value pair that is tombstoned.
87+
// If so, we must move the cursor.
88+
if itr.valid && itr.cursorTombstoned() {
89+
itr.Next()
90+
}
8591
}
8692
return itr
8793
}

store/v2/storage/storage_test_suite.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,33 @@ func (s *StorageTestSuite) TestDatabaseIterator_ForwardIterationHigher() {
485485
s.Require().Equal(0, count)
486486
}
487487

488+
func (s *StorageTestSuite) TestDatabaseIterator_WithDelete() {
489+
db, err := s.NewDB(s.T().TempDir())
490+
s.Require().NoError(err)
491+
defer db.Close()
492+
493+
dbApplyChangeset(s.T(), db, 1, storeKey1, [][]byte{[]byte("keyA")}, [][]byte{[]byte("value001")})
494+
dbApplyChangeset(s.T(), db, 2, storeKey1, [][]byte{[]byte("keyA")}, [][]byte{nil}) // delete
495+
496+
itr, err := db.Iterator(storeKey1Bytes, 1, nil, nil)
497+
s.Require().NoError(err)
498+
499+
count := 0
500+
for ; itr.Valid(); itr.Next() {
501+
count++
502+
}
503+
s.Require().Equal(1, count)
504+
505+
itr, err = db.Iterator(storeKey1Bytes, 2, nil, nil)
506+
s.Require().NoError(err)
507+
508+
count = 0
509+
for ; itr.Valid(); itr.Next() {
510+
count++
511+
}
512+
s.Require().Equal(0, count)
513+
}
514+
488515
func (s *StorageTestSuite) TestDatabase_IteratorNoDomain() {
489516
db, err := s.NewDB(s.T().TempDir())
490517
s.Require().NoError(err)

0 commit comments

Comments
 (0)