github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/les/flowcontrol/manager.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  //版权所有2016 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  //包流控制实现客户端流控制机制
    26  package flowcontrol
    27  
    28  import (
    29  	"sync"
    30  	"time"
    31  
    32  	"github.com/ethereum/go-ethereum/common/mclock"
    33  )
    34  
    35  const rcConst = 1000000
    36  
    37  type cmNode struct {
    38  	node                         *ClientNode
    39  	lastUpdate                   mclock.AbsTime
    40  	serving, recharging          bool
    41  	rcWeight                     uint64
    42  	rcValue, rcDelta, startValue int64
    43  	finishRecharge               mclock.AbsTime
    44  }
    45  
    46  func (node *cmNode) update(time mclock.AbsTime) {
    47  	dt := int64(time - node.lastUpdate)
    48  	node.rcValue += node.rcDelta * dt / rcConst
    49  	node.lastUpdate = time
    50  	if node.recharging && time >= node.finishRecharge {
    51  		node.recharging = false
    52  		node.rcDelta = 0
    53  		node.rcValue = 0
    54  	}
    55  }
    56  
    57  func (node *cmNode) set(serving bool, simReqCnt, sumWeight uint64) {
    58  	if node.serving && !serving {
    59  		node.recharging = true
    60  		sumWeight += node.rcWeight
    61  	}
    62  	node.serving = serving
    63  	if node.recharging && serving {
    64  		node.recharging = false
    65  		sumWeight -= node.rcWeight
    66  	}
    67  
    68  	node.rcDelta = 0
    69  	if serving {
    70  		node.rcDelta = int64(rcConst / simReqCnt)
    71  	}
    72  	if node.recharging {
    73  		node.rcDelta = -int64(node.node.cm.rcRecharge * node.rcWeight / sumWeight)
    74  		node.finishRecharge = node.lastUpdate + mclock.AbsTime(node.rcValue*rcConst/(-node.rcDelta))
    75  	}
    76  }
    77  
    78  type ClientManager struct {
    79  	lock                             sync.Mutex
    80  	nodes                            map[*cmNode]struct{}
    81  	simReqCnt, sumWeight, rcSumValue uint64
    82  	maxSimReq, maxRcSum              uint64
    83  	rcRecharge                       uint64
    84  	resumeQueue                      chan chan bool
    85  	time                             mclock.AbsTime
    86  }
    87  
    88  func NewClientManager(rcTarget, maxSimReq, maxRcSum uint64) *ClientManager {
    89  	cm := &ClientManager{
    90  		nodes:       make(map[*cmNode]struct{}),
    91  		resumeQueue: make(chan chan bool),
    92  		rcRecharge:  rcConst * rcConst / (100*rcConst/rcTarget - rcConst),
    93  		maxSimReq:   maxSimReq,
    94  		maxRcSum:    maxRcSum,
    95  	}
    96  	go cm.queueProc()
    97  	return cm
    98  }
    99  
   100  func (self *ClientManager) Stop() {
   101  	self.lock.Lock()
   102  	defer self.lock.Unlock()
   103  
   104  //向任何等待接受例程发出返回false的信号
   105  	self.nodes = make(map[*cmNode]struct{})
   106  	close(self.resumeQueue)
   107  }
   108  
   109  func (self *ClientManager) addNode(cnode *ClientNode) *cmNode {
   110  	time := mclock.Now()
   111  	node := &cmNode{
   112  		node:           cnode,
   113  		lastUpdate:     time,
   114  		finishRecharge: time,
   115  		rcWeight:       1,
   116  	}
   117  	self.lock.Lock()
   118  	defer self.lock.Unlock()
   119  
   120  	self.nodes[node] = struct{}{}
   121  	self.update(mclock.Now())
   122  	return node
   123  }
   124  
   125  func (self *ClientManager) removeNode(node *cmNode) {
   126  	self.lock.Lock()
   127  	defer self.lock.Unlock()
   128  
   129  	time := mclock.Now()
   130  	self.stop(node, time)
   131  	delete(self.nodes, node)
   132  	self.update(time)
   133  }
   134  
   135  //重新计算总重量
   136  func (self *ClientManager) updateNodes(time mclock.AbsTime) (rce bool) {
   137  	var sumWeight, rcSum uint64
   138  	for node := range self.nodes {
   139  		rc := node.recharging
   140  		node.update(time)
   141  		if rc && !node.recharging {
   142  			rce = true
   143  		}
   144  		if node.recharging {
   145  			sumWeight += node.rcWeight
   146  		}
   147  		rcSum += uint64(node.rcValue)
   148  	}
   149  	self.sumWeight = sumWeight
   150  	self.rcSumValue = rcSum
   151  	return
   152  }
   153  
   154  func (self *ClientManager) update(time mclock.AbsTime) {
   155  	for {
   156  		firstTime := time
   157  		for node := range self.nodes {
   158  			if node.recharging && node.finishRecharge < firstTime {
   159  				firstTime = node.finishRecharge
   160  			}
   161  		}
   162  		if self.updateNodes(firstTime) {
   163  			for node := range self.nodes {
   164  				if node.recharging {
   165  					node.set(node.serving, self.simReqCnt, self.sumWeight)
   166  				}
   167  			}
   168  		} else {
   169  			self.time = time
   170  			return
   171  		}
   172  	}
   173  }
   174  
   175  func (self *ClientManager) canStartReq() bool {
   176  	return self.simReqCnt < self.maxSimReq && self.rcSumValue < self.maxRcSum
   177  }
   178  
   179  func (self *ClientManager) queueProc() {
   180  	for rc := range self.resumeQueue {
   181  		for {
   182  			time.Sleep(time.Millisecond * 10)
   183  			self.lock.Lock()
   184  			self.update(mclock.Now())
   185  			cs := self.canStartReq()
   186  			self.lock.Unlock()
   187  			if cs {
   188  				break
   189  			}
   190  		}
   191  		close(rc)
   192  	}
   193  }
   194  
   195  func (self *ClientManager) accept(node *cmNode, time mclock.AbsTime) bool {
   196  	self.lock.Lock()
   197  	defer self.lock.Unlock()
   198  
   199  	self.update(time)
   200  	if !self.canStartReq() {
   201  		resume := make(chan bool)
   202  		self.lock.Unlock()
   203  		self.resumeQueue <- resume
   204  		<-resume
   205  		self.lock.Lock()
   206  		if _, ok := self.nodes[node]; !ok {
   207  return false //如果节点已删除或管理器已停止,则拒绝
   208  		}
   209  	}
   210  	self.simReqCnt++
   211  	node.set(true, self.simReqCnt, self.sumWeight)
   212  	node.startValue = node.rcValue
   213  	self.update(self.time)
   214  	return true
   215  }
   216  
   217  func (self *ClientManager) stop(node *cmNode, time mclock.AbsTime) {
   218  	if node.serving {
   219  		self.update(time)
   220  		self.simReqCnt--
   221  		node.set(false, self.simReqCnt, self.sumWeight)
   222  		self.update(time)
   223  	}
   224  }
   225  
   226  func (self *ClientManager) processed(node *cmNode, time mclock.AbsTime) (rcValue, rcCost uint64) {
   227  	self.lock.Lock()
   228  	defer self.lock.Unlock()
   229  
   230  	self.stop(node, time)
   231  	return uint64(node.rcValue), uint64(node.rcValue - node.startValue)
   232  }