force disk flush when caught up to current
This commit is contained in:
parent
0a01170422
commit
82d4b6657b
18 changed files with 109 additions and 18 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -10,4 +10,5 @@ type Repo interface {
|
|||
Set(height int32, hash *chainhash.Hash) error
|
||||
Get(height int32) (*chainhash.Hash, error)
|
||||
Close() error
|
||||
Flush() error
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -6,4 +6,5 @@ type Repo interface {
|
|||
Save(height int32, changes []change.Change) error
|
||||
Load(height int32) ([]change.Change, error)
|
||||
Close() error
|
||||
Flush() error
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -9,4 +9,5 @@ type Repo interface {
|
|||
Get(key []byte) ([]byte, io.Closer, error)
|
||||
Set(key, value []byte) error
|
||||
Close() error
|
||||
Flush() error
|
||||
}
|
||||
|
|
|
@ -35,3 +35,7 @@ func LogOnce(s string) {
|
|||
loggedStrings[s] = true
|
||||
log.Info(s)
|
||||
}
|
||||
|
||||
func Warn(s string) {
|
||||
log.Warn(s)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -26,4 +26,6 @@ type Repo interface {
|
|||
|
||||
// IterateAll iterates keys until the predicate function returns false
|
||||
IterateAll(predicate func(name []byte) bool)
|
||||
|
||||
Flush() error
|
||||
}
|
||||
|
|
|
@ -5,4 +5,5 @@ type Repo interface {
|
|||
SetNodesAt(names [][]byte, heights []int32) error
|
||||
NodesAt(height int32) ([][]byte, error)
|
||||
Close() error
|
||||
Flush() error
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue