-
Notifications
You must be signed in to change notification settings - Fork 22
/
free_hours_manager.go
189 lines (160 loc) · 3.73 KB
/
free_hours_manager.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package utils
import (
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
"github.com/TeaOSLab/EdgeNode/internal/events"
"github.com/TeaOSLab/EdgeNode/internal/goman"
"sort"
"sync"
"sync/atomic"
"time"
)
var SharedFreeHoursManager = NewFreeHoursManager()
func init() {
if !teaconst.IsMain {
return
}
events.On(events.EventLoaded, func() {
goman.New(func() {
SharedFreeHoursManager.Start()
})
})
events.On(events.EventQuit, func() {
SharedFreeHoursManager.Stop()
})
}
// FreeHoursManager 计算节点空闲时间
// 以便于我们在空闲时间执行高强度的任务,如清理缓存等
type FreeHoursManager struct {
dayTrafficMap map[int][24]uint64 // day => [ traffic bytes ]
lastBytes uint64
freeHours []int
count int
locker sync.Mutex
ticker *time.Ticker
}
func NewFreeHoursManager() *FreeHoursManager {
return &FreeHoursManager{dayTrafficMap: map[int][24]uint64{}, count: 3}
}
func (this *FreeHoursManager) Start() {
this.ticker = time.NewTicker(30 * time.Minute)
for range this.ticker.C {
this.Update(atomic.LoadUint64(&teaconst.InTrafficBytes))
}
}
func (this *FreeHoursManager) Update(bytes uint64) {
if this.count <= 0 {
this.count = 3
}
if this.lastBytes == 0 {
this.lastBytes = bytes
} else {
// 记录流量
var deltaBytes = bytes - this.lastBytes
var now = time.Now()
var day = now.Day()
var hour = now.Hour()
traffic, ok := this.dayTrafficMap[day]
if ok {
traffic[hour] += deltaBytes
} else {
var traffic = [24]uint64{}
traffic[hour] += deltaBytes
this.dayTrafficMap[day] = traffic
}
this.lastBytes = bytes
// 计算空闲时间
var result = [24]uint64{}
var hasData = false
for trafficDay, trafficArray := range this.dayTrafficMap {
// 当天的不算
if trafficDay == day {
continue
}
// 查看最近5天的
if (day > trafficDay && day-trafficDay <= 5) || (day < trafficDay && trafficDay-day >= 26) {
var weights = this.sortUintArrayWeights(trafficArray)
for k, v := range weights {
result[k] += v
}
hasData = true
}
}
if hasData {
var freeHours = this.sortUintArrayIndexes(result)
this.locker.Lock()
this.freeHours = freeHours[:this.count] // 取前N个小时作为空闲时间
this.locker.Unlock()
}
}
}
func (this *FreeHoursManager) IsFreeHour() bool {
this.locker.Lock()
defer this.locker.Unlock()
if len(this.freeHours) == 0 {
return false
}
var hour = time.Now().Hour()
for _, h := range this.freeHours {
if h == hour {
return true
}
}
return false
}
func (this *FreeHoursManager) Stop() {
if this.ticker != nil {
this.ticker.Stop()
}
}
// 对数组进行排序,并返回权重
func (this *FreeHoursManager) sortUintArrayWeights(arr [24]uint64) [24]uint64 {
var l = []map[string]interface{}{}
for k, v := range arr {
l = append(l, map[string]interface{}{
"k": k,
"v": v,
})
}
sort.Slice(l, func(i, j int) bool {
var m1 = l[i]
var v1 = m1["v"].(uint64)
var m2 = l[j]
var v2 = m2["v"].(uint64)
return v1 < v2
})
var result = [24]uint64{}
for k, v := range l {
if k < this.count {
k = 0
} else {
k = 1
}
result[v["k"].(int)] = v["v"].(uint64)
}
return result
}
// 对数组进行排序,并返回索引
func (this *FreeHoursManager) sortUintArrayIndexes(arr [24]uint64) [24]int {
var l = []map[string]interface{}{}
for k, v := range arr {
l = append(l, map[string]interface{}{
"k": k,
"v": v,
})
}
sort.Slice(l, func(i, j int) bool {
var m1 = l[i]
var v1 = m1["v"].(uint64)
var m2 = l[j]
var v2 = m2["v"].(uint64)
return v1 < v2
})
var result = [24]int{}
var i = 0
for _, v := range l {
result[i] = v["k"].(int)
i++
}
return result
}