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")
|
"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.
|
// 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
|
// Warn if any unknown new rules are either about to activate or
|
||||||
// have already been activated.
|
// have already been activated.
|
||||||
if err := b.warnUnknownRuleActivations(node); err != nil {
|
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.
|
// Write any block status changes to DB before updating best state.
|
||||||
err := b.index.flushToDB()
|
err := b.index.flushToDB()
|
||||||
if err != nil {
|
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
|
// factors are used to guess, but the key factors that allow the chain to
|
||||||
// believe it is current are:
|
// believe it is current are:
|
||||||
// - Latest block height is after the latest checkpoint (if enabled)
|
// - 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).
|
// This function MUST be called with the chain state lock held (for reads).
|
||||||
func (b *BlockChain) isCurrent() bool {
|
func (b *BlockChain) isCurrent() bool {
|
||||||
|
@ -1234,13 +1235,13 @@ func (b *BlockChain) isCurrent() bool {
|
||||||
return false
|
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.
|
// ago.
|
||||||
//
|
//
|
||||||
// The chain appears to be current if none of the checks reported
|
// The chain appears to be current if none of the checks reported
|
||||||
// otherwise.
|
// otherwise.
|
||||||
minus24Hours := b.timeSource.AdjustedTime().Add(-24 * time.Hour).Unix()
|
hours := b.timeSource.AdjustedTime().Add(-7 * time.Hour).Unix()
|
||||||
return b.bestChain.Tip().timestamp >= minus24Hours
|
return b.bestChain.Tip().timestamp >= hours
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCurrent returns whether or not the chain believes it is current. Several
|
// 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() {
|
if h >= b.claimTrie.Height() {
|
||||||
err = b.ParseClaimScripts(block, n, view, true)
|
err = b.ParseClaimScripts(block, n, view, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ import (
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"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()
|
ht := block.Height()
|
||||||
|
|
||||||
for _, tx := range block.Transactions() {
|
for _, tx := range block.Transactions() {
|
||||||
|
@ -40,6 +41,10 @@ func (b *BlockChain) ParseClaimScripts(block *btcutil.Block, bn *blockNode, view
|
||||||
}
|
}
|
||||||
hash := b.claimTrie.MerkleHash()
|
hash := b.claimTrie.MerkleHash()
|
||||||
|
|
||||||
|
if shouldFlush {
|
||||||
|
b.claimTrie.FlushToDisk()
|
||||||
|
}
|
||||||
|
|
||||||
if bn.claimTrie != *hash {
|
if bn.claimTrie != *hash {
|
||||||
if failOnHashMiss {
|
if failOnHashMiss {
|
||||||
return errors.Errorf("height: %d, ct.MerkleHash: %s != node.ClaimTrie: %s", ht, *hash, bn.claimTrie)
|
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()
|
err = repo.db.Close()
|
||||||
return errors.Wrap(err, "on 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
|
Set(height int32, hash *chainhash.Hash) error
|
||||||
Get(height int32) (*chainhash.Hash, error)
|
Get(height int32) (*chainhash.Hash, error)
|
||||||
Close() error
|
Close() error
|
||||||
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,3 +69,8 @@ func (repo *Pebble) Close() error {
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
return errors.Wrap(err, "on 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
|
Save(height int32, changes []change.Change) error
|
||||||
Load(height int32) ([]change.Change, error)
|
Load(height int32) ([]change.Change, error)
|
||||||
Close() 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) {
|
func (ct *ClaimTrie) Node(name []byte) (*node.Node, error) {
|
||||||
return ct.nodeManager.Node(name)
|
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())
|
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()
|
err = repo.db.Close()
|
||||||
return errors.Wrap(err, "on 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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MerkleTrie interface {
|
type MerkleTrie interface {
|
||||||
|
@ -13,6 +15,7 @@ type MerkleTrie interface {
|
||||||
Update(name []byte, restoreChildren bool)
|
Update(name []byte, restoreChildren bool)
|
||||||
MerkleHash() *chainhash.Hash
|
MerkleHash() *chainhash.Hash
|
||||||
MerkleHashAllClaims() *chainhash.Hash
|
MerkleHashAllClaims() *chainhash.Hash
|
||||||
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type RamTrie struct {
|
type RamTrie struct {
|
||||||
|
@ -50,10 +53,14 @@ func (rt *RamTrie) SetRoot(h *chainhash.Hash, names [][]byte) {
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c := 0
|
||||||
rt.store.IterateNames(func(name []byte) bool {
|
rt.store.IterateNames(func(name []byte) bool {
|
||||||
rt.Update(name, false)
|
rt.Update(name, false)
|
||||||
|
c++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
node.LogOnce("Completed claim trie construction. Name count: " + strconv.Itoa(c))
|
||||||
} else {
|
} else {
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
rt.Update(name, false)
|
rt.Update(name, false)
|
||||||
|
@ -147,3 +154,7 @@ func (rt *RamTrie) merkleHashAllClaims(v *collapsedVertex) *chainhash.Hash {
|
||||||
v.merkleHash = node.HashMerkleBranches(childHash, claimHash)
|
v.merkleHash = node.HashMerkleBranches(childHash, claimHash)
|
||||||
return v.merkleHash
|
return v.merkleHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rt *RamTrie) Flush() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -9,4 +9,5 @@ type Repo interface {
|
||||||
Get(key []byte) ([]byte, io.Closer, error)
|
Get(key []byte) ([]byte, io.Closer, error)
|
||||||
Set(key, value []byte) error
|
Set(key, value []byte) error
|
||||||
Close() error
|
Close() error
|
||||||
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,3 +35,7 @@ func LogOnce(s string) {
|
||||||
loggedStrings[s] = true
|
loggedStrings[s] = true
|
||||||
log.Info(s)
|
log.Info(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Warn(s string) {
|
||||||
|
log.Warn(s)
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ type Manager interface {
|
||||||
NextUpdateHeightOfNode(name []byte) ([]byte, int32)
|
NextUpdateHeightOfNode(name []byte) ([]byte, int32)
|
||||||
IterateNames(predicate func(name []byte) bool)
|
IterateNames(predicate func(name []byte) bool)
|
||||||
Hash(name []byte) *chainhash.Hash
|
Hash(name []byte) *chainhash.Hash
|
||||||
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeCacheLeaf struct {
|
type nodeCacheLeaf struct {
|
||||||
|
@ -448,3 +449,7 @@ func calculateNodeHash(op wire.OutPoint, takeover int32) *chainhash.Hash {
|
||||||
|
|
||||||
return &hh
|
return &hh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (nm *BaseManager) Flush() error {
|
||||||
|
return nm.repo.Flush()
|
||||||
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ func init() {
|
||||||
|
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
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}
|
repo := &Pebble{db: db}
|
||||||
|
|
||||||
return repo, errors.Wrapf(err, "unable to open %s", path)
|
return repo, errors.Wrapf(err, "unable to open %s", path)
|
||||||
|
@ -218,3 +218,8 @@ func (repo *Pebble) Close() error {
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
return errors.Wrap(err, "on 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 iterates keys until the predicate function returns false
|
||||||
IterateAll(predicate func(name []byte) bool)
|
IterateAll(predicate func(name []byte) bool)
|
||||||
|
|
||||||
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,5 @@ type Repo interface {
|
||||||
SetNodesAt(names [][]byte, heights []int32) error
|
SetNodesAt(names [][]byte, heights []int32) error
|
||||||
NodesAt(height int32) ([][]byte, error)
|
NodesAt(height int32) ([][]byte, error)
|
||||||
Close() error
|
Close() error
|
||||||
|
Flush() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,3 +39,7 @@ func (repo *Memory) NodesAt(height int32) ([][]byte, error) {
|
||||||
func (repo *Memory) Close() error {
|
func (repo *Memory) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *Memory) Flush() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ type Pebble struct {
|
||||||
|
|
||||||
func NewPebble(path string) (*Pebble, error) {
|
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}
|
repo := &Pebble{db: db}
|
||||||
|
|
||||||
return repo, errors.Wrapf(err, "unable to open %s", path)
|
return repo, errors.Wrapf(err, "unable to open %s", path)
|
||||||
|
@ -79,3 +79,8 @@ func (repo *Pebble) Close() error {
|
||||||
err = repo.db.Close()
|
err = repo.db.Close()
|
||||||
return errors.Wrap(err, "on close")
|
return errors.Wrap(err, "on close")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *Pebble) Flush() error {
|
||||||
|
_, err := repo.db.AsyncFlush()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue