@@ -75,8 +75,10 @@ type Table struct {
75
75
net transport
76
76
refreshReq chan chan struct {}
77
77
initDone chan struct {}
78
- closeReq chan struct {}
79
- closed chan struct {}
78
+
79
+ closeOnce sync.Once
80
+ closeReq chan struct {}
81
+ closed chan struct {}
80
82
81
83
nodeAddedHook func (* node ) // for testing
82
84
}
@@ -180,16 +182,14 @@ func (tab *Table) ReadRandomNodes(buf []*enode.Node) (n int) {
180
182
181
183
// Close terminates the network listener and flushes the node database.
182
184
func (tab * Table ) Close () {
183
- if tab .net != nil {
184
- tab .net .close ()
185
- }
186
-
187
- select {
188
- case <- tab .closed :
189
- // already closed.
190
- case tab .closeReq <- struct {}{}:
191
- <- tab .closed // wait for refreshLoop to end.
192
- }
185
+ tab .closeOnce .Do (func () {
186
+ if tab .net != nil {
187
+ tab .net .close ()
188
+ }
189
+ // Wait for loop to end.
190
+ close (tab .closeReq )
191
+ <- tab .closed
192
+ })
193
193
}
194
194
195
195
// setFallbackNodes sets the initial points of contact. These nodes
@@ -290,31 +290,39 @@ func (tab *Table) lookup(targetKey encPubkey, refreshIfEmpty bool) []*node {
290
290
// we have asked all closest nodes, stop the search
291
291
break
292
292
}
293
- // wait for the next reply
294
- for _ , n := range <- reply {
295
- if n != nil && ! seen [n .ID ()] {
296
- seen [n .ID ()] = true
297
- result .push (n , bucketSize )
293
+ select {
294
+ case nodes := <- reply :
295
+ for _ , n := range nodes {
296
+ if n != nil && ! seen [n .ID ()] {
297
+ seen [n .ID ()] = true
298
+ result .push (n , bucketSize )
299
+ }
298
300
}
301
+ case <- tab .closeReq :
302
+ return nil // shutdown, no need to continue.
299
303
}
300
304
pendingQueries --
301
305
}
302
306
return result .entries
303
307
}
304
308
305
309
func (tab * Table ) findnode (n * node , targetKey encPubkey , reply chan <- []* node ) {
306
- fails := tab .db .FindFails (n .ID ())
310
+ fails := tab .db .FindFails (n .ID (), n . IP () )
307
311
r , err := tab .net .findnode (n .ID (), n .addr (), targetKey )
308
- if err != nil || len (r ) == 0 {
312
+ if err == errClosed {
313
+ // Avoid recording failures on shutdown.
314
+ reply <- nil
315
+ return
316
+ } else if err != nil || len (r ) == 0 {
309
317
fails ++
310
- tab .db .UpdateFindFails (n .ID (), fails )
318
+ tab .db .UpdateFindFails (n .ID (), n . IP (), fails )
311
319
log .Trace ("Findnode failed" , "id" , n .ID (), "failcount" , fails , "err" , err )
312
320
if fails >= maxFindnodeFailures {
313
321
log .Trace ("Too many findnode failures, dropping" , "id" , n .ID (), "failcount" , fails )
314
322
tab .delete (n )
315
323
}
316
324
} else if fails > 0 {
317
- tab .db .UpdateFindFails (n .ID (), fails - 1 )
325
+ tab .db .UpdateFindFails (n .ID (), n . IP (), fails - 1 )
318
326
}
319
327
320
328
// Grab as many nodes as possible. Some of them might not be alive anymore, but we'll
@@ -329,7 +337,7 @@ func (tab *Table) refresh() <-chan struct{} {
329
337
done := make (chan struct {})
330
338
select {
331
339
case tab .refreshReq <- done :
332
- case <- tab .closed :
340
+ case <- tab .closeReq :
333
341
close (done )
334
342
}
335
343
return done
@@ -433,7 +441,7 @@ func (tab *Table) loadSeedNodes() {
433
441
seeds = append (seeds , tab .nursery ... )
434
442
for i := range seeds {
435
443
seed := seeds [i ]
436
- age := log.Lazy {Fn : func () interface {} { return time .Since (tab .db .LastPongReceived (seed .ID ())) }}
444
+ age := log.Lazy {Fn : func () interface {} { return time .Since (tab .db .LastPongReceived (seed .ID (), seed . IP () )) }}
437
445
log .Trace ("Found seed node in database" , "id" , seed .ID (), "addr" , seed .addr (), "age" , age )
438
446
tab .add (seed )
439
447
}
@@ -458,16 +466,17 @@ func (tab *Table) doRevalidate(done chan<- struct{}) {
458
466
b := tab .buckets [bi ]
459
467
if err == nil {
460
468
// The node responded, move it to the front.
461
- log .Debug ("Revalidated node" , "b" , bi , "id" , last .ID ())
469
+ last .livenessChecks ++
470
+ log .Debug ("Revalidated node" , "b" , bi , "id" , last .ID (), "checks" , last .livenessChecks )
462
471
b .bump (last )
463
472
return
464
473
}
465
474
// No reply received, pick a replacement or delete the node if there aren't
466
475
// any replacements.
467
476
if r := tab .replace (b , last ); r != nil {
468
- log .Debug ("Replaced dead node" , "b" , bi , "id" , last .ID (), "ip" , last .IP (), "r" , r .ID (), "rip" , r .IP ())
477
+ log .Debug ("Replaced dead node" , "b" , bi , "id" , last .ID (), "ip" , last .IP (), "checks" , last . livenessChecks , " r" , r .ID (), "rip" , r .IP ())
469
478
} else {
470
- log .Debug ("Removed dead node" , "b" , bi , "id" , last .ID (), "ip" , last .IP ())
479
+ log .Debug ("Removed dead node" , "b" , bi , "id" , last .ID (), "ip" , last .IP (), "checks" , last . livenessChecks )
471
480
}
472
481
}
473
482
@@ -502,7 +511,7 @@ func (tab *Table) copyLiveNodes() {
502
511
now := time .Now ()
503
512
for _ , b := range & tab .buckets {
504
513
for _ , n := range b .entries {
505
- if now .Sub (n .addedAt ) >= seedMinTableTime {
514
+ if n . livenessChecks > 0 && now .Sub (n .addedAt ) >= seedMinTableTime {
506
515
tab .db .UpdateNode (unwrapNode (n ))
507
516
}
508
517
}
@@ -518,7 +527,9 @@ func (tab *Table) closest(target enode.ID, nresults int) *nodesByDistance {
518
527
close := & nodesByDistance {target : target }
519
528
for _ , b := range & tab .buckets {
520
529
for _ , n := range b .entries {
521
- close .push (n , nresults )
530
+ if n .livenessChecks > 0 {
531
+ close .push (n , nresults )
532
+ }
522
533
}
523
534
}
524
535
return close
@@ -572,23 +583,6 @@ func (tab *Table) addThroughPing(n *node) {
572
583
tab .add (n )
573
584
}
574
585
575
- // stuff adds nodes the table to the end of their corresponding bucket
576
- // if the bucket is not full. The caller must not hold tab.mutex.
577
- func (tab * Table ) stuff (nodes []* node ) {
578
- tab .mutex .Lock ()
579
- defer tab .mutex .Unlock ()
580
-
581
- for _ , n := range nodes {
582
- if n .ID () == tab .self ().ID () {
583
- continue // don't add self
584
- }
585
- b := tab .bucket (n .ID ())
586
- if len (b .entries ) < bucketSize {
587
- tab .bumpOrAdd (b , n )
588
- }
589
- }
590
- }
591
-
592
586
// delete removes an entry from the node table. It is used to evacuate dead nodes.
593
587
func (tab * Table ) delete (node * node ) {
594
588
tab .mutex .Lock ()
0 commit comments