From 64097b8455f5778fe7180308af15c8585c415434 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 14 Oct 2016 15:07:12 +0200 Subject: [PATCH] trie: fixup cachegen overflow at request of nick --- trie/hasher.go | 2 ++ trie/node.go | 12 +++------- trie/node_test.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 trie/node_test.go diff --git a/trie/hasher.go b/trie/hasher.go index c22631a35b..e395e00d79 100644 --- a/trie/hasher.go +++ b/trie/hasher.go @@ -58,6 +58,8 @@ func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error) return hash, n, nil } if n.canUnload(h.cachegen, h.cachelimit) { + // Evict the node from cache. All of its subnodes will have a lower or equal + // cache generation number. return hash, hash, nil } if !dirty { diff --git a/trie/node.go b/trie/node.go index 835cb57f74..de9752c936 100644 --- a/trie/node.go +++ b/trie/node.go @@ -64,17 +64,11 @@ type nodeFlag struct { // canUnload tells whether a node can be unloaded. func (n *nodeFlag) canUnload(cachegen, cachelimit uint16) bool { - var dist uint16 - if n.gen > cachegen { - dist = n.gen - cachegen - } else { - dist = cachegen - n.gen - } - return !n.dirty && dist > cachelimit + return !n.dirty && cachegen-n.gen >= cachelimit } -func (n *fullNode) canUnload(gen, limit uint16) bool { return (&n.flags).canUnload(gen, limit) } -func (n *shortNode) canUnload(gen, limit uint16) bool { return (&n.flags).canUnload(gen, limit) } +func (n *fullNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } +func (n *shortNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } func (n hashNode) canUnload(uint16, uint16) bool { return false } func (n valueNode) canUnload(uint16, uint16) bool { return false } diff --git a/trie/node_test.go b/trie/node_test.go new file mode 100644 index 0000000000..7ad1ff9e7b --- /dev/null +++ b/trie/node_test.go @@ -0,0 +1,58 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import "testing" + +func TestCanUnload(t *testing.T) { + tests := []struct { + flag nodeFlag + cachegen, cachelimit uint16 + want bool + }{ + { + flag: nodeFlag{dirty: true, gen: 0}, + want: false, + }, + { + flag: nodeFlag{dirty: false, gen: 0}, + cachegen: 0, cachelimit: 0, + want: true, + }, + { + flag: nodeFlag{dirty: false, gen: 65534}, + cachegen: 65535, cachelimit: 1, + want: true, + }, + { + flag: nodeFlag{dirty: false, gen: 65534}, + cachegen: 0, cachelimit: 1, + want: true, + }, + { + flag: nodeFlag{dirty: false, gen: 1}, + cachegen: 65535, cachelimit: 1, + want: true, + }, + } + + for _, test := range tests { + if got := test.flag.canUnload(test.cachegen, test.cachelimit); got != test.want { + t.Errorf("%+v\n got %t, want %t", test, got, test.want) + } + } +}