github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/simulations/simulation.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  //版权所有2017 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 simulations
    26  
    27  import (
    28  	"context"
    29  	"time"
    30  
    31  	"github.com/ethereum/go-ethereum/p2p/discover"
    32  )
    33  
    34  //模拟为在模拟网络中运行操作提供了一个框架
    35  //然后等待期望得到满足
    36  type Simulation struct {
    37  	network *Network
    38  }
    39  
    40  //新模拟返回在给定网络中运行的新模拟
    41  func NewSimulation(network *Network) *Simulation {
    42  	return &Simulation{
    43  		network: network,
    44  	}
    45  }
    46  
    47  //运行通过执行步骤的操作执行模拟步骤,并
    48  //然后等待步骤的期望得到满足
    49  func (s *Simulation) Run(ctx context.Context, step *Step) (result *StepResult) {
    50  	result = newStepResult()
    51  
    52  	result.StartedAt = time.Now()
    53  	defer func() { result.FinishedAt = time.Now() }()
    54  
    55  //在步骤期间监视网络事件
    56  	stop := s.watchNetwork(result)
    57  	defer stop()
    58  
    59  //执行操作
    60  	if err := step.Action(ctx); err != nil {
    61  		result.Error = err
    62  		return
    63  	}
    64  
    65  //等待所有节点期望通过、错误或超时
    66  	nodes := make(map[discover.NodeID]struct{}, len(step.Expect.Nodes))
    67  	for _, id := range step.Expect.Nodes {
    68  		nodes[id] = struct{}{}
    69  	}
    70  	for len(result.Passes) < len(nodes) {
    71  		select {
    72  		case id := <-step.Trigger:
    73  //如果不检查节点,则跳过
    74  			if _, ok := nodes[id]; !ok {
    75  				continue
    76  			}
    77  
    78  //如果节点已通过,则跳过
    79  			if _, ok := result.Passes[id]; ok {
    80  				continue
    81  			}
    82  
    83  //运行节点期望检查
    84  			pass, err := step.Expect.Check(ctx, id)
    85  			if err != nil {
    86  				result.Error = err
    87  				return
    88  			}
    89  			if pass {
    90  				result.Passes[id] = time.Now()
    91  			}
    92  		case <-ctx.Done():
    93  			result.Error = ctx.Err()
    94  			return
    95  		}
    96  	}
    97  
    98  	return
    99  }
   100  
   101  func (s *Simulation) watchNetwork(result *StepResult) func() {
   102  	stop := make(chan struct{})
   103  	done := make(chan struct{})
   104  	events := make(chan *Event)
   105  	sub := s.network.Events().Subscribe(events)
   106  	go func() {
   107  		defer close(done)
   108  		defer sub.Unsubscribe()
   109  		for {
   110  			select {
   111  			case event := <-events:
   112  				result.NetworkEvents = append(result.NetworkEvents, event)
   113  			case <-stop:
   114  				return
   115  			}
   116  		}
   117  	}()
   118  	return func() {
   119  		close(stop)
   120  		<-done
   121  	}
   122  }
   123  
   124  type Step struct {
   125  //操作是为此步骤执行的操作
   126  	Action func(context.Context) error
   127  
   128  //触发器是一个接收节点ID并触发
   129  //该节点的预期检查
   130  	Trigger chan discover.NodeID
   131  
   132  //Expect是执行此步骤时等待的期望
   133  	Expect *Expectation
   134  }
   135  
   136  type Expectation struct {
   137  //节点是要检查的节点列表
   138  	Nodes []discover.NodeID
   139  
   140  //检查给定节点是否满足预期
   141  	Check func(context.Context, discover.NodeID) (bool, error)
   142  }
   143  
   144  func newStepResult() *StepResult {
   145  	return &StepResult{
   146  		Passes: make(map[discover.NodeID]time.Time),
   147  	}
   148  }
   149  
   150  type StepResult struct {
   151  //错误是运行步骤时遇到的错误
   152  	Error error
   153  
   154  //Startedat是步骤开始的时间
   155  	StartedAt time.Time
   156  
   157  //FinishedAt是步骤完成的时间。
   158  	FinishedAt time.Time
   159  
   160  //传递是成功节点期望的时间戳
   161  	Passes map[discover.NodeID]time.Time
   162  
   163  //NetworkEvents是在步骤中发生的网络事件。
   164  	NetworkEvents []*Event
   165  }