github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/accounts/manager.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:32</date> 10 //</624450065276080128> 11 12 13 package accounts 14 15 import ( 16 "reflect" 17 "sort" 18 "sync" 19 20 "github.com/ethereum/go-ethereum/event" 21 ) 22 23 //经理是一个主要的客户经理,可以与 24 //用于签署事务的后端。 25 type Manager struct { 26 backends map[reflect.Type][]Backend //当前注册的后端索引 27 updaters []event.Subscription //所有后端的钱包更新订阅 28 updates chan WalletEvent //后端钱包更改的订阅接收器 29 wallets []Wallet //缓存所有注册后端的所有钱包 30 31 feed event.Feed //钱包信息提示到达/离开 32 33 quit chan chan error 34 lock sync.RWMutex 35 } 36 37 //NewManager创建一个通用的客户经理,通过 38 //支撑的后端。 39 func NewManager(backends ...Backend) *Manager { 40 //从后端检索钱包的初始列表并按URL排序 41 var wallets []Wallet 42 for _, backend := range backends { 43 wallets = merge(wallets, backend.Wallets()...) 44 } 45 //从所有后端订阅钱包通知 46 updates := make(chan WalletEvent, 4*len(backends)) 47 48 subs := make([]event.Subscription, len(backends)) 49 for i, backend := range backends { 50 subs[i] = backend.Subscribe(updates) 51 } 52 //召集客户经理并返回 53 am := &Manager{ 54 backends: make(map[reflect.Type][]Backend), 55 updaters: subs, 56 updates: updates, 57 wallets: wallets, 58 quit: make(chan chan error), 59 } 60 for _, backend := range backends { 61 kind := reflect.TypeOf(backend) 62 am.backends[kind] = append(am.backends[kind], backend) 63 } 64 go am.update() 65 66 return am 67 } 68 69 //关闭将终止客户经理的内部通知进程。 70 func (am *Manager) Close() error { 71 errc := make(chan error) 72 am.quit <- errc 73 return <-errc 74 } 75 76 //更新是钱包事件循环,监听来自后端的通知 77 //更新钱包的缓存。 78 func (am *Manager) update() { 79 //管理器终止时关闭所有订阅 80 defer func() { 81 am.lock.Lock() 82 for _, sub := range am.updaters { 83 sub.Unsubscribe() 84 } 85 am.updaters = nil 86 am.lock.Unlock() 87 }() 88 89 //循环直至终止 90 for { 91 select { 92 case event := <-am.updates: 93 // 94 am.lock.Lock() 95 switch event.Kind { 96 case WalletArrived: 97 am.wallets = merge(am.wallets, event.Wallet) 98 case WalletDropped: 99 am.wallets = drop(am.wallets, event.Wallet) 100 } 101 am.lock.Unlock() 102 103 //通知事件的任何侦听器 104 am.feed.Send(event) 105 106 case errc := <-am.quit: 107 //经理终止,返回 108 errc <- nil 109 return 110 } 111 } 112 } 113 114 //后端从帐户管理器中检索具有给定类型的后端。 115 func (am *Manager) Backends(kind reflect.Type) []Backend { 116 return am.backends[kind] 117 } 118 119 //钱包将返回在此帐户管理器下注册的所有签名者帐户。 120 func (am *Manager) Wallets() []Wallet { 121 am.lock.RLock() 122 defer am.lock.RUnlock() 123 124 cpy := make([]Wallet, len(am.wallets)) 125 copy(cpy, am.wallets) 126 return cpy 127 } 128 129 //Wallet检索与特定URL关联的钱包。 130 func (am *Manager) Wallet(url string) (Wallet, error) { 131 am.lock.RLock() 132 defer am.lock.RUnlock() 133 134 parsed, err := parseURL(url) 135 if err != nil { 136 return nil, err 137 } 138 for _, wallet := range am.Wallets() { 139 if wallet.URL() == parsed { 140 return wallet, nil 141 } 142 } 143 return nil, ErrUnknownWallet 144 } 145 146 //查找与特定帐户对应的钱包。自从 147 //帐户可以动态地添加到钱包中或从钱包中删除,此方法具有 148 //钱包数量的线性运行时间。 149 func (am *Manager) Find(account Account) (Wallet, error) { 150 am.lock.RLock() 151 defer am.lock.RUnlock() 152 153 for _, wallet := range am.wallets { 154 if wallet.Contains(account) { 155 return wallet, nil 156 } 157 } 158 return nil, ErrUnknownAccount 159 } 160 161 //订阅创建异步订阅以在 162 //经理检测到钱包从其任何后端到达或离开。 163 func (am *Manager) Subscribe(sink chan<- WalletEvent) event.Subscription { 164 return am.feed.Subscribe(sink) 165 } 166 167 //merge是一种类似于append的钱包排序方式,其中 168 //通过在正确位置插入新钱包,可以保留原始列表。 169 // 170 //假定原始切片已按URL排序。 171 func merge(slice []Wallet, wallets ...Wallet) []Wallet { 172 for _, wallet := range wallets { 173 n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 }) 174 if n == len(slice) { 175 slice = append(slice, wallet) 176 continue 177 } 178 slice = append(slice[:n], append([]Wallet{wallet}, slice[n:]...)...) 179 } 180 return slice 181 } 182 183 //drop是merge的coutterpart,它从排序后的 184 //缓存并删除指定的。 185 func drop(slice []Wallet, wallets ...Wallet) []Wallet { 186 for _, wallet := range wallets { 187 n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 }) 188 if n == len(slice) { 189 //未找到钱包,可能在启动过程中发生 190 continue 191 } 192 slice = append(slice[:n], slice[n+1:]...) 193 } 194 return slice 195 } 196