kademlia.go 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package simulation
  17. import (
  18. "context"
  19. "encoding/hex"
  20. "time"
  21. "github.com/ethereum/go-ethereum/common"
  22. "github.com/ethereum/go-ethereum/log"
  23. "github.com/ethereum/go-ethereum/p2p/enode"
  24. "github.com/ethereum/go-ethereum/swarm/network"
  25. )
  26. // BucketKeyKademlia is the key to be used for storing the kademlia
  27. // instance for particuar node, usually inside the ServiceFunc function.
  28. var BucketKeyKademlia BucketKey = "kademlia"
  29. // WaitTillHealthy is blocking until the health of all kademlias is true.
  30. // If error is not nil, a map of kademlia that was found not healthy is returned.
  31. func (s *Simulation) WaitTillHealthy(ctx context.Context, kadMinProxSize int) (ill map[enode.ID]*network.Kademlia, err error) {
  32. // Prepare PeerPot map for checking Kademlia health
  33. var ppmap map[string]*network.PeerPot
  34. kademlias := s.kademlias()
  35. addrs := make([][]byte, 0, len(kademlias))
  36. for _, k := range kademlias {
  37. addrs = append(addrs, k.BaseAddr())
  38. }
  39. ppmap = network.NewPeerPotMap(kadMinProxSize, addrs)
  40. // Wait for healthy Kademlia on every node before checking files
  41. ticker := time.NewTicker(200 * time.Millisecond)
  42. defer ticker.Stop()
  43. ill = make(map[enode.ID]*network.Kademlia)
  44. for {
  45. select {
  46. case <-ctx.Done():
  47. return ill, ctx.Err()
  48. case <-ticker.C:
  49. for k := range ill {
  50. delete(ill, k)
  51. }
  52. log.Debug("kademlia health check", "addr count", len(addrs))
  53. for id, k := range kademlias {
  54. //PeerPot for this node
  55. addr := common.Bytes2Hex(k.BaseAddr())
  56. pp := ppmap[addr]
  57. //call Healthy RPC
  58. h := k.Healthy(pp)
  59. //print info
  60. log.Debug(k.String())
  61. log.Debug("kademlia", "empty bins", pp.EmptyBins, "gotNN", h.GotNN, "knowNN", h.KnowNN, "full", h.Full)
  62. log.Debug("kademlia", "health", h.GotNN && h.KnowNN && h.Full, "addr", hex.EncodeToString(k.BaseAddr()), "node", id)
  63. log.Debug("kademlia", "ill condition", !h.GotNN || !h.Full, "addr", hex.EncodeToString(k.BaseAddr()), "node", id)
  64. if !h.GotNN || !h.Full {
  65. ill[id] = k
  66. }
  67. }
  68. if len(ill) == 0 {
  69. return nil, nil
  70. }
  71. }
  72. }
  73. }
  74. // kademlias returns all Kademlia instances that are set
  75. // in simulation bucket.
  76. func (s *Simulation) kademlias() (ks map[enode.ID]*network.Kademlia) {
  77. items := s.UpNodesItems(BucketKeyKademlia)
  78. ks = make(map[enode.ID]*network.Kademlia, len(items))
  79. for id, v := range items {
  80. k, ok := v.(*network.Kademlia)
  81. if !ok {
  82. continue
  83. }
  84. ks[id] = k
  85. }
  86. return ks
  87. }