@@ -34,6 +34,7 @@ import (
3434
3535 "github.com/ethereum/go-ethereum/common"
3636 "github.com/ethereum/go-ethereum/log"
37+ "github.com/ethereum/go-ethereum/metrics"
3738 "github.com/ethereum/go-ethereum/p2p/enode"
3839 "github.com/ethereum/go-ethereum/p2p/netutil"
3940)
@@ -80,7 +81,8 @@ type Table struct {
8081 closeReq chan struct {}
8182 closed chan struct {}
8283
83- nodeAddedHook func (* node ) // for testing
84+ nodeAddedHook func (* bucket , * node )
85+ nodeRemovedHook func (* bucket , * node )
8486}
8587
8688// transport is implemented by the UDP transports.
@@ -98,6 +100,7 @@ type bucket struct {
98100 entries []* node // live entries, sorted by time of last contact
99101 replacements []* node // recently seen nodes to be used if revalidation fails
100102 ips netutil.DistinctNetSet
103+ index int
101104}
102105
103106func newTable (t transport , db * enode.DB , cfg Config ) (* Table , error ) {
@@ -119,7 +122,8 @@ func newTable(t transport, db *enode.DB, cfg Config) (*Table, error) {
119122 }
120123 for i := range tab .buckets {
121124 tab .buckets [i ] = & bucket {
122- ips : netutil.DistinctNetSet {Subnet : bucketSubnet , Limit : bucketIPLimit },
125+ index : i ,
126+ ips : netutil.DistinctNetSet {Subnet : bucketSubnet , Limit : bucketIPLimit },
123127 }
124128 }
125129 tab .seedRand ()
@@ -128,6 +132,22 @@ func newTable(t transport, db *enode.DB, cfg Config) (*Table, error) {
128132 return tab , nil
129133}
130134
135+ func newMeteredTable (t transport , db * enode.DB , cfg Config ) (* Table , error ) {
136+ tab , err := newTable (t , db , cfg )
137+ if err != nil {
138+ return nil , err
139+ }
140+ if metrics .Enabled {
141+ tab .nodeAddedHook = func (b * bucket , n * node ) {
142+ bucketsCounter [b .index ].Inc (1 )
143+ }
144+ tab .nodeRemovedHook = func (b * bucket , n * node ) {
145+ bucketsCounter [b .index ].Dec (1 )
146+ }
147+ }
148+ return tab , nil
149+ }
150+
131151// Nodes returns all nodes contained in the table.
132152func (tab * Table ) Nodes () []* enode.Node {
133153 if ! tab .isInitDone () {
@@ -495,7 +515,7 @@ func (tab *Table) addSeenNode(n *node) {
495515 n .addedAt = time .Now ()
496516
497517 if tab .nodeAddedHook != nil {
498- tab .nodeAddedHook (n )
518+ tab .nodeAddedHook (b , n )
499519 }
500520}
501521
@@ -539,7 +559,7 @@ func (tab *Table) addVerifiedNode(n *node) {
539559 n .addedAt = time .Now ()
540560
541561 if tab .nodeAddedHook != nil {
542- tab .nodeAddedHook (n )
562+ tab .nodeAddedHook (b , n )
543563 }
544564}
545565
@@ -638,8 +658,16 @@ func (tab *Table) bumpInBucket(b *bucket, n *node) bool {
638658}
639659
640660func (tab * Table ) deleteInBucket (b * bucket , n * node ) {
661+ // Check if the node is actually in the bucket so the removed hook
662+ // isn't called multiple times for the same node.
663+ if ! contains (b .entries , n .ID ()) {
664+ return
665+ }
641666 b .entries = deleteNode (b .entries , n )
642667 tab .removeIP (b , n .IP ())
668+ if tab .nodeRemovedHook != nil {
669+ tab .nodeRemovedHook (b , n )
670+ }
643671}
644672
645673func contains (ns []* node , id enode.ID ) bool {
0 commit comments