github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/downloader/api.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2015 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package downloader 26 27 import ( 28 "context" 29 "sync" 30 31 ethereum "github.com/ethereum/go-ethereum" 32 "github.com/ethereum/go-ethereum/event" 33 "github.com/ethereum/go-ethereum/rpc" 34 ) 35 36 //PublicDownloaderAPI提供了一个API,它提供有关当前同步状态的信息。 37 //它只提供对任何人都可以使用的数据进行操作的方法,而不存在安全风险。 38 type PublicDownloaderAPI struct { 39 d *Downloader 40 mux *event.TypeMux 41 installSyncSubscription chan chan interface{} 42 uninstallSyncSubscription chan *uninstallSyncSubscriptionRequest 43 } 44 45 //新建PublicDownloaderAPI创建新的PublicDownloaderAPI。API有一个内部事件循环, 46 //通过全局事件mux从下载程序侦听事件。如果它收到 47 //这些事件会将其广播到通过 48 //InstallSyncSubscription频道。 49 func NewPublicDownloaderAPI(d *Downloader, m *event.TypeMux) *PublicDownloaderAPI { 50 api := &PublicDownloaderAPI{ 51 d: d, 52 mux: m, 53 installSyncSubscription: make(chan chan interface{}), 54 uninstallSyncSubscription: make(chan *uninstallSyncSubscriptionRequest), 55 } 56 57 go api.eventLoop() 58 59 return api 60 } 61 62 //EventLoop运行一个循环,直到事件mux关闭。它将安装和卸载新的 63 //将订阅和广播同步状态更新同步到已安装的同步订阅。 64 func (api *PublicDownloaderAPI) eventLoop() { 65 var ( 66 sub = api.mux.Subscribe(StartEvent{}, DoneEvent{}, FailedEvent{}) 67 syncSubscriptions = make(map[chan interface{}]struct{}) 68 ) 69 70 for { 71 select { 72 case i := <-api.installSyncSubscription: 73 syncSubscriptions[i] = struct{}{} 74 case u := <-api.uninstallSyncSubscription: 75 delete(syncSubscriptions, u.c) 76 close(u.uninstalled) 77 case event := <-sub.Chan(): 78 if event == nil { 79 return 80 } 81 82 var notification interface{} 83 switch event.Data.(type) { 84 case StartEvent: 85 notification = &SyncingResult{ 86 Syncing: true, 87 Status: api.d.Progress(), 88 } 89 case DoneEvent, FailedEvent: 90 notification = false 91 } 92 //广播 93 for c := range syncSubscriptions { 94 c <- notification 95 } 96 } 97 } 98 } 99 100 //同步提供此节点何时开始与以太坊网络同步以及何时完成同步的信息。 101 func (api *PublicDownloaderAPI) Syncing(ctx context.Context) (*rpc.Subscription, error) { 102 notifier, supported := rpc.NotifierFromContext(ctx) 103 if !supported { 104 return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported 105 } 106 107 rpcSub := notifier.CreateSubscription() 108 109 go func() { 110 statuses := make(chan interface{}) 111 sub := api.SubscribeSyncStatus(statuses) 112 113 for { 114 select { 115 case status := <-statuses: 116 notifier.Notify(rpcSub.ID, status) 117 case <-rpcSub.Err(): 118 sub.Unsubscribe() 119 return 120 case <-notifier.Closed(): 121 sub.Unsubscribe() 122 return 123 } 124 } 125 }() 126 127 return rpcSub, nil 128 } 129 130 //同步结果提供有关此节点当前同步状态的信息。 131 type SyncingResult struct { 132 Syncing bool `json:"syncing"` 133 Status ethereum.SyncProgress `json:"status"` 134 } 135 136 //UninstallSyncSubscriptionRequest在API事件循环中卸载同步订阅。 137 type uninstallSyncSubscriptionRequest struct { 138 c chan interface{} 139 uninstalled chan interface{} 140 } 141 142 //SyncStatusSubscription表示同步订阅。 143 type SyncStatusSubscription struct { 144 api *PublicDownloaderAPI //在此API实例的事件循环中注册订阅 145 c chan interface{} //事件广播到的频道 146 unsubOnce sync.Once //确保取消订阅逻辑执行一次 147 } 148 149 //取消订阅将从DeloLoad事件循环中卸载订阅。 150 //传递给subscribeSyncStatus的状态通道不再使用。 151 //在这个方法返回之后。 152 func (s *SyncStatusSubscription) Unsubscribe() { 153 s.unsubOnce.Do(func() { 154 req := uninstallSyncSubscriptionRequest{s.c, make(chan interface{})} 155 s.api.uninstallSyncSubscription <- &req 156 157 for { 158 select { 159 case <-s.c: 160 //删除新的状态事件,直到卸载确认 161 continue 162 case <-req.uninstalled: 163 return 164 } 165 } 166 }) 167 } 168 169 //订阅同步状态创建将广播新同步更新的订阅。 170 //给定的通道必须接收接口值,结果可以是 171 func (api *PublicDownloaderAPI) SubscribeSyncStatus(status chan interface{}) *SyncStatusSubscription { 172 api.installSyncSubscription <- status 173 return &SyncStatusSubscription{api: api, c: status} 174 }