cmd/utils, node: switch to Pebble as the default db if none exists (#27136)

* cmd/utils, node: switch to Pebble as the default db if none exists

* node: fall back to LevelDB on platforms not supporting Pebble

* core/rawdb, node: default to Pebble at the node level

* cmd/geth: fix some tests explicitly using leveldb

* ethdb/pebble: allow double closes, makes tests simpler
This commit is contained in:
Péter Szilágyi 2023-04-21 19:24:18 +03:00 committed by GitHub
parent bbc565ab05
commit d3ece3a07c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 28 deletions

View File

@ -121,7 +121,7 @@ func testDAOForkBlockNewChain(t *testing.T, test int, genesis string, expectBloc
} }
// Retrieve the DAO config flag from the database // Retrieve the DAO config flag from the database
path := filepath.Join(datadir, "geth", "chaindata") path := filepath.Join(datadir, "geth", "chaindata")
db, err := rawdb.NewLevelDBDatabase(path, 0, 0, "", false) db, err := rawdb.NewPebbleDBDatabase(path, 0, 0, "", false)
if err != nil { if err != nil {
t.Fatalf("test %d: failed to open test database: %v", test, err) t.Fatalf("test %d: failed to open test database: %v", test, err)
} }

View File

@ -146,8 +146,8 @@ func TestCustomBackend(t *testing.T) {
return nil return nil
} }
for i, tt := range []backendTest{ for i, tt := range []backendTest{
{ // When not specified, it should default to leveldb { // When not specified, it should default to pebble
execArgs: []string{"--db.engine", "leveldb"}, execArgs: []string{"--db.engine", "pebble"},
execExpect: "0x0000000000001338", execExpect: "0x0000000000001338",
}, },
{ // Explicit leveldb { // Explicit leveldb

View File

@ -101,8 +101,8 @@ var (
} }
DBEngineFlag = &cli.StringFlag{ DBEngineFlag = &cli.StringFlag{
Name: "db.engine", Name: "db.engine",
Usage: "Backing database implementation to use ('leveldb' or 'pebble')", Usage: "Backing database implementation to use ('pebble' or 'leveldb')",
Value: "leveldb", Value: node.DefaultConfig.DBEngine,
Category: flags.EthCategory, Category: flags.EthCategory,
} }
AncientFlag = &flags.DirectoryFlag{ AncientFlag = &flags.DirectoryFlag{

View File

@ -358,9 +358,15 @@ type OpenOptions struct {
// //
// type == null type != null // type == null type != null
// +---------------------------------------- // +----------------------------------------
// db is non-existent | leveldb default | specified type // db is non-existent | pebble default | specified type
// db is existent | from db | specified type (if compatible) // db is existent | from db | specified type (if compatible)
func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) { func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
// Reject any unsupported database type
if len(o.Type) != 0 && o.Type != dbLeveldb && o.Type != dbPebble {
return nil, fmt.Errorf("unknown db.engine %v", o.Type)
}
// Retrieve any pre-existing database's type and use that or the requested one
// as long as there's no conflict between the two types
existingDb := hasPreexistingDb(o.Directory) existingDb := hasPreexistingDb(o.Directory)
if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb { if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb {
return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb) return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb)
@ -373,12 +379,19 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
return nil, errors.New("db.engine 'pebble' not supported on this platform") return nil, errors.New("db.engine 'pebble' not supported on this platform")
} }
} }
if len(o.Type) != 0 && o.Type != dbLeveldb { if o.Type == dbLeveldb || existingDb == dbLeveldb {
return nil, fmt.Errorf("unknown db.engine %v", o.Type) log.Info("Using leveldb as the backing database")
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
}
// No pre-existing database, no user-requested one either. Default to Pebble
// on supported platforms and LevelDB on anything else.
if PebbleEnabled {
log.Info("Defaulting to pebble as the backing database")
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
} else {
log.Info("Defaulting to leveldb as the backing database")
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
} }
log.Info("Using leveldb as the backing database")
// Use leveldb, either as default (no explicit choice), or pre-existing, or chosen explicitly
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
} }
// Open opens both a disk-based key-value database such as leveldb or pebble, but also // Open opens both a disk-based key-value database such as leveldb or pebble, but also

View File

@ -222,14 +222,17 @@ func (d *Database) Close() error {
d.quitLock.Lock() d.quitLock.Lock()
defer d.quitLock.Unlock() defer d.quitLock.Unlock()
if d.quitChan != nil { // Allow double closing, simplifies things
errc := make(chan error) if d.quitChan == nil {
d.quitChan <- errc return nil
if err := <-errc; err != nil {
d.log.Error("Metrics collection failed", "err", err)
}
d.quitChan = nil
} }
errc := make(chan error)
d.quitChan <- errc
if err := <-errc; err != nil {
d.log.Error("Metrics collection failed", "err", err)
}
d.quitChan = nil
return d.db.Close() return d.db.Close()
} }

View File

@ -28,14 +28,12 @@ import (
) )
const ( const (
DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server
DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server
DefaultWSHost = "localhost" // Default host interface for the websocket RPC server DefaultWSHost = "localhost" // Default host interface for the websocket RPC server
DefaultWSPort = 8546 // Default TCP port for the websocket RPC server DefaultWSPort = 8546 // Default TCP port for the websocket RPC server
DefaultGraphQLHost = "localhost" // Default host interface for the GraphQL server DefaultAuthHost = "localhost" // Default host interface for the authenticated apis
DefaultGraphQLPort = 8547 // Default TCP port for the GraphQL server DefaultAuthPort = 8551 // Default port for the authenticated apis
DefaultAuthHost = "localhost" // Default host interface for the authenticated apis
DefaultAuthPort = 8551 // Default port for the authenticated apis
) )
var ( var (
@ -64,7 +62,7 @@ var DefaultConfig = Config{
MaxPeers: 50, MaxPeers: 50,
NAT: nat.Any(), NAT: nat.Any(),
}, },
DBEngine: "", DBEngine: "", // Use whatever exists, will default to Pebble if non-existent and supported
} }
// DefaultDataDir is the default data directory to use for the databases and other // DefaultDataDir is the default data directory to use for the databases and other