github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/ratelimiter/rwbucket.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package ratelimiter
     7  
     8  import (
     9  	"github.com/insolar/vanilla/atomickit"
    10  )
    11  
    12  type RWRateQuota interface {
    13  	RateQuota
    14  	TakeWriteQuota(max int64) int64
    15  	TakeWriteQuotaNoWait(max int64) int64
    16  	WriteBucket() RateQuota
    17  }
    18  
    19  func NewRWBucket(bm *PeriodManager, read, write BucketConfig) *RWBucket {
    20  	read.Check()
    21  	write.Check()
    22  
    23  	return &RWBucket{RWSubBucket{
    24  		stateR: BucketState{
    25  			filledAmount: atomickit.NewUint32(read.RefillAmount),
    26  			bucketConfig: read,
    27  		},
    28  		stateW: BucketState{
    29  			filledAmount: atomickit.NewUint32(write.RefillAmount),
    30  			bucketConfig: write,
    31  		},
    32  		refiller: PeriodRefiller{
    33  			manager:     bm,
    34  			periodCount: atomickit.NewUint64(bm.currentPeriod.Load()),
    35  		}}}
    36  }
    37  
    38  func NewRWChildBucket(parent ParentRWBucket, read, write BucketConfig) *RWChildBucket {
    39  	read.Check()
    40  	write.Check()
    41  
    42  	bm := parent.(periodBucket).GetManager()
    43  	return &RWChildBucket{RWChildSubBucket{
    44  		stateR: BucketState{
    45  			bucketConfig: read,
    46  		}, stateW: BucketState{
    47  			bucketConfig: write,
    48  		}, refiller: PeriodRefiller{
    49  			manager:     bm,
    50  			periodCount: atomickit.NewUint64(bm.currentPeriod.Load()),
    51  		}, parent: parent}}
    52  }
    53  
    54  func NewRWChildBucketRatio(parent ParentRWBucket, refillRatio, maxRatio float32) *RWChildBucket {
    55  	cfgR, cfgW := parent.CopyRWConfig()
    56  	return NewRWChildBucket(parent, cfgR.Scale(refillRatio, maxRatio), cfgW.Scale(refillRatio, maxRatio))
    57  }
    58  
    59  var _ ParentRWBucket = &RWBucket{}
    60  var _ RWRateQuota = &RWBucket{}
    61  var _ periodBucket = &RWBucket{}
    62  
    63  type RWBucket struct {
    64  	s RWSubBucket
    65  }
    66  
    67  func (p *RWBucket) GetManager() *PeriodManager {
    68  	return p.s.refiller.manager
    69  }
    70  
    71  func (p *RWBucket) CopyRWConfig() (read, write BucketConfig) {
    72  	return p.s.stateR.config(), p.s.stateW.config()
    73  }
    74  
    75  func (p *RWBucket) TakeQuota(max int64) int64 {
    76  	return p.s.refiller.TakeQuota(max, &p.s.stateR, p.s.refillR)
    77  }
    78  
    79  func (p *RWBucket) TakeQuotaNoWait(max int64) int64 {
    80  	return p.s.refiller.TakeQuotaNoWait(max, &p.s.stateR, p.s.refillR)
    81  }
    82  
    83  func (p *RWBucket) TakeWriteQuota(max int64) int64 {
    84  	return p.s.refiller.TakeQuota(max, &p.s.stateW, p.s.refillW)
    85  }
    86  
    87  func (p *RWBucket) TakeWriteQuotaNoWait(max int64) int64 {
    88  	return p.s.refiller.TakeQuotaNoWait(max, &p.s.stateW, p.s.refillW)
    89  }
    90  
    91  func (p *RWBucket) TakeReadQuotaNoScale(max uint32) uint32 {
    92  	return p.s.stateR.TakeQuotaNoScale(max, p.s.refillR)
    93  }
    94  
    95  func (p *RWBucket) TakeWriteQuotaNoScale(max uint32) uint32 {
    96  	return p.s.stateW.TakeQuotaNoScale(max, p.s.refillW)
    97  }
    98  
    99  func (p *RWBucket) WriteBucket() RateQuota {
   100  	return &p.s
   101  }
   102  
   103  type RWSubBucket struct {
   104  	stateR   BucketState
   105  	stateW   BucketState
   106  	refiller PeriodRefiller
   107  }
   108  
   109  func (p *RWSubBucket) TakeQuota(max int64) int64 {
   110  	return p.refiller.TakeQuota(max, &p.stateW, p.refillW)
   111  }
   112  
   113  func (p *RWSubBucket) TakeQuotaNoWait(max int64) int64 {
   114  	return p.refiller.TakeQuotaNoWait(max, &p.stateW, p.refillW)
   115  }
   116  
   117  func (p *RWSubBucket) refillR(uint32) uint32 {
   118  	x := p.refiller.GetRefillCount()
   119  	p.stateW.ForceRefill(p.stateW.PeriodsToRefill(x))
   120  	return p.stateR.PeriodsToRefill(x)
   121  }
   122  
   123  func (p *RWSubBucket) refillW(uint32) uint32 {
   124  	x := p.refiller.GetRefillCount()
   125  	p.stateR.ForceRefill(p.stateR.PeriodsToRefill(x))
   126  	return p.stateW.PeriodsToRefill(x)
   127  }
   128  
   129  /**********************************************************/
   130  
   131  var _ ParentRWBucket = &RWChildBucket{}
   132  var _ RWRateQuota = &RWChildBucket{}
   133  var _ periodBucket = &RWChildBucket{}
   134  
   135  type RWChildBucket struct {
   136  	s RWChildSubBucket
   137  }
   138  
   139  func (p *RWChildBucket) GetManager() *PeriodManager {
   140  	return p.s.refiller.manager
   141  }
   142  
   143  func (p *RWChildBucket) CopyRWConfig() (read, write BucketConfig) {
   144  	return p.s.stateR.config(), p.s.stateW.config()
   145  }
   146  
   147  func (p *RWChildBucket) TakeQuota(max int64) int64 {
   148  	return p.s.refiller.TakeQuota(max, &p.s.stateR, p.s.refillR)
   149  }
   150  
   151  func (p *RWChildBucket) TakeQuotaNoWait(max int64) int64 {
   152  	return p.s.refiller.TakeQuotaNoWait(max, &p.s.stateR, p.s.refillR)
   153  }
   154  
   155  func (p *RWChildBucket) TakeWriteQuota(max int64) int64 {
   156  	return p.s.refiller.TakeQuota(max, &p.s.stateW, p.s.refillW)
   157  }
   158  
   159  func (p *RWChildBucket) TakeWriteQuotaNoWait(max int64) int64 {
   160  	return p.s.refiller.TakeQuotaNoWait(max, &p.s.stateW, p.s.refillW)
   161  }
   162  
   163  func (p *RWChildBucket) TakeReadQuotaNoScale(max uint32) uint32 {
   164  	return p.s.stateR.TakeQuotaNoScale(max, p.s.refillR)
   165  }
   166  
   167  func (p *RWChildBucket) TakeWriteQuotaNoScale(max uint32) uint32 {
   168  	return p.s.stateW.TakeQuotaNoScale(max, p.s.refillW)
   169  }
   170  
   171  func (p *RWChildBucket) WriteBucket() RateQuota {
   172  	return &p.s
   173  }
   174  
   175  type ParentRWBucket interface {
   176  	TakeReadQuotaNoScale(max uint32) uint32
   177  	TakeWriteQuotaNoScale(max uint32) uint32
   178  	CopyRWConfig() (read, write BucketConfig)
   179  }
   180  
   181  type RWChildSubBucket struct {
   182  	stateR   BucketState
   183  	stateW   BucketState
   184  	refiller PeriodRefiller
   185  
   186  	quotaR RefillQuota
   187  	quotaW RefillQuota
   188  	parent ParentRWBucket
   189  }
   190  
   191  func (p *RWChildSubBucket) TakeQuota(max int64) int64 {
   192  	return p.refiller.TakeQuota(max, &p.stateW, p.refillW)
   193  }
   194  
   195  func (p *RWChildSubBucket) TakeQuotaNoWait(max int64) int64 {
   196  	return p.refiller.TakeQuotaNoWait(max, &p.stateW, p.refillW)
   197  }
   198  
   199  func (p *RWChildSubBucket) refillR(needed uint32) uint32 {
   200  	x := p.refiller.GetRefillCount()
   201  	p.stateW.ForceRefill(p.quotaW.Refill(needed, x, &p.stateW, p.parent.TakeWriteQuotaNoScale))
   202  	return p.quotaR.Refill(needed, x, &p.stateR, p.parent.TakeReadQuotaNoScale)
   203  }
   204  
   205  func (p *RWChildSubBucket) refillW(needed uint32) uint32 {
   206  	x := p.refiller.GetRefillCount()
   207  	p.stateR.ForceRefill(p.quotaR.Refill(needed, x, &p.stateR, p.parent.TakeReadQuotaNoScale))
   208  	return p.quotaW.Refill(needed, x, &p.stateW, p.parent.TakeWriteQuotaNoScale)
   209  }