all: add read-only option to database (#22407)
* all: add read-only option to database * all: fixes tests * cmd/geth: migrate flags * cmd/geth: fix the compact * cmd/geth: fix the format * cmd/geth: fix log * cmd: add chain-readonly * core: add readonly notion to freezer * core/rawdb: add log * core/rawdb: fix freezer close * cmd: fix * cmd, core: construct db * core: update tests
This commit is contained in:
@ -35,6 +35,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// errReadOnly is returned if the freezer is opened in read only mode. All the
|
||||
// mutations are disallowed.
|
||||
errReadOnly = errors.New("read only")
|
||||
|
||||
// errUnknownTable is returned if the user attempts to read from a table that is
|
||||
// not tracked by the freezer.
|
||||
errUnknownTable = errors.New("unknown table")
|
||||
@ -73,6 +77,7 @@ type freezer struct {
|
||||
frozen uint64 // Number of blocks already frozen
|
||||
threshold uint64 // Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests)
|
||||
|
||||
readonly bool
|
||||
tables map[string]*freezerTable // Data tables for storing everything
|
||||
instanceLock fileutil.Releaser // File-system lock to prevent double opens
|
||||
|
||||
@ -84,7 +89,7 @@ type freezer struct {
|
||||
|
||||
// newFreezer creates a chain freezer that moves ancient chain data into
|
||||
// append-only flat file containers.
|
||||
func newFreezer(datadir string, namespace string) (*freezer, error) {
|
||||
func newFreezer(datadir string, namespace string, readonly bool) (*freezer, error) {
|
||||
// Create the initial freezer object
|
||||
var (
|
||||
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
|
||||
@ -106,6 +111,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
||||
}
|
||||
// Open all the supported data tables
|
||||
freezer := &freezer{
|
||||
readonly: readonly,
|
||||
threshold: params.FullImmutabilityThreshold,
|
||||
tables: make(map[string]*freezerTable),
|
||||
instanceLock: lock,
|
||||
@ -130,7 +136,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
||||
lock.Release()
|
||||
return nil, err
|
||||
}
|
||||
log.Info("Opened ancient database", "database", datadir)
|
||||
log.Info("Opened ancient database", "database", datadir, "readonly", readonly)
|
||||
return freezer, nil
|
||||
}
|
||||
|
||||
@ -138,7 +144,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
||||
func (f *freezer) Close() error {
|
||||
var errs []error
|
||||
f.closeOnce.Do(func() {
|
||||
f.quit <- struct{}{}
|
||||
close(f.quit)
|
||||
for _, table := range f.tables {
|
||||
if err := table.Close(); err != nil {
|
||||
errs = append(errs, err)
|
||||
@ -191,6 +197,9 @@ func (f *freezer) AncientSize(kind string) (uint64, error) {
|
||||
// injection will be rejected. But if two injections with same number happen at
|
||||
// the same time, we can get into the trouble.
|
||||
func (f *freezer) AppendAncient(number uint64, hash, header, body, receipts, td []byte) (err error) {
|
||||
if f.readonly {
|
||||
return errReadOnly
|
||||
}
|
||||
// Ensure the binary blobs we are appending is continuous with freezer.
|
||||
if atomic.LoadUint64(&f.frozen) != number {
|
||||
return errOutOrderInsertion
|
||||
@ -233,6 +242,9 @@ func (f *freezer) AppendAncient(number uint64, hash, header, body, receipts, td
|
||||
|
||||
// TruncateAncients discards any recent data above the provided threshold number.
|
||||
func (f *freezer) TruncateAncients(items uint64) error {
|
||||
if f.readonly {
|
||||
return errReadOnly
|
||||
}
|
||||
if atomic.LoadUint64(&f.frozen) <= items {
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user