-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: height limited query with leveldb (#3)
* feat: height limited leveldb * chore: remove redundant interfaces * fix: reverse iterator creation * feat: batch write with genesis block * fix: batch panic in genesis block execution * feat: override cms * fix: mutate store's db instance * feat: append byte for deletion flag into item rather than encode * feat: optimize key modifying * feat: separately store real data for sync * refactor: remove query handling middleware * refactor: rename function that duplicate hldb with new height * refactor: remove test function * refactor: rename key prefixes * refactor: remove item struct * refactor: make heleveldb iterator composite tmdb.Iterator * refactor: shorten key prefix * feat: add archival cache, flush latest only * deps: tidy * refactor: rename branching kvstore function. * feat: cache last valid key in iterator * fix: being locked when disable sync * feat: invert key suffix not to use reverse iterator * feat: cache last valid value in iterator * feat: use default store on query without height * fix: check height from query string. check invalid height. * refactor: rename prefixing functions * style: add comments * feat: remove heleveldb test Co-authored-by: Jesse Chung <jesse@soob.co>
- Loading branch information
Showing
19 changed files
with
1,637 additions
and
184 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package heleveldb | ||
|
||
type DriverConfig struct { | ||
Name string | ||
Dir string | ||
Mode int | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package heleveldb | ||
|
||
import ( | ||
"math" | ||
|
||
tmdb "github.com/tendermint/tm-db" | ||
"github.com/terra-money/mantlemint-provider-v0.34.x/db/hld" | ||
"github.com/terra-money/mantlemint/lib" | ||
) | ||
|
||
var _ hld.HeightLimitEnabledBatch = (*LevelBatch)(nil) | ||
|
||
type LevelBatch struct { | ||
height int64 | ||
batch tmdb.Batch | ||
mode int | ||
} | ||
|
||
func (b *LevelBatch) keyBytesWithHeight(key []byte) []byte { | ||
if b.mode == DriverModeKeySuffixAsc { | ||
return append(prefixDataWithHeightKey(key), lib.UintToBigEndian(uint64(b.height))...) | ||
} else { | ||
return append(prefixDataWithHeightKey(key), lib.UintToBigEndian(math.MaxUint64-uint64(b.height))...) | ||
} | ||
|
||
} | ||
|
||
func NewLevelDBBatch(atHeight int64, driver *Driver) *LevelBatch { | ||
return &LevelBatch{ | ||
height: atHeight, | ||
batch: driver.session.NewBatch(), | ||
mode: driver.mode, | ||
} | ||
} | ||
|
||
func (b *LevelBatch) Set(key, value []byte) error { | ||
newKey := b.keyBytesWithHeight(key) | ||
|
||
// make fixed size byte slice for performance | ||
buf := make([]byte, 0, len(value)+1) | ||
buf = append(buf, byte(0)) // 0 => not deleted | ||
buf = append(buf, value...) | ||
|
||
if err := b.batch.Set(prefixCurrentDataKey(key), buf[1:]); err != nil { | ||
return err | ||
} | ||
if err := b.batch.Set(prefixKeysForIteratorKey(key), []byte{}); err != nil { | ||
return err | ||
} | ||
return b.batch.Set(newKey, buf) | ||
} | ||
|
||
func (b *LevelBatch) Delete(key []byte) error { | ||
newKey := b.keyBytesWithHeight(key) | ||
|
||
buf := []byte{1} | ||
|
||
if err := b.batch.Delete(prefixCurrentDataKey(key)); err != nil { | ||
return err | ||
} | ||
if err := b.batch.Set(prefixKeysForIteratorKey(key), buf); err != nil { | ||
return err | ||
} | ||
return b.batch.Set(newKey, buf) | ||
} | ||
|
||
func (b *LevelBatch) Write() error { | ||
return b.batch.Write() | ||
} | ||
|
||
func (b *LevelBatch) WriteSync() error { | ||
return b.batch.WriteSync() | ||
} | ||
|
||
func (b *LevelBatch) Close() error { | ||
return b.batch.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package heleveldb | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
|
||
tmdb "github.com/tendermint/tm-db" | ||
"github.com/terra-money/mantlemint-provider-v0.34.x/db/hld" | ||
"github.com/terra-money/mantlemint/lib" | ||
) | ||
|
||
type Driver struct { | ||
session *tmdb.GoLevelDB | ||
mode int | ||
} | ||
|
||
func NewLevelDBDriver(config *DriverConfig) (*Driver, error) { | ||
ldb, err := tmdb.NewGoLevelDB(config.Name, config.Dir) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &Driver{ | ||
session: ldb, | ||
mode: config.Mode, | ||
}, nil | ||
} | ||
|
||
func (d *Driver) newInnerIterator(requestHeight int64, pdb *tmdb.PrefixDB) (tmdb.Iterator, error) { | ||
if d.mode == DriverModeKeySuffixAsc { | ||
heightEnd := lib.UintToBigEndian(uint64(requestHeight + 1)) | ||
return pdb.ReverseIterator(nil, heightEnd) | ||
} else { | ||
heightStart := lib.UintToBigEndian(math.MaxUint64 - uint64(requestHeight)) | ||
return pdb.Iterator(heightStart, nil) | ||
} | ||
} | ||
|
||
func (d *Driver) Get(maxHeight int64, key []byte) ([]byte, error) { | ||
if maxHeight == 0 { | ||
return d.session.Get(prefixCurrentDataKey(key)) | ||
} | ||
var requestHeight = hld.Height(maxHeight).CurrentOrLatest().ToInt64() | ||
var requestHeightMin = hld.Height(0).CurrentOrNever().ToInt64() | ||
|
||
// check if requestHeightMin is | ||
if requestHeightMin > requestHeight { | ||
return nil, fmt.Errorf("invalid height") | ||
} | ||
|
||
pdb := tmdb.NewPrefixDB(d.session, prefixDataWithHeightKey(key)) | ||
|
||
iter, _ := d.newInnerIterator(requestHeight, pdb) | ||
defer iter.Close() | ||
|
||
// in tm-db@v0.6.4, key not found is NOT an error | ||
if !iter.Valid() { | ||
return nil, nil | ||
} | ||
|
||
value := iter.Value() | ||
deleted := value[0] | ||
if deleted == 1 { | ||
return nil, nil | ||
} else { | ||
if len(value) > 1 { | ||
return value[1:], nil | ||
} | ||
return []byte{}, nil | ||
} | ||
} | ||
|
||
func (d *Driver) Has(maxHeight int64, key []byte) (bool, error) { | ||
if maxHeight == 0 { | ||
return d.session.Has(prefixCurrentDataKey(key)) | ||
} | ||
var requestHeight = hld.Height(maxHeight).CurrentOrLatest().ToInt64() | ||
var requestHeightMin = hld.Height(0).CurrentOrNever().ToInt64() | ||
|
||
// check if requestHeightMin is | ||
if requestHeightMin > requestHeight { | ||
return false, fmt.Errorf("invalid height") | ||
} | ||
|
||
pdb := tmdb.NewPrefixDB(d.session, prefixDataWithHeightKey(key)) | ||
|
||
iter, _ := d.newInnerIterator(requestHeight, pdb) | ||
defer iter.Close() | ||
|
||
// in tm-db@v0.6.4, key not found is NOT an error | ||
if !iter.Valid() { | ||
return false, nil | ||
} | ||
|
||
deleted := iter.Value()[0] | ||
|
||
if deleted == 1 { | ||
return false, nil | ||
} else { | ||
return true, nil | ||
} | ||
} | ||
|
||
func (d *Driver) Set(atHeight int64, key, value []byte) error { | ||
// should never reach here, all should be batched in tiered+hld | ||
panic("should never reach here") | ||
} | ||
|
||
func (d *Driver) SetSync(atHeight int64, key, value []byte) error { | ||
// should never reach here, all should be batched in tiered+hld | ||
panic("should never reach here") | ||
} | ||
|
||
func (d *Driver) Delete(atHeight int64, key []byte) error { | ||
// should never reach here, all should be batched in tiered+hld | ||
panic("should never reach here") | ||
} | ||
|
||
func (d *Driver) DeleteSync(atHeight int64, key []byte) error { | ||
return d.Delete(atHeight, key) | ||
} | ||
|
||
func (d *Driver) Iterator(maxHeight int64, start, end []byte) (hld.HeightLimitEnabledIterator, error) { | ||
if maxHeight == 0 { | ||
pdb := tmdb.NewPrefixDB(d.session, cCurrentDataPrefix) | ||
return pdb.Iterator(start, end) | ||
} | ||
return NewLevelDBIterator(d, maxHeight, start, end) | ||
} | ||
|
||
func (d *Driver) ReverseIterator(maxHeight int64, start, end []byte) (hld.HeightLimitEnabledIterator, error) { | ||
if maxHeight == 0 { | ||
pdb := tmdb.NewPrefixDB(d.session, cCurrentDataPrefix) | ||
return pdb.ReverseIterator(start, end) | ||
} | ||
return NewLevelDBReverseIterator(d, maxHeight, start, end) | ||
} | ||
|
||
func (d *Driver) Close() error { | ||
d.session.Close() | ||
return nil | ||
} | ||
|
||
func (d *Driver) NewBatch(atHeight int64) hld.HeightLimitEnabledBatch { | ||
return NewLevelDBBatch(atHeight, d) | ||
} | ||
|
||
// TODO: Implement me | ||
func (d *Driver) Print() error { | ||
return nil | ||
} | ||
|
||
func (d *Driver) Stats() map[string]string { | ||
return nil | ||
} |
Oops, something went wrong.