github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/counters/item.go (about)

     1  // Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
     2  
     3  package counters
     4  
     5  import (
     6  	"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
     7  )
     8  
     9  const spanMaxValue = 10_000_000
    10  const maxSpans = 10
    11  
    12  type Item[T SupportedUIntType] struct {
    13  	spans          [maxSpans + 1]T
    14  	lastUpdateTime int64
    15  	lifeSeconds    int64
    16  	spanSeconds    int64
    17  }
    18  
    19  func NewItem[T SupportedUIntType](lifeSeconds int) Item[T] {
    20  	if lifeSeconds <= 0 {
    21  		lifeSeconds = 60
    22  	}
    23  	var spanSeconds = lifeSeconds / maxSpans
    24  	if spanSeconds < 1 {
    25  		spanSeconds = 1
    26  	} else if lifeSeconds > maxSpans && lifeSeconds%maxSpans != 0 {
    27  		spanSeconds++
    28  	}
    29  
    30  	return Item[T]{
    31  		lifeSeconds:    int64(lifeSeconds),
    32  		spanSeconds:    int64(spanSeconds),
    33  		lastUpdateTime: fasttime.Now().Unix(),
    34  	}
    35  }
    36  
    37  func (this *Item[T]) Increase() (result T) {
    38  	var currentTime = fasttime.Now().Unix()
    39  	var currentSpanIndex = this.calculateSpanIndex(currentTime)
    40  
    41  	// return quickly
    42  	if this.lastUpdateTime == currentTime {
    43  		if this.spans[currentSpanIndex] < spanMaxValue {
    44  			this.spans[currentSpanIndex]++
    45  		}
    46  		for _, count := range this.spans {
    47  			result += count
    48  		}
    49  		return
    50  	}
    51  
    52  	if this.lastUpdateTime > 0 {
    53  		if currentTime-this.lastUpdateTime > this.lifeSeconds {
    54  			for index := range this.spans {
    55  				this.spans[index] = 0
    56  			}
    57  		} else {
    58  			var lastSpanIndex = this.calculateSpanIndex(this.lastUpdateTime)
    59  
    60  			if lastSpanIndex != currentSpanIndex {
    61  				var countSpans = len(this.spans)
    62  
    63  				// reset values between LAST and CURRENT
    64  				for index := lastSpanIndex + 1; ; index++ {
    65  					var realIndex = index % countSpans
    66  					this.spans[realIndex] = 0
    67  					if realIndex == currentSpanIndex {
    68  						break
    69  					}
    70  				}
    71  			}
    72  		}
    73  	}
    74  
    75  	if this.spans[currentSpanIndex] < spanMaxValue {
    76  		this.spans[currentSpanIndex]++
    77  	}
    78  	this.lastUpdateTime = currentTime
    79  
    80  	for _, count := range this.spans {
    81  		result += count
    82  	}
    83  
    84  	return
    85  }
    86  
    87  func (this *Item[T]) Sum() (result T) {
    88  	if this.lastUpdateTime == 0 {
    89  		return 0
    90  	}
    91  
    92  	var currentTime = fasttime.Now().Unix()
    93  	var currentSpanIndex = this.calculateSpanIndex(currentTime)
    94  
    95  	if currentTime-this.lastUpdateTime > this.lifeSeconds {
    96  		return 0
    97  	} else {
    98  		var lastSpanIndex = this.calculateSpanIndex(this.lastUpdateTime)
    99  		var countSpans = len(this.spans)
   100  		for index := currentSpanIndex + 1; ; index++ {
   101  			var realIndex = index % countSpans
   102  			result += this.spans[realIndex]
   103  			if realIndex == lastSpanIndex {
   104  				break
   105  			}
   106  		}
   107  	}
   108  
   109  	return result
   110  }
   111  
   112  func (this *Item[T]) Reset() {
   113  	for index := range this.spans {
   114  		this.spans[index] = 0
   115  	}
   116  }
   117  
   118  func (this *Item[T]) IsExpired(currentTime int64) bool {
   119  	return this.lastUpdateTime < currentTime-this.lifeSeconds-this.spanSeconds
   120  }
   121  
   122  func (this *Item[T]) calculateSpanIndex(timestamp int64) int {
   123  	var index = int(timestamp % this.lifeSeconds / this.spanSeconds)
   124  	if index > maxSpans-1 {
   125  		return maxSpans - 1
   126  	}
   127  	return index
   128  }
   129  
   130  func (this *Item[T]) IsOk() bool {
   131  	return this.lifeSeconds > 0
   132  }