Files
EdgeNode/internal/utils/counters/item.go

129 lines
2.8 KiB
Go
Raw Normal View History

// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package counters
import (
"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
)
2023-11-15 15:57:41 +08:00
const spanMaxValue = 10_000_000
2023-12-24 15:11:09 +08:00
const maxSpans = 10
2023-11-15 15:57:41 +08:00
type Item[T SupportedUIntType] struct {
2023-12-24 15:11:09 +08:00
spans [maxSpans + 1]T
lastUpdateTime int64
2023-11-15 15:57:41 +08:00
lifeSeconds int64
spanSeconds int64
}
2023-11-15 15:57:41 +08:00
func NewItem[T SupportedUIntType](lifeSeconds int) *Item[T] {
if lifeSeconds <= 0 {
lifeSeconds = 60
}
2023-12-24 15:11:09 +08:00
var spanSeconds = lifeSeconds / maxSpans
if spanSeconds < 1 {
spanSeconds = 1
2023-12-24 15:11:09 +08:00
} else if lifeSeconds > maxSpans && lifeSeconds%maxSpans != 0 {
spanSeconds++
}
2023-11-15 15:57:41 +08:00
return &Item[T]{
lifeSeconds: int64(lifeSeconds),
spanSeconds: int64(spanSeconds),
lastUpdateTime: fasttime.Now().Unix(),
}
}
2023-11-15 15:57:41 +08:00
func (this *Item[T]) Increase() (result T) {
var currentTime = fasttime.Now().Unix()
var currentSpanIndex = this.calculateSpanIndex(currentTime)
// return quickly
if this.lastUpdateTime == currentTime {
2023-11-15 15:57:41 +08:00
if this.spans[currentSpanIndex] < spanMaxValue {
this.spans[currentSpanIndex]++
}
2023-10-05 16:29:02 +08:00
for _, count := range this.spans {
result += count
}
return
}
if this.lastUpdateTime > 0 {
if currentTime-this.lastUpdateTime > this.lifeSeconds {
for index := range this.spans {
this.spans[index] = 0
}
} else {
var lastSpanIndex = this.calculateSpanIndex(this.lastUpdateTime)
2023-10-05 16:29:02 +08:00
if lastSpanIndex != currentSpanIndex {
var countSpans = len(this.spans)
// reset values between LAST and CURRENT
for index := lastSpanIndex + 1; ; index++ {
var realIndex = index % countSpans
this.spans[realIndex] = 0
2023-10-05 16:29:02 +08:00
if realIndex == currentSpanIndex {
break
}
}
}
}
}
2023-11-15 15:57:41 +08:00
if this.spans[currentSpanIndex] < spanMaxValue {
this.spans[currentSpanIndex]++
}
this.lastUpdateTime = currentTime
2023-10-05 16:29:02 +08:00
for _, count := range this.spans {
result += count
}
return
}
2023-11-15 15:57:41 +08:00
func (this *Item[T]) Sum() (result T) {
if this.lastUpdateTime == 0 {
return 0
}
var currentTime = fasttime.Now().Unix()
var currentSpanIndex = this.calculateSpanIndex(currentTime)
if currentTime-this.lastUpdateTime > this.lifeSeconds {
return 0
} else {
var lastSpanIndex = this.calculateSpanIndex(this.lastUpdateTime)
var countSpans = len(this.spans)
2023-10-05 16:29:02 +08:00
for index := currentSpanIndex + 1; ; index++ {
var realIndex = index % countSpans
result += this.spans[realIndex]
if realIndex == lastSpanIndex {
break
}
}
}
return result
}
2023-11-15 15:57:41 +08:00
func (this *Item[T]) Reset() {
for index := range this.spans {
this.spans[index] = 0
}
}
2023-11-15 15:57:41 +08:00
func (this *Item[T]) IsExpired(currentTime int64) bool {
2023-07-15 11:08:25 +08:00
return this.lastUpdateTime < currentTime-this.lifeSeconds-this.spanSeconds
}
2023-11-15 15:57:41 +08:00
func (this *Item[T]) calculateSpanIndex(timestamp int64) int {
2023-12-24 15:11:09 +08:00
var index = int(timestamp % this.lifeSeconds / this.spanSeconds)
if index > maxSpans-1 {
return maxSpans - 1
}
return index
}