Files
waf-platform/EdgeDNS/internal/models/record_ids.go
2026-02-04 20:27:13 +08:00

173 lines
3.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package models
import (
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/iwind/TeaGo/rands"
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
type recordIdInfo struct {
Id int64
Weight int32
}
type RecordIds struct {
IdList []*recordIdInfo
IdBucket []int64
RoundIndex int
totalWeight int64
}
func NewRecordIds() *RecordIds {
return &RecordIds{}
}
func (this *RecordIds) IsEmpty() bool {
return len(this.IdList) == 0
}
func (this *RecordIds) Add(newId int64, weight int32) {
if weight <= 0 {
weight = 10
}
const maxWeight = 999999
if weight > maxWeight {
weight = maxWeight
}
// 检查是否存在
for _, idInfo := range this.IdList {
if idInfo.Id == newId {
return
}
}
// 添加
this.IdList = append(this.IdList, &recordIdInfo{
Id: newId,
Weight: weight,
})
// 重置数据
this.resetData()
}
func (this *RecordIds) Remove(oldId int64) {
defer this.resetData()
var newIdList = []*recordIdInfo{}
for _, idInfo := range this.IdList {
if idInfo.Id == oldId {
continue
}
newIdList = append(newIdList, idInfo)
}
this.IdList = newIdList
}
// NextId for round-robin
func (this *RecordIds) NextId() int64 {
var l = len(this.IdList)
if l == 0 {
return 0
}
if l == 1 {
return this.IdList[0].Id
}
if this.RoundIndex > l-1 {
this.RoundIndex = 0
}
var id = this.IdList[this.RoundIndex].Id
this.RoundIndex++
return id
}
func (this *RecordIds) RandomIds(count int) []int64 {
if count <= 0 {
count = dnsconfigs.NSAnswerDefaultSize
}
var totalRecords = len(this.IdList)
if totalRecords == 0 {
return nil
}
if totalRecords == 1 {
return []int64{this.IdList[0].Id} // duplicate
}
if totalRecords < count {
count = totalRecords
}
var totalIds = len(this.IdBucket)
var startIndex = rands.Int(0, totalIds-1)
var endIndex = startIndex + count - 1
if endIndex <= totalIds-1 {
return this.IdBucket[startIndex : endIndex+1]
}
return append(this.IdBucket[startIndex:totalIds], this.IdBucket[0:endIndex-totalIds+1]...)
}
func (this *RecordIds) resetData() {
this.resetWeight()
}
func (this *RecordIds) resetWeight() {
var totalWeight int64
var weightMap = map[int32]bool{} // weight => bool
var hasUniqueWeights = false
var ids []int64
for _, idInfo := range this.IdList {
totalWeight += int64(idInfo.Weight)
// 检查是否有不同的权重
if len(weightMap) > 0 && !weightMap[idInfo.Weight] {
hasUniqueWeights = true
}
weightMap[idInfo.Weight] = true
ids = append(ids, idInfo.Id)
}
// 根据权重重新组织IDs
if hasUniqueWeights {
var newIds = []int64{}
for _, idInfo := range this.IdList {
for i := int32(0); i < idInfo.Weight; i++ {
newIds = append(newIds, idInfo.Id)
}
}
ids = newIds
}
var countIds = len(ids)
if countIds > 0 {
rand.Shuffle(countIds, func(i, j int) {
ids[i], ids[j] = ids[j], ids[i]
})
}
this.totalWeight = totalWeight
this.IdBucket = ids
}