Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get node cache #1633

Merged
merged 10 commits into from
Jun 15, 2021
37 changes: 29 additions & 8 deletions lib/blocktree/blocktree.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ type BlockTree struct {
leaves *leafMap
db database.Database
sync.RWMutex
blockCache map[Hash]*node
danigomez marked this conversation as resolved.
Show resolved Hide resolved
}

// NewEmptyBlockTree creates a BlockTree with a nil head
func NewEmptyBlockTree(db database.Database) *BlockTree {
return &BlockTree{
head: nil,
leaves: newEmptyLeafMap(),
db: db,
head: nil,
leaves: newEmptyLeafMap(),
db: db,
blockCache: make(map[Hash]*node),
}
}

Expand All @@ -61,9 +63,10 @@ func NewBlockTreeFromRoot(root *types.Header, db database.Database) *BlockTree {
}

return &BlockTree{
head: head,
leaves: newLeafMap(head),
db: db,
head: head,
leaves: newLeafMap(head),
db: db,
blockCache: make(map[Hash]*node),
}
}

Expand Down Expand Up @@ -150,7 +153,19 @@ func (bt *BlockTree) GetAllBlocksAtDepth(hash common.Hash) []common.Hash {
}

// getNode finds and returns a node based on its Hash. Returns nil if not found.
func (bt *BlockTree) getNode(h Hash) *node {
func (bt *BlockTree) getNode(h Hash) (ret *node) {
defer func() {
if ret != nil {
if _, ok := bt.blockCache[ret.hash]; !ok {
bt.blockCache[ret.hash] = ret
danigomez marked this conversation as resolved.
Show resolved Hide resolved
}
}
danigomez marked this conversation as resolved.
Show resolved Hide resolved
}()

if b, ok := bt.blockCache[h]; ok {
return b
}

if bt.head.hash == h {
return bt.head
}
Expand All @@ -175,6 +190,11 @@ func (bt *BlockTree) getNode(h Hash) *node {
func (bt *BlockTree) Prune(finalised Hash) (pruned []Hash) {
bt.Lock()
defer bt.Unlock()
defer func() {
for _, hash := range pruned {
delete(bt.blockCache, hash)
}
}()

if finalised == bt.head.hash {
return pruned
Expand Down Expand Up @@ -350,7 +370,8 @@ func (bt *BlockTree) DeepCopy() *BlockTree {
defer bt.RUnlock()

btCopy := &BlockTree{
db: bt.db,
db: bt.db,
blockCache: bt.blockCache,
danigomez marked this conversation as resolved.
Show resolved Hide resolved
}

if bt.head == nil {
Expand Down
48 changes: 48 additions & 0 deletions lib/blocktree/blocktree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,29 @@ func TestBlockTree_GetNode(t *testing.T) {
}
}

func TestBlockTree_GetNodeCache(t *testing.T) {
bt, branches := createTestBlockTree(testHeader, 16, nil)

for _, branch := range branches {
header := &types.Header{
ParentHash: branch.hash,
Number: branch.depth,
StateRoot: Hash{0x1},
}

err := bt.AddBlock(header, 0)
require.Nil(t, err)
}

block := bt.getNode(branches[0].hash)

cachedBlock, ok := bt.blockCache[block.hash]
require.True(t, ok)
require.NotNil(t, cachedBlock)
require.Equal(t, cachedBlock, block)

}

func TestBlockTree_GetAllBlocksAtDepth(t *testing.T) {
bt, _ := createTestBlockTree(testHeader, 8, nil)
hashes := bt.head.getNodesWithDepth(big.NewInt(10), []common.Hash{})
Expand Down Expand Up @@ -386,12 +409,37 @@ func TestBlockTree_Prune(t *testing.T) {
}
}

func TestBlockTree_PruneCache(t *testing.T) {
var bt *BlockTree
var branches []testBranch

for {
bt, branches = createTestBlockTree(testHeader, 5, nil)
if len(branches) > 0 && len(bt.getNode(branches[0].hash).children) > 1 {
break
}
}

// pick some block to finalise
finalised := bt.head.children[0].children[0].children[0]
pruned := bt.Prune(finalised.hash)

for _, prunedHash := range pruned {
block, ok := bt.blockCache[prunedHash]

require.False(t, ok)
require.Nil(t, block)
}

}

func TestBlockTree_DeepCopy(t *testing.T) {
bt, _ := createFlatTree(t, 8)

btCopy := bt.DeepCopy()

require.Equal(t, bt.db, btCopy.db)
require.Equal(t, bt.blockCache, btCopy.blockCache)
require.True(t, equalNodeValue(bt.head, btCopy.head), "BlockTree heads not equal")
require.True(t, equalLeave(bt.leaves, btCopy.leaves), "BlockTree leaves not equal")

Expand Down