core/rawdb: add file lock for freezer
This commit is contained in:
parent
b69bdc2a4f
commit
b6cac42e9f
@ -17,6 +17,8 @@
|
|||||||
package rawdb
|
package rawdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/leveldb"
|
"github.com/ethereum/go-ethereum/ethdb/leveldb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||||
@ -25,7 +27,23 @@ import (
|
|||||||
// freezerdb is a databse wrapper that enabled freezer data retrievals.
|
// freezerdb is a databse wrapper that enabled freezer data retrievals.
|
||||||
type freezerdb struct {
|
type freezerdb struct {
|
||||||
ethdb.KeyValueStore
|
ethdb.KeyValueStore
|
||||||
ethdb.Ancienter
|
ethdb.AncientStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close implements io.Closer, closing both the fast key-value store as well as
|
||||||
|
// the slow ancient tables.
|
||||||
|
func (frdb *freezerdb) Close() error {
|
||||||
|
var errs []error
|
||||||
|
if err := frdb.KeyValueStore.Close(); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
if err := frdb.AncientStore.Close(); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
if len(errs) != 0 {
|
||||||
|
return fmt.Errorf("%v", errs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nofreezedb is a database wrapper that disables freezer data retrievals.
|
// nofreezedb is a database wrapper that disables freezer data retrievals.
|
||||||
@ -58,7 +76,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
|
|||||||
|
|
||||||
return &freezerdb{
|
return &freezerdb{
|
||||||
KeyValueStore: db,
|
KeyValueStore: db,
|
||||||
Ancienter: frdb,
|
AncientStore: frdb,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"path/filepath"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
"github.com/prometheus/tsdb/fileutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// errUnknownTable is returned if the user attempts to read from a table that is
|
// errUnknownTable is returned if the user attempts to read from a table that is
|
||||||
@ -57,8 +59,9 @@ const (
|
|||||||
// reserving it for go-ethereum. This would also reduce the memory requirements
|
// reserving it for go-ethereum. This would also reduce the memory requirements
|
||||||
// of Geth, and thus also GC overhead.
|
// of Geth, and thus also GC overhead.
|
||||||
type freezer struct {
|
type freezer struct {
|
||||||
tables map[string]*freezerTable // Data tables for storing everything
|
tables map[string]*freezerTable // Data tables for storing everything
|
||||||
frozen uint64 // Number of blocks already frozen
|
frozen uint64 // Number of blocks already frozen
|
||||||
|
instanceLock fileutil.Releaser // File-system lock to prevent double opens
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFreezer creates a chain freezer that moves ancient chain data into
|
// newFreezer creates a chain freezer that moves ancient chain data into
|
||||||
@ -69,9 +72,14 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
|||||||
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
|
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
|
||||||
writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil)
|
writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil)
|
||||||
)
|
)
|
||||||
|
lock, _, err := fileutil.Flock(filepath.Join(datadir, "LOCK"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
// Open all the supported data tables
|
// Open all the supported data tables
|
||||||
freezer := &freezer{
|
freezer := &freezer{
|
||||||
tables: make(map[string]*freezerTable),
|
tables: make(map[string]*freezerTable),
|
||||||
|
instanceLock: lock,
|
||||||
}
|
}
|
||||||
for _, name := range []string{"hashes", "headers", "bodies", "receipts", "diffs"} {
|
for _, name := range []string{"hashes", "headers", "bodies", "receipts", "diffs"} {
|
||||||
table, err := newTable(datadir, name, readMeter, writeMeter)
|
table, err := newTable(datadir, name, readMeter, writeMeter)
|
||||||
@ -79,6 +87,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
|||||||
for _, table := range freezer.tables {
|
for _, table := range freezer.tables {
|
||||||
table.Close()
|
table.Close()
|
||||||
}
|
}
|
||||||
|
lock.Release()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
freezer.tables[name] = table
|
freezer.tables[name] = table
|
||||||
@ -95,6 +104,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
|||||||
for _, table := range freezer.tables {
|
for _, table := range freezer.tables {
|
||||||
table.Close()
|
table.Close()
|
||||||
}
|
}
|
||||||
|
lock.Release()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,6 +119,9 @@ func (f *freezer) Close() error {
|
|||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := f.instanceLock.Release(); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
return fmt.Errorf("%v", errs)
|
return fmt.Errorf("%v", errs)
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,13 @@ type AncientReader interface {
|
|||||||
Ancienter
|
Ancienter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AncientStore contains all the methods required to allow handling different
|
||||||
|
// ancient data stores backing immutable chain data store.
|
||||||
|
type AncientStore interface {
|
||||||
|
Ancienter
|
||||||
|
io.Closer
|
||||||
|
}
|
||||||
|
|
||||||
// Database contains all the methods required by the high level database to not
|
// Database contains all the methods required by the high level database to not
|
||||||
// only access the key-value data store but also the chain freezer.
|
// only access the key-value data store but also the chain freezer.
|
||||||
type Database interface {
|
type Database interface {
|
||||||
|
Loading…
Reference in New Issue
Block a user