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