@@ -12,6 +12,7 @@ import (
1212 "time"
1313
1414 gcemd "cloud.google.com/go/compute/metadata"
15+ "github.com/cockroachdb/pebble"
1516 "github.com/dgraph-io/badger/v2"
1617 "github.com/hashicorp/go-multierror"
1718 dht "github.com/libp2p/go-libp2p-kad-dht"
@@ -20,6 +21,7 @@ import (
2021 "github.com/libp2p/go-libp2p/core/routing"
2122 "github.com/prometheus/client_golang/prometheus"
2223 "github.com/rs/zerolog"
24+ "github.com/rs/zerolog/log"
2325 "github.com/spf13/pflag"
2426 "golang.org/x/time/rate"
2527 "google.golang.org/api/option"
@@ -31,6 +33,7 @@ import (
3133 "github.com/onflow/flow-go/admin/commands/common"
3234 storageCommands "github.com/onflow/flow-go/admin/commands/storage"
3335 "github.com/onflow/flow-go/cmd/build"
36+ "github.com/onflow/flow-go/cmd/scaffold"
3437 "github.com/onflow/flow-go/config"
3538 "github.com/onflow/flow-go/consensus/hotstuff/persister"
3639 "github.com/onflow/flow-go/fvm/initialize"
@@ -164,6 +167,7 @@ func (fnb *FlowNodeBuilder) BaseFlags() {
164167 fnb .flags .StringVar (& fnb .BaseConfig .BindAddr , "bind" , defaultConfig .BindAddr , "address to bind on" )
165168 fnb .flags .StringVarP (& fnb .BaseConfig .BootstrapDir , "bootstrapdir" , "b" , defaultConfig .BootstrapDir , "path to the bootstrap directory" )
166169 fnb .flags .StringVarP (& fnb .BaseConfig .datadir , "datadir" , "d" , defaultConfig .datadir , "directory to store the public database (protocol state)" )
170+ fnb .flags .StringVar (& fnb .BaseConfig .pebbleDir , "pebble-dir" , defaultConfig .pebbleDir , "directory to store the public pebble database (protocol state)" )
167171 fnb .flags .StringVar (& fnb .BaseConfig .secretsdir , "secretsdir" , defaultConfig .secretsdir , "directory to store private database (secrets)" )
168172 fnb .flags .StringVarP (& fnb .BaseConfig .level , "loglevel" , "l" , defaultConfig .level , "level for logging output" )
169173 fnb .flags .Uint32Var (& fnb .BaseConfig .debugLogLimit , "debug-log-limit" , defaultConfig .debugLogLimit , "max number of debug/trace log events per second" )
@@ -1057,14 +1061,22 @@ func (fnb *FlowNodeBuilder) initProfiler() error {
10571061 return nil
10581062}
10591063
1060- func (fnb * FlowNodeBuilder ) initDB () error {
1061-
1062- // if a db has been passed in, use that instead of creating one
1063- if fnb .BaseConfig .db != nil {
1064- fnb .DB = fnb .BaseConfig .db
1064+ func (fnb * FlowNodeBuilder ) initBadgerDB () error {
1065+ // if the badger DB is already set, use it.
1066+ // the badger DB might be set by the follower engine
1067+ if fnb .BaseConfig .badgerDB != nil {
1068+ fnb .DB = fnb .BaseConfig .badgerDB
10651069 return nil
10661070 }
10671071
1072+ // if the badger DB is not set, then the datadir must be provided to initialize
1073+ // the badger DB
1074+ // since we've set an default directory for the badger DB, this check
1075+ // is not necessary, but rather a sanity check
1076+ if fnb .BaseConfig .datadir == NotSet {
1077+ return fmt .Errorf ("missing required flag '--datadir'" )
1078+ }
1079+
10681080 // Pre-create DB path (Badger creates only one-level dirs)
10691081 err := os .MkdirAll (fnb .BaseConfig .datadir , 0700 )
10701082 if err != nil {
@@ -1111,6 +1123,24 @@ func (fnb *FlowNodeBuilder) initDB() error {
11111123 return nil
11121124}
11131125
1126+ func (fnb * FlowNodeBuilder ) initPebbleDB () error {
1127+ // if the pebble DB is already set, use it
1128+ // the pebble DB might be set by the follower engine
1129+ if fnb .BaseConfig .pebbleDB != nil {
1130+ fnb .PebbleDB = fnb .BaseConfig .pebbleDB
1131+ return nil
1132+ }
1133+
1134+ db , closer , err := scaffold .InitPebbleDB (fnb .BaseConfig .pebbleDir )
1135+ if err != nil {
1136+ return err
1137+ }
1138+
1139+ fnb .PebbleDB = db
1140+ fnb .ShutdownFunc (closer .Close )
1141+ return nil
1142+ }
1143+
11141144func (fnb * FlowNodeBuilder ) initSecretsDB () error {
11151145
11161146 // if the secrets DB is disabled (only applicable for Consensus Follower,
@@ -1888,11 +1918,55 @@ func WithBindAddress(bindAddress string) Option {
18881918 }
18891919}
18901920
1921+ // WithDataDir set the data directory for the badger database
1922+ // It will be ignored if WithBadgerDB is used
18911923func WithDataDir (dataDir string ) Option {
18921924 return func (config * BaseConfig ) {
1893- if config .db == nil {
1894- config .datadir = dataDir
1925+ if config .badgerDB != nil {
1926+ log .Warn ().Msgf ("ignoring data directory %s as badger database is already set" , dataDir )
1927+ return
1928+ }
1929+
1930+ config .datadir = dataDir
1931+ }
1932+ }
1933+
1934+ // WithBadgerDB sets the badger database instance
1935+ // If used, then WithDataDir method will be ignored
1936+ func WithBadgerDB (db * badger.DB ) Option {
1937+ return func (config * BaseConfig ) {
1938+ if config .datadir != "" && config .datadir != NotSet {
1939+ log .Warn ().Msgf ("ignoring data directory is already set for badger %v" , config .datadir )
1940+ config .datadir = ""
18951941 }
1942+
1943+ config .badgerDB = db
1944+ }
1945+ }
1946+
1947+ // WithPebbleDir set the data directory for the pebble database
1948+ // It will be ignored if WithPebbleDB is used
1949+ func WithPebbleDir (dataDir string ) Option {
1950+ return func (config * BaseConfig ) {
1951+ if config .pebbleDB != nil {
1952+ log .Warn ().Msgf ("ignoring data directory %s as pebble database is already set" , dataDir )
1953+ return
1954+ }
1955+
1956+ config .pebbleDir = dataDir
1957+ }
1958+ }
1959+
1960+ // WithPebbleDB sets the pebble database instance
1961+ // If used, then WithPebbleDir method will be ignored
1962+ func WithPebbleDB (db * pebble.DB ) Option {
1963+ return func (config * BaseConfig ) {
1964+ if config .pebbleDir != "" && config .pebbleDir != NotSet {
1965+ log .Warn ().Msgf ("ignoring data directory is already set for pebble %v" , config .pebbleDir )
1966+ config .pebbleDir = ""
1967+ }
1968+
1969+ config .pebbleDB = db
18961970 }
18971971}
18981972
@@ -1926,14 +2000,6 @@ func WithLogLevel(level string) Option {
19262000 }
19272001}
19282002
1929- // WithDB takes precedence over WithDataDir and datadir will be set to empty if DB is set using this option
1930- func WithDB (db * badger.DB ) Option {
1931- return func (config * BaseConfig ) {
1932- config .db = db
1933- config .datadir = ""
1934- }
1935- }
1936-
19372003// FlowNode creates a new Flow node builder with the given name.
19382004func FlowNode (role string , opts ... Option ) * FlowNodeBuilder {
19392005 config := DefaultBaseConfig ()
@@ -2039,7 +2105,13 @@ func (fnb *FlowNodeBuilder) onStart() error {
20392105 return err
20402106 }
20412107
2042- if err := fnb .initDB (); err != nil {
2108+ // we always initialize both badger and pebble databases
2109+ // even if we only use one of them, this simplify the code and checks
2110+ if err := fnb .initBadgerDB (); err != nil {
2111+ return err
2112+ }
2113+
2114+ if err := fnb .initPebbleDB (); err != nil {
20432115 return err
20442116 }
20452117
0 commit comments