nodemgr: add locks for the node cache
This commit is contained in:
parent
85631bd0b9
commit
f927d6743a
1 changed files with 24 additions and 10 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/lbryio/claimtrie/change"
|
"github.com/lbryio/claimtrie/change"
|
||||||
"github.com/lbryio/claimtrie/claim"
|
"github.com/lbryio/claimtrie/claim"
|
||||||
|
@ -17,8 +18,11 @@ import (
|
||||||
// NodeMgr ...
|
// NodeMgr ...
|
||||||
type NodeMgr struct {
|
type NodeMgr struct {
|
||||||
height claim.Height
|
height claim.Height
|
||||||
|
|
||||||
db *leveldb.DB
|
db *leveldb.DB
|
||||||
|
|
||||||
|
// cachemu synchronizes the access to the map itself, but not the
|
||||||
|
// values of the node.
|
||||||
|
cachemu sync.RWMutex
|
||||||
cache map[string]*claim.Node
|
cache map[string]*claim.Node
|
||||||
nextUpdates todos
|
nextUpdates todos
|
||||||
}
|
}
|
||||||
|
@ -35,12 +39,16 @@ func New(db *leveldb.DB) *NodeMgr {
|
||||||
|
|
||||||
// Load loads the nodes from the database up to height ht.
|
// Load loads the nodes from the database up to height ht.
|
||||||
func (nm *NodeMgr) Load(ht claim.Height) {
|
func (nm *NodeMgr) Load(ht claim.Height) {
|
||||||
|
|
||||||
nm.height = ht
|
nm.height = ht
|
||||||
iter := nm.db.NewIterator(nil, nil)
|
iter := nm.db.NewIterator(nil, nil)
|
||||||
|
nm.cachemu.Lock()
|
||||||
for iter.Next() {
|
for iter.Next() {
|
||||||
name := string(iter.Key())
|
name := string(iter.Key())
|
||||||
nm.cache[name] = nm.load(name, ht)
|
nm.cache[name] = nm.load(name, ht)
|
||||||
}
|
}
|
||||||
|
nm.cachemu.Unlock()
|
||||||
|
|
||||||
data, err := nm.db.Get([]byte("nextUpdates"), nil)
|
data, err := nm.db.Get([]byte("nextUpdates"), nil)
|
||||||
if err == leveldb.ErrNotFound {
|
if err == leveldb.ErrNotFound {
|
||||||
return
|
return
|
||||||
|
@ -71,6 +79,8 @@ func (nm *NodeMgr) Get(key []byte) trie.Value {
|
||||||
|
|
||||||
// Reset resets all nodes to specified height.
|
// Reset resets all nodes to specified height.
|
||||||
func (nm *NodeMgr) Reset(ht claim.Height) {
|
func (nm *NodeMgr) Reset(ht claim.Height) {
|
||||||
|
nm.cachemu.Lock()
|
||||||
|
defer nm.cachemu.Unlock()
|
||||||
nm.height = ht
|
nm.height = ht
|
||||||
for name, n := range nm.cache {
|
for name, n := range nm.cache {
|
||||||
if n.Height() >= ht {
|
if n.Height() >= ht {
|
||||||
|
@ -81,21 +91,25 @@ func (nm *NodeMgr) Reset(ht claim.Height) {
|
||||||
|
|
||||||
// Size returns the number of nodes loaded into the cache.
|
// Size returns the number of nodes loaded into the cache.
|
||||||
func (nm *NodeMgr) Size() int {
|
func (nm *NodeMgr) Size() int {
|
||||||
|
nm.cachemu.RLock()
|
||||||
|
defer nm.cachemu.RUnlock()
|
||||||
return len(nm.cache)
|
return len(nm.cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nm *NodeMgr) load(name string, ht claim.Height) *claim.Node {
|
func (nm *NodeMgr) load(name string, ht claim.Height) *claim.Node {
|
||||||
c := change.NewChangeList(nm.db, name).Load().Truncate(ht).Changes()
|
c := change.NewChangeList(nm.db, name).Load().Truncate(ht).Changes()
|
||||||
return NewFromChanges(name, c, ht)
|
return replay(name, c).AdjustTo(ht)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeAt returns the node adjusted to specified height.
|
// NodeAt returns the node adjusted to specified height.
|
||||||
func (nm *NodeMgr) NodeAt(name string, ht claim.Height) *claim.Node {
|
func (nm *NodeMgr) NodeAt(name string, ht claim.Height) *claim.Node {
|
||||||
|
nm.cachemu.Lock()
|
||||||
n, ok := nm.cache[name]
|
n, ok := nm.cache[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
n = claim.NewNode(name)
|
n = claim.NewNode(name)
|
||||||
nm.cache[name] = n
|
nm.cache[name] = n
|
||||||
}
|
}
|
||||||
|
nm.cachemu.Unlock()
|
||||||
|
|
||||||
// Cached version is too new.
|
// Cached version is too new.
|
||||||
if n.Height() > nm.height || n.Height() > ht {
|
if n.Height() > nm.height || n.Height() > ht {
|
||||||
|
@ -112,7 +126,9 @@ func (nm *NodeMgr) ModifyNode(name string, chg *change.Change) error {
|
||||||
if err := execute(n, chg); err != nil {
|
if err := execute(n, chg); err != nil {
|
||||||
return errors.Wrapf(err, "claim.execute(n,chg)")
|
return errors.Wrapf(err, "claim.execute(n,chg)")
|
||||||
}
|
}
|
||||||
|
nm.cachemu.Lock()
|
||||||
nm.cache[name] = n
|
nm.cache[name] = n
|
||||||
|
nm.cachemu.Unlock()
|
||||||
nm.nextUpdates.set(name, ht+1)
|
nm.nextUpdates.set(name, ht+1)
|
||||||
change.NewChangeList(nm.db, name).Load().Append(chg).Save()
|
change.NewChangeList(nm.db, name).Load().Append(chg).Save()
|
||||||
return nil
|
return nil
|
||||||
|
@ -129,11 +145,14 @@ func (nm *NodeMgr) CatchUp(ht claim.Height, notifier func(key []byte)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisitFunc ...
|
// VisitFunc visit each node in read-only manner.
|
||||||
type VisitFunc func(n *claim.Node) (stop bool)
|
type VisitFunc func(n *claim.Node) (stop bool)
|
||||||
|
|
||||||
// Visit visits every node in the cache with VisiFunc.
|
// Visit visits every node in the cache with VisitFunc.
|
||||||
|
// If the VisitFunc returns true, the iteration ends immediately.
|
||||||
func (nm *NodeMgr) Visit(v VisitFunc) {
|
func (nm *NodeMgr) Visit(v VisitFunc) {
|
||||||
|
nm.cachemu.RLock()
|
||||||
|
defer nm.cachemu.RUnlock()
|
||||||
for _, n := range nm.cache {
|
for _, n := range nm.cache {
|
||||||
if v(n) {
|
if v(n) {
|
||||||
return
|
return
|
||||||
|
@ -141,7 +160,7 @@ func (nm *NodeMgr) Visit(v VisitFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show is a conevenient function for debugging and velopment purpose.
|
// Show is a conevenient function for debugging purpose.
|
||||||
// The proper way to handle user request would be a query function with filters specified.
|
// The proper way to handle user request would be a query function with filters specified.
|
||||||
func (nm *NodeMgr) Show(name string, ht claim.Height, dump bool) error {
|
func (nm *NodeMgr) Show(name string, ht claim.Height, dump bool) error {
|
||||||
names := []string{}
|
names := []string{}
|
||||||
|
@ -166,11 +185,6 @@ func (nm *NodeMgr) Show(name string, ht claim.Height, dump bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromChanges ...
|
|
||||||
func NewFromChanges(name string, chgs []*change.Change, ht claim.Height) *claim.Node {
|
|
||||||
return replay(name, chgs).AdjustTo(ht)
|
|
||||||
}
|
|
||||||
|
|
||||||
func replay(name string, chgs []*change.Change) *claim.Node {
|
func replay(name string, chgs []*change.Change) *claim.Node {
|
||||||
n := claim.NewNode(name)
|
n := claim.NewNode(name)
|
||||||
for _, chg := range chgs {
|
for _, chg := range chgs {
|
||||||
|
|
Loading…
Reference in a new issue