Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Archive migration online #75

Merged
merged 7 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.19

require (
github.com/alitto/pond v1.8.3
github.com/armon/go-metrics v0.4.1
github.com/cockroachdb/pebble v0.0.0-20230819001538-1798fbf5956c
github.com/confio/ics23/go v0.9.0
github.com/cosmos/iavl v0.21.0-alpha.1.0.20230904092046-df3db2d96583
Expand Down Expand Up @@ -45,6 +46,8 @@ require (
github.com/google/btree v1.1.2 // indirect
github.com/google/flatbuffers v1.12.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI=
Expand Down Expand Up @@ -547,6 +549,7 @@ github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
Expand All @@ -557,13 +560,16 @@ github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR3
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
Expand Down Expand Up @@ -843,6 +849,7 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
Expand Down
91 changes: 83 additions & 8 deletions ss/pebbledb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"sync"
"time"

"github.com/armon/go-metrics"
"github.com/cockroachdb/pebble"
"github.com/cockroachdb/pebble/bloom"
errorutils "github.com/sei-protocol/sei-db/common/errors"
Expand All @@ -25,12 +26,14 @@
const (
VersionSize = 8

PrefixStore = "s/k:"
LenPrefixStore = 4
StorePrefixTpl = "s/k:%s/" // s/k:<storeKey>
latestVersionKey = "s/_latest" // NB: latestVersionKey key must be lexically smaller than StorePrefixTpl
earliestVersionKey = "s/_earliest"
tombstoneVal = "TOMBSTONE"
PrefixStore = "s/k:"
LenPrefixStore = 4
StorePrefixTpl = "s/k:%s/" // s/k:<storeKey>
latestVersionKey = "s/_latest" // NB: latestVersionKey key must be lexically smaller than StorePrefixTpl
earliestVersionKey = "s/_earliest"
latestMigratedKeyMetadata = "s/_latestMigratedKey"
latestMigratedModuleMetadata = "s/_latestMigratedModule"
tombstoneVal = "TOMBSTONE"

// TODO: Make configurable
ImportCommitBatchSize = 10000
Expand Down Expand Up @@ -155,7 +158,9 @@
func (db *Database) SetLatestVersion(version int64) error {
var ts [VersionSize]byte
binary.LittleEndian.PutUint64(ts[:], uint64(version))
return db.storage.Set([]byte(latestVersionKey), ts[:], defaultWriteOpts)
err := db.storage.Set([]byte(latestVersionKey), ts[:], defaultWriteOpts)
fmt.Printf("SetLatestVersion: version=%d, err=%v, latestVersionKey=%s\n", version, err, latestVersionKey)
return err
}

func (db *Database) GetLatestVersion() (int64, error) {
Expand Down Expand Up @@ -210,6 +215,42 @@
return int64(binary.LittleEndian.Uint64(bz)), closer.Close()
}

// SetLatestKey sets the latest key processed during migration.
func (db *Database) SetLatestMigratedKey(key []byte) error {
return db.storage.Set([]byte(latestMigratedKeyMetadata), key, defaultWriteOpts)
}

// GetLatestKey retrieves the latest key processed during migration.
func (db *Database) GetLatestMigratedKey() ([]byte, error) {
bz, closer, err := db.storage.Get([]byte(latestMigratedKeyMetadata))
if err != nil {
if errors.Is(err, pebble.ErrNotFound) {
return nil, nil
}
return nil, err
}
defer closer.Close()
return bz, nil
}

// SetLatestModule sets the latest module processed during migration.
func (db *Database) SetLatestMigratedModule(module string) error {
return db.storage.Set([]byte(latestMigratedModuleMetadata), []byte(module), defaultWriteOpts)
}

// GetLatestModule retrieves the latest module processed during migration.
func (db *Database) GetLatestMigratedModule() (string, error) {
bz, closer, err := db.storage.Get([]byte(latestMigratedModuleMetadata))
if err != nil {
if errors.Is(err, pebble.ErrNotFound) {
return "", nil
}
return "", err
}
defer closer.Close()
return string(bz), nil
}

func (db *Database) Has(storeKey string, version int64, key []byte) (bool, error) {
if version < db.earliestVersion {
return false, nil
Expand Down Expand Up @@ -341,7 +382,7 @@
// We add a heuristic to skip over a module's keys during pruning if it hasn't been updated
// since the last time pruning occurred.
// NOTE: There is a rare case when a module's keys are skipped during pruning even though
// it has been updated. This occurs when that module is updated in between pruning runs, the node after is restarted.
// it has been updated. This occurs when that module's keys are updated in between pruning runs, the node after is restarted.
// This is not a large issue given the next time that module is updated, it will be properly pruned thereafter.
func (db *Database) Prune(version int64) error {
earliestVersion := version + 1 // we increment by 1 to include the provided version
Expand Down Expand Up @@ -556,29 +597,63 @@
}

var counter int
var latestKey []byte // store the latest key from the batch
var latestModule string
for entry := range ch {
err := batch.Set(entry.StoreKey, entry.Key, entry.Value, entry.Version)
if err != nil {
panic(err)
}

latestKey = entry.Key // track the latest key
latestModule = entry.StoreKey
counter++

if counter%ImportCommitBatchSize == 0 {
startTime := time.Now()

Check warning

Code scanning / CodeQL

Calling the system time Warning

Calling the system time may be a possible source of non-determinism

// Commit the batch and record the latest key as metadata
if err := batch.Write(); err != nil {
panic(err)
}

// Persist the latest key in the metadata
if err := db.SetLatestMigratedKey(latestKey); err != nil {
panic(err)
}

if err := db.SetLatestMigratedModule(latestModule); err != nil {
panic(err)
}

if counter%1000000 == 0 {
fmt.Printf("Time taken to write batch counter %d: %v\n", counter, time.Since(startTime))
metrics.IncrCounterWithLabels([]string{"sei", "migration", "nodes_imported"}, float32(1000000), []metrics.Label{
{Name: "module", Value: latestModule},
})
}

batch, err = NewRawBatch(db.storage)
if err != nil {
panic(err)
}
}
}

// Final batch write
if batch.Size() > 0 {
if err := batch.Write(); err != nil {
panic(err)
}

// Persist the final latest key
if err := db.SetLatestMigratedKey(latestKey); err != nil {
panic(err)
}

if err := db.SetLatestMigratedModule(latestModule); err != nil {
panic(err)
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions ss/types/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ type StateStore interface {
SetLatestVersion(version int64) error
GetEarliestVersion() (int64, error)
SetEarliestVersion(version int64) error
GetLatestMigratedKey() ([]byte, error)
SetLatestMigratedKey(key []byte) error
GetLatestMigratedModule() (string, error)
SetLatestMigratedModule(module string) error

// ApplyChangeset Persist the change set of a block,
// the `changeSet` should be ordered by (storeKey, key),
Expand Down
Loading