1.4.5.2
This commit is contained in:
172
EdgeDNS/internal/models/record_ids.go
Normal file
172
EdgeDNS/internal/models/record_ids.go
Normal file
@@ -0,0 +1,172 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user