force disk flush when caught up to current

This commit is contained in:
Brannon King 2021-07-27 15:10:17 -04:00 committed by Roy Lee
parent 0a01170422
commit 82d4b6657b
18 changed files with 109 additions and 18 deletions

View file

@ -574,15 +574,9 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block,
"spent transaction out information")
}
// Handle LBRY Claim Scripts
if b.claimTrie != nil {
if err := b.ParseClaimScripts(block, node, view, false); err != nil {
return ruleError(ErrBadClaimTrie, err.Error())
}
}
// No warnings about unknown rules until the chain is current.
if b.isCurrent() {
current := b.isCurrent()
if current {
// Warn if any unknown new rules are either about to activate or
// have already been activated.
if err := b.warnUnknownRuleActivations(node); err != nil {
@ -590,6 +584,13 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block,
}
}
// Handle LBRY Claim Scripts
if b.claimTrie != nil {
if err := b.ParseClaimScripts(block, node, view, false, current); err != nil {
return ruleError(ErrBadClaimTrie, err.Error())
}
}
// Write any block status changes to DB before updating best state.
err := b.index.flushToDB()
if err != nil {
@ -1223,7 +1224,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla
// factors are used to guess, but the key factors that allow the chain to
// believe it is current are:
// - Latest block height is after the latest checkpoint (if enabled)
// - Latest block has a timestamp newer than 24 hours ago
// - Latest block has a timestamp newer than ~6 hours ago (as LBRY block time is one fourth of bitcoin)
//
// This function MUST be called with the chain state lock held (for reads).
func (b *BlockChain) isCurrent() bool {
@ -1234,13 +1235,13 @@ func (b *BlockChain) isCurrent() bool {
return false
}
// Not current if the latest best block has a timestamp before 24 hours
// Not current if the latest best block has a timestamp before 7 hours
// ago.
//
// The chain appears to be current if none of the checks reported
// otherwise.
minus24Hours := b.timeSource.AdjustedTime().Add(-24 * time.Hour).Unix()
return b.bestChain.Tip().timestamp >= minus24Hours
hours := b.timeSource.AdjustedTime().Add(-7 * time.Hour).Unix()
return b.bestChain.Tip().timestamp >= hours
}
// IsCurrent returns whether or not the chain believes it is current. Several
@ -1879,7 +1880,7 @@ func rebuildMissingClaimTrieData(b *BlockChain, done <-chan struct{}) error {
}
if h >= b.claimTrie.Height() {
err = b.ParseClaimScripts(block, n, view, true)
err = b.ParseClaimScripts(block, n, view, true, false)
if err != nil {
return err
}

View file

@ -15,7 +15,8 @@ import (
"github.com/btcsuite/btcd/claimtrie/node"
)
func (b *BlockChain) ParseClaimScripts(block *btcutil.Block, bn *blockNode, view *UtxoViewpoint, failOnHashMiss bool) error {
func (b *BlockChain) ParseClaimScripts(block *btcutil.Block, bn *blockNode, view *UtxoViewpoint,
failOnHashMiss bool, shouldFlush bool) error {
ht := block.Height()
for _, tx := range block.Transactions() {
@ -40,6 +41,10 @@ func (b *BlockChain) ParseClaimScripts(block *btcutil.Block, bn *blockNode, view
}
hash := b.claimTrie.MerkleHash()
if shouldFlush {
b.claimTrie.FlushToDisk()
}
if bn.claimTrie != *hash {
if failOnHashMiss {
return errors.Errorf("height: %d, ct.MerkleHash: %s != node.ClaimTrie: %s", ht, *hash, bn.claimTrie)

View file

@ -69,3 +69,8 @@ func (repo *Pebble) Close() error {
err = repo.db.Close()
return errors.Wrap(err, "on close")
}
func (repo *Pebble) Flush() error {
_, err := repo.db.AsyncFlush()
return err
}

View file

@ -10,4 +10,5 @@ type Repo interface {
Set(height int32, hash *chainhash.Hash) error
Get(height int32) (*chainhash.Hash, error)
Close() error
Flush() error
}

View file

@ -69,3 +69,8 @@ func (repo *Pebble) Close() error {
err = repo.db.Close()
return errors.Wrap(err, "on close")
}
func (repo *Pebble) Flush() error {
_, err := repo.db.AsyncFlush()
return err
}

View file

@ -6,4 +6,5 @@ type Repo interface {
Save(height int32, changes []change.Change) error
Load(height int32) ([]change.Change, error)
Close() error
Flush() error
}

View file

@ -410,3 +410,29 @@ func (ct *ClaimTrie) forwardNodeChange(chg change.Change) error {
func (ct *ClaimTrie) Node(name []byte) (*node.Node, error) {
return ct.nodeManager.Node(name)
}
func (ct *ClaimTrie) FlushToDisk() {
// maybe the user can fix the file lock shown in the warning before they shut down
if err := ct.nodeManager.Flush(); err != nil {
node.Warn("During nodeManager flush: " + err.Error())
}
if err := ct.temporalRepo.Flush(); err != nil {
node.Warn("During temporalRepo flush: " + err.Error())
}
if err := ct.merkleTrie.Flush(); err != nil {
node.Warn("During merkleTrie flush: " + err.Error())
}
if err := ct.blockRepo.Flush(); err != nil {
node.Warn("During blockRepo flush: " + err.Error())
}
if ct.reportedBlockRepo != nil {
if err := ct.reportedBlockRepo.Flush(); err != nil {
node.Warn("During reportedBlockRepo flush: " + err.Error())
}
}
if ct.chainRepo != nil {
if err := ct.chainRepo.Flush(); err != nil {
node.Warn("During chainRepo flush: " + err.Error())
}
}
}

View file

@ -272,3 +272,7 @@ func (t *PersistentTrie) Dump(s string) {
fmt.Printf(" Child %s hash: %s\n", string(key), value.merkleHash.String())
}
}
func (t *PersistentTrie) Flush() error {
return t.repo.Flush()
}

View file

@ -59,3 +59,8 @@ func (repo *Pebble) Close() error {
err = repo.db.Close()
return errors.Wrap(err, "on close")
}
func (repo *Pebble) Flush() error {
_, err := repo.db.AsyncFlush()
return err
}

View file

@ -2,10 +2,12 @@ package merkletrie
import (
"bytes"
"runtime"
"strconv"
"sync"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/claimtrie/node"
"runtime"
"sync"
)
type MerkleTrie interface {
@ -13,6 +15,7 @@ type MerkleTrie interface {
Update(name []byte, restoreChildren bool)
MerkleHash() *chainhash.Hash
MerkleHashAllClaims() *chainhash.Hash
Flush() error
}
type RamTrie struct {
@ -50,10 +53,14 @@ func (rt *RamTrie) SetRoot(h *chainhash.Hash, names [][]byte) {
runtime.GC()
}
c := 0
rt.store.IterateNames(func(name []byte) bool {
rt.Update(name, false)
c++
return true
})
node.LogOnce("Completed claim trie construction. Name count: " + strconv.Itoa(c))
} else {
for _, name := range names {
rt.Update(name, false)
@ -147,3 +154,7 @@ func (rt *RamTrie) merkleHashAllClaims(v *collapsedVertex) *chainhash.Hash {
v.merkleHash = node.HashMerkleBranches(childHash, claimHash)
return v.merkleHash
}
func (rt *RamTrie) Flush() error {
return nil
}

View file

@ -9,4 +9,5 @@ type Repo interface {
Get(key []byte) ([]byte, io.Closer, error)
Set(key, value []byte) error
Close() error
Flush() error
}

View file

@ -35,3 +35,7 @@ func LogOnce(s string) {
loggedStrings[s] = true
log.Info(s)
}
func Warn(s string) {
log.Warn(s)
}

View file

@ -25,6 +25,7 @@ type Manager interface {
NextUpdateHeightOfNode(name []byte) ([]byte, int32)
IterateNames(predicate func(name []byte) bool)
Hash(name []byte) *chainhash.Hash
Flush() error
}
type nodeCacheLeaf struct {
@ -448,3 +449,7 @@ func calculateNodeHash(op wire.OutPoint, takeover int32) *chainhash.Hash {
return &hh
}
func (nm *BaseManager) Flush() error {
return nm.repo.Flush()
}

View file

@ -79,7 +79,7 @@ func init() {
func NewPebble(path string) (*Pebble, error) {
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(256 << 20), BytesPerSync: 16 << 20})
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(32 << 20), BytesPerSync: 4 << 20})
repo := &Pebble{db: db}
return repo, errors.Wrapf(err, "unable to open %s", path)
@ -218,3 +218,8 @@ func (repo *Pebble) Close() error {
err = repo.db.Close()
return errors.Wrap(err, "on close")
}
func (repo *Pebble) Flush() error {
_, err := repo.db.AsyncFlush()
return err
}

View file

@ -26,4 +26,6 @@ type Repo interface {
// IterateAll iterates keys until the predicate function returns false
IterateAll(predicate func(name []byte) bool)
Flush() error
}

View file

@ -5,4 +5,5 @@ type Repo interface {
SetNodesAt(names [][]byte, heights []int32) error
NodesAt(height int32) ([][]byte, error)
Close() error
Flush() error
}

View file

@ -39,3 +39,7 @@ func (repo *Memory) NodesAt(height int32) ([][]byte, error) {
func (repo *Memory) Close() error {
return nil
}
func (repo *Memory) Flush() error {
return nil
}

View file

@ -14,7 +14,7 @@ type Pebble struct {
func NewPebble(path string) (*Pebble, error) {
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(128 << 20)})
db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(16 << 20)})
repo := &Pebble{db: db}
return repo, errors.Wrapf(err, "unable to open %s", path)
@ -79,3 +79,8 @@ func (repo *Pebble) Close() error {
err = repo.db.Close()
return errors.Wrap(err, "on close")
}
func (repo *Pebble) Flush() error {
_, err := repo.db.AsyncFlush()
return err
}