Fix bwlimit toggle in conjunction with schedules (Fixes #1607)

This commit is contained in:
cbruegg 2017-08-17 17:40:43 +02:00 committed by Nick Craig-Wood
parent e96c5b5f39
commit bb6300b032
2 changed files with 29 additions and 12 deletions

View file

@ -18,25 +18,26 @@ import (
// Globals // Globals
var ( var (
Stats = NewStats() Stats = NewStats()
tokenBucketMu sync.Mutex // protects the token bucket variables tokenBucketMu sync.Mutex // protects the token bucket variables
tokenBucket *rate.Limiter tokenBucket *rate.Limiter
prevTokenBucket = tokenBucket prevTokenBucket = tokenBucket
currLimitMu sync.Mutex // protects changes to the timeslot bwLimitToggledOff = false
currLimit BwTimeSlot currLimitMu sync.Mutex // protects changes to the timeslot
currLimit BwTimeSlot
) )
const maxBurstSize = 1 * 1024 * 1024 // must be bigger than the biggest request const maxBurstSize = 1 * 1024 * 1024 // must be bigger than the biggest request
// make a new empty token bucket with the bandwidth given // make a new empty token bucket with the bandwidth given
func newTokenBucket(bandwidth SizeSuffix) *rate.Limiter { func newTokenBucket(bandwidth SizeSuffix) *rate.Limiter {
tokenBucket = rate.NewLimiter(rate.Limit(bandwidth), maxBurstSize) newTokenBucket := rate.NewLimiter(rate.Limit(bandwidth), maxBurstSize)
// empty the bucket // empty the bucket
err := tokenBucket.WaitN(context.Background(), maxBurstSize) err := newTokenBucket.WaitN(context.Background(), maxBurstSize)
if err != nil { if err != nil {
Errorf(nil, "Failed to empty token bucket: %v", err) Errorf(nil, "Failed to empty token bucket: %v", err)
} }
return tokenBucket return newTokenBucket
} }
// Start the token bucket if necessary // Start the token bucket if necessary
@ -72,12 +73,27 @@ func startTokenTicker() {
if currLimit.bandwidth != limitNow.bandwidth { if currLimit.bandwidth != limitNow.bandwidth {
tokenBucketMu.Lock() tokenBucketMu.Lock()
// If bwlimit is toggled off, the change should only
// become active on the next toggle, which causes
// an exchange of tokenBucket <-> prevTokenBucket
var targetBucket **rate.Limiter
if bwLimitToggledOff {
targetBucket = &prevTokenBucket
} else {
targetBucket = &tokenBucket
}
// Set new bandwidth. If unlimited, set tokenbucket to nil. // Set new bandwidth. If unlimited, set tokenbucket to nil.
if limitNow.bandwidth > 0 { if limitNow.bandwidth > 0 {
tokenBucket = newTokenBucket(limitNow.bandwidth) *targetBucket = newTokenBucket(limitNow.bandwidth)
Logf(nil, "Scheduled bandwidth change. Limit set to %vBytes/s", &limitNow.bandwidth) if bwLimitToggledOff {
Logf(nil, "Scheduled bandwidth change. " +
"Limit will be set to %vBytes/s when toggled on again.", &limitNow.bandwidth)
} else {
Logf(nil, "Scheduled bandwidth change. Limit set to %vBytes/s", &limitNow.bandwidth)
}
} else { } else {
tokenBucket = nil *targetBucket = nil
Logf(nil, "Scheduled bandwidth change. Bandwidth limits disabled") Logf(nil, "Scheduled bandwidth change. Bandwidth limits disabled")
} }

View file

@ -21,6 +21,7 @@ func startSignalHandler() {
for { for {
<-signals <-signals
tokenBucketMu.Lock() tokenBucketMu.Lock()
bwLimitToggledOff = !bwLimitToggledOff
tokenBucket, prevTokenBucket = prevTokenBucket, tokenBucket tokenBucket, prevTokenBucket = prevTokenBucket, tokenBucket
s := "disabled" s := "disabled"
if tokenBucket != nil { if tokenBucket != nil {