-
Notifications
You must be signed in to change notification settings - Fork 39
/
ranked_storage_account_set.go
104 lines (85 loc) · 2.48 KB
/
ranked_storage_account_set.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package resources
import (
"math/rand"
"sync"
"time"
)
const (
defaultNumberOfBuckets = 6
defaultBucketDurationInSeconds = 10
)
var defaultTiersValue = [4]int{90, 70, 30, 0}
var defaultTimeProvider = func() int64 { return time.Now().Unix() }
type RankedStorageAccountSet struct {
accounts map[string]*RankedStorageAccount
numberOfBuckets int
bucketDuration int64
tiers []int
timeProvider func() int64
lock sync.Mutex
}
func newRankedStorageAccountSet(
numberOfBuckets int,
bucketDuration int64,
tiers []int,
timeProvider func() int64,
) *RankedStorageAccountSet {
return &RankedStorageAccountSet{
accounts: make(map[string]*RankedStorageAccount),
numberOfBuckets: numberOfBuckets,
bucketDuration: bucketDuration,
tiers: tiers,
timeProvider: timeProvider,
lock: sync.Mutex{},
}
}
func newDefaultRankedStorageAccountSet() *RankedStorageAccountSet {
return newRankedStorageAccountSet(defaultNumberOfBuckets, defaultBucketDurationInSeconds, defaultTiersValue[:], defaultTimeProvider)
}
func (r *RankedStorageAccountSet) addAccountResult(accountName string, success bool) {
r.lock.Lock()
defer r.lock.Unlock()
account, ok := r.accounts[accountName]
if ok {
account.logResult(success)
}
}
func (r *RankedStorageAccountSet) registerStorageAccount(accountName string) {
r.lock.Lock()
defer r.lock.Unlock()
if _, ok := r.accounts[accountName]; !ok {
r.accounts[accountName] = newRankedStorageAccount(accountName, r.numberOfBuckets, r.bucketDuration, r.timeProvider)
}
}
func (r *RankedStorageAccountSet) getStorageAccount(accountName string) (*RankedStorageAccount, bool) {
r.lock.Lock()
defer r.lock.Unlock()
account, ok := r.accounts[accountName]
return account, ok
}
func (r *RankedStorageAccountSet) getRankedShuffledAccounts() []RankedStorageAccount {
r.lock.Lock()
defer r.lock.Unlock()
accountsByTier := make([][]RankedStorageAccount, len(r.tiers))
for i := range accountsByTier {
accountsByTier[i] = []RankedStorageAccount{}
}
for _, account := range r.accounts {
rankPercentage := int(account.getRank() * 100.0)
for i := range r.tiers {
if rankPercentage >= r.tiers[i] {
accountsByTier[i] = append(accountsByTier[i], *account)
break
}
}
}
var result []RankedStorageAccount
for _, tier := range accountsByTier {
rand.Shuffle(len(tier), func(i, j int) {
tier[i], tier[j] = tier[j], tier[i]
})
//Apend to results
result = append(result, tier...)
}
return result
}