You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
1.8 KiB

7 years ago
7 years ago
7 years ago
7 years ago
p2p: seed mode refactoring (#3011) ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
6 years ago
7 years ago
7 years ago
7 years ago
  1. package pex
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. cmn "github.com/tendermint/tendermint/libs/common"
  7. )
  8. /* Loading & Saving */
  9. type addrBookJSON struct {
  10. Key string `json:"key"`
  11. Addrs []*knownAddress `json:"addrs"`
  12. }
  13. func (a *addrBook) saveToFile(filePath string) {
  14. a.mtx.Lock()
  15. defer a.mtx.Unlock()
  16. a.Logger.Info("Saving AddrBook to file", "size", a.size())
  17. addrs := make([]*knownAddress, 0, len(a.addrLookup))
  18. for _, ka := range a.addrLookup {
  19. addrs = append(addrs, ka)
  20. }
  21. aJSON := &addrBookJSON{
  22. Key: a.key,
  23. Addrs: addrs,
  24. }
  25. jsonBytes, err := json.MarshalIndent(aJSON, "", "\t")
  26. if err != nil {
  27. a.Logger.Error("Failed to save AddrBook to file", "err", err)
  28. return
  29. }
  30. err = cmn.WriteFileAtomic(filePath, jsonBytes, 0644)
  31. if err != nil {
  32. a.Logger.Error("Failed to save AddrBook to file", "file", filePath, "err", err)
  33. }
  34. }
  35. // Returns false if file does not exist.
  36. // cmn.Panics if file is corrupt.
  37. func (a *addrBook) loadFromFile(filePath string) bool {
  38. // If doesn't exist, do nothing.
  39. _, err := os.Stat(filePath)
  40. if os.IsNotExist(err) {
  41. return false
  42. }
  43. // Load addrBookJSON{}
  44. r, err := os.Open(filePath)
  45. if err != nil {
  46. cmn.PanicCrisis(fmt.Sprintf("Error opening file %s: %v", filePath, err))
  47. }
  48. defer r.Close() // nolint: errcheck
  49. aJSON := &addrBookJSON{}
  50. dec := json.NewDecoder(r)
  51. err = dec.Decode(aJSON)
  52. if err != nil {
  53. cmn.PanicCrisis(fmt.Sprintf("Error reading file %s: %v", filePath, err))
  54. }
  55. // Restore all the fields...
  56. // Restore the key
  57. a.key = aJSON.Key
  58. // Restore .bucketsNew & .bucketsOld
  59. for _, ka := range aJSON.Addrs {
  60. for _, bucketIndex := range ka.Buckets {
  61. bucket := a.getBucket(ka.BucketType, bucketIndex)
  62. bucket[ka.Addr.String()] = ka
  63. }
  64. a.addrLookup[ka.ID()] = ka
  65. if ka.BucketType == bucketTypeNew {
  66. a.nNew++
  67. } else {
  68. a.nOld++
  69. }
  70. }
  71. return true
  72. }