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