statesync.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright 2017 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 downloader
  17. import (
  18. "sync"
  19. "github.com/ethereum/go-ethereum/common"
  20. "github.com/ethereum/go-ethereum/log"
  21. )
  22. // syncState starts downloading state with the given root hash.
  23. func (d *Downloader) syncState(root common.Hash) *stateSync {
  24. // Create the state sync
  25. s := newStateSync(d, root)
  26. select {
  27. case d.stateSyncStart <- s:
  28. // If we tell the statesync to restart with a new root, we also need
  29. // to wait for it to actually also start -- when old requests have timed
  30. // out or been delivered
  31. <-s.started
  32. case <-d.quitCh:
  33. s.err = errCancelStateFetch
  34. close(s.done)
  35. }
  36. return s
  37. }
  38. // stateFetcher manages the active state sync and accepts requests
  39. // on its behalf.
  40. func (d *Downloader) stateFetcher() {
  41. for {
  42. select {
  43. case s := <-d.stateSyncStart:
  44. for next := s; next != nil; {
  45. next = d.runStateSync(next)
  46. }
  47. case <-d.quitCh:
  48. return
  49. }
  50. }
  51. }
  52. // runStateSync runs a state synchronisation until it completes or another root
  53. // hash is requested to be switched over to.
  54. func (d *Downloader) runStateSync(s *stateSync) *stateSync {
  55. log.Trace("State sync starting", "root", s.root)
  56. go s.run()
  57. defer s.Cancel()
  58. for {
  59. select {
  60. case next := <-d.stateSyncStart:
  61. return next
  62. case <-s.done:
  63. return nil
  64. }
  65. }
  66. }
  67. // stateSync schedules requests for downloading a particular state trie defined
  68. // by a given state root.
  69. type stateSync struct {
  70. d *Downloader // Downloader instance to access and manage current peerset
  71. root common.Hash // State root currently being synced
  72. started chan struct{} // Started is signalled once the sync loop starts
  73. cancel chan struct{} // Channel to signal a termination request
  74. cancelOnce sync.Once // Ensures cancel only ever gets called once
  75. done chan struct{} // Channel to signal termination completion
  76. err error // Any error hit during sync (set before completion)
  77. }
  78. // newStateSync creates a new state trie download scheduler. This method does not
  79. // yet start the sync. The user needs to call run to initiate.
  80. func newStateSync(d *Downloader, root common.Hash) *stateSync {
  81. return &stateSync{
  82. d: d,
  83. root: root,
  84. cancel: make(chan struct{}),
  85. done: make(chan struct{}),
  86. started: make(chan struct{}),
  87. }
  88. }
  89. // run starts the task assignment and response processing loop, blocking until
  90. // it finishes, and finally notifying any goroutines waiting for the loop to
  91. // finish.
  92. func (s *stateSync) run() {
  93. close(s.started)
  94. s.err = s.d.SnapSyncer.Sync(s.root, s.cancel)
  95. close(s.done)
  96. }
  97. // Wait blocks until the sync is done or canceled.
  98. func (s *stateSync) Wait() error {
  99. <-s.done
  100. return s.err
  101. }
  102. // Cancel cancels the sync and waits until it has shut down.
  103. func (s *stateSync) Cancel() error {
  104. s.cancelOnce.Do(func() {
  105. close(s.cancel)
  106. })
  107. return s.Wait()
  108. }