|
|
@@ -73,6 +73,7 @@ type freezer struct {
|
|
|
|
|
|
tables map[string]*freezerTable // Data tables for storing everything
|
|
|
instanceLock fileutil.Releaser // File-system lock to prevent double opens
|
|
|
+ quit chan struct{}
|
|
|
}
|
|
|
|
|
|
// newFreezer creates a chain freezer that moves ancient chain data into
|
|
|
@@ -101,6 +102,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
|
|
freezer := &freezer{
|
|
|
tables: make(map[string]*freezerTable),
|
|
|
instanceLock: lock,
|
|
|
+ quit: make(chan struct{}),
|
|
|
}
|
|
|
for name, disableSnappy := range freezerNoSnappy {
|
|
|
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy)
|
|
|
@@ -126,6 +128,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
|
|
|
|
|
|
// Close terminates the chain freezer, unmapping all the data files.
|
|
|
func (f *freezer) Close() error {
|
|
|
+ f.quit <- struct{}{}
|
|
|
var errs []error
|
|
|
for _, table := range f.tables {
|
|
|
if err := table.Close(); err != nil {
|
|
|
@@ -254,35 +257,50 @@ func (f *freezer) Sync() error {
|
|
|
func (f *freezer) freeze(db ethdb.KeyValueStore) {
|
|
|
nfdb := &nofreezedb{KeyValueStore: db}
|
|
|
|
|
|
+ backoff := false
|
|
|
for {
|
|
|
+ select {
|
|
|
+ case <-f.quit:
|
|
|
+ log.Info("Freezer shutting down")
|
|
|
+ return
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ if backoff {
|
|
|
+ select {
|
|
|
+ case <-time.NewTimer(freezerRecheckInterval).C:
|
|
|
+ backoff = false
|
|
|
+ case <-f.quit:
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
// Retrieve the freezing threshold.
|
|
|
hash := ReadHeadBlockHash(nfdb)
|
|
|
if hash == (common.Hash{}) {
|
|
|
log.Debug("Current full block hash unavailable") // new chain, empty database
|
|
|
- time.Sleep(freezerRecheckInterval)
|
|
|
+ backoff = true
|
|
|
continue
|
|
|
}
|
|
|
number := ReadHeaderNumber(nfdb, hash)
|
|
|
switch {
|
|
|
case number == nil:
|
|
|
log.Error("Current full block number unavailable", "hash", hash)
|
|
|
- time.Sleep(freezerRecheckInterval)
|
|
|
+ backoff = true
|
|
|
continue
|
|
|
|
|
|
case *number < params.ImmutabilityThreshold:
|
|
|
log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", params.ImmutabilityThreshold)
|
|
|
- time.Sleep(freezerRecheckInterval)
|
|
|
+ backoff = true
|
|
|
continue
|
|
|
|
|
|
case *number-params.ImmutabilityThreshold <= f.frozen:
|
|
|
log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", f.frozen)
|
|
|
- time.Sleep(freezerRecheckInterval)
|
|
|
+ backoff = true
|
|
|
continue
|
|
|
}
|
|
|
head := ReadHeader(nfdb, hash, *number)
|
|
|
if head == nil {
|
|
|
log.Error("Current full block unavailable", "number", *number, "hash", hash)
|
|
|
- time.Sleep(freezerRecheckInterval)
|
|
|
+ backoff = true
|
|
|
continue
|
|
|
}
|
|
|
// Seems we have data ready to be frozen, process in usable batches
|
|
|
@@ -369,7 +387,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) {
|
|
|
|
|
|
// Avoid database thrashing with tiny writes
|
|
|
if f.frozen-first < freezerBatchLimit {
|
|
|
- time.Sleep(freezerRecheckInterval)
|
|
|
+ backoff = true
|
|
|
}
|
|
|
}
|
|
|
}
|