Files
elmprodvpn/selective-vpn-api/app/transport_client_runtime_alloc_reconcile.go

89 lines
2.0 KiB
Go

package app
import (
"sort"
"strings"
)
func reconcileTransportAllocations(items []TransportClient, forceRebalance bool) ([]TransportClient, bool) {
if len(items) == 0 {
return items, false
}
changed := false
sort.Slice(items, func(i, j int) bool { return items[i].ID < items[j].ID })
usedMarks := map[uint64]struct{}{}
usedPrefs := map[int]struct{}{}
missingMark := make([]int, 0)
missingPref := make([]int, 0)
needRebalance := forceRebalance
for i := range items {
if m, ok := parseTransportMarkHex(items[i].MarkHex); ok {
if _, exists := usedMarks[m]; exists {
needRebalance = true
} else {
usedMarks[m] = struct{}{}
}
} else if strings.TrimSpace(items[i].MarkHex) == "" {
missingMark = append(missingMark, i)
} else {
needRebalance = true
}
if p, ok := parseTransportPref(items[i].PriorityBase); ok {
if _, exists := usedPrefs[p]; exists {
needRebalance = true
} else {
usedPrefs[p] = struct{}{}
}
} else if items[i].PriorityBase == 0 {
missingPref = append(missingPref, i)
} else {
needRebalance = true
}
}
if needRebalance {
usedMarks = map[uint64]struct{}{}
usedPrefs = map[int]struct{}{}
for i := range items {
m := nextTransportMark(usedMarks)
p := nextTransportPref(usedPrefs)
usedMarks[m] = struct{}{}
usedPrefs[p] = struct{}{}
markHex := formatTransportMarkHex(m)
if items[i].MarkHex != markHex {
items[i].MarkHex = markHex
changed = true
}
if items[i].PriorityBase != p {
items[i].PriorityBase = p
changed = true
}
}
return items, changed
}
for _, idx := range missingMark {
m := nextTransportMark(usedMarks)
usedMarks[m] = struct{}{}
markHex := formatTransportMarkHex(m)
if items[idx].MarkHex != markHex {
items[idx].MarkHex = markHex
changed = true
}
}
for _, idx := range missingPref {
p := nextTransportPref(usedPrefs)
usedPrefs[p] = struct{}{}
if items[idx].PriorityBase != p {
items[idx].PriorityBase = p
changed = true
}
}
return items, changed
}