From bb6300b0324fc1365b2c9afce7399b8ea6b20224 Mon Sep 17 00:00:00 2001 From: cbruegg Date: Thu, 17 Aug 2017 17:40:43 +0200 Subject: [PATCH] Fix bwlimit toggle in conjunction with schedules (Fixes #1607) --- fs/accounting.go | 40 ++++++++++++++++++++++++++++------------ fs/accounting_unix.go | 1 + 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/fs/accounting.go b/fs/accounting.go index c25ec46d6..b779382ca 100644 --- a/fs/accounting.go +++ b/fs/accounting.go @@ -18,25 +18,26 @@ import ( // Globals var ( - Stats = NewStats() - tokenBucketMu sync.Mutex // protects the token bucket variables - tokenBucket *rate.Limiter - prevTokenBucket = tokenBucket - currLimitMu sync.Mutex // protects changes to the timeslot - currLimit BwTimeSlot + Stats = NewStats() + tokenBucketMu sync.Mutex // protects the token bucket variables + tokenBucket *rate.Limiter + prevTokenBucket = tokenBucket + bwLimitToggledOff = false + currLimitMu sync.Mutex // protects changes to the timeslot + currLimit BwTimeSlot ) const maxBurstSize = 1 * 1024 * 1024 // must be bigger than the biggest request // make a new empty token bucket with the bandwidth given func newTokenBucket(bandwidth SizeSuffix) *rate.Limiter { - tokenBucket = rate.NewLimiter(rate.Limit(bandwidth), maxBurstSize) + newTokenBucket := rate.NewLimiter(rate.Limit(bandwidth), maxBurstSize) // empty the bucket - err := tokenBucket.WaitN(context.Background(), maxBurstSize) + err := newTokenBucket.WaitN(context.Background(), maxBurstSize) if err != nil { Errorf(nil, "Failed to empty token bucket: %v", err) } - return tokenBucket + return newTokenBucket } // Start the token bucket if necessary @@ -72,12 +73,27 @@ func startTokenTicker() { if currLimit.bandwidth != limitNow.bandwidth { 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. if limitNow.bandwidth > 0 { - tokenBucket = newTokenBucket(limitNow.bandwidth) - Logf(nil, "Scheduled bandwidth change. Limit set to %vBytes/s", &limitNow.bandwidth) + *targetBucket = newTokenBucket(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 { - tokenBucket = nil + *targetBucket = nil Logf(nil, "Scheduled bandwidth change. Bandwidth limits disabled") } diff --git a/fs/accounting_unix.go b/fs/accounting_unix.go index 24ffa955b..5ca04b3ac 100644 --- a/fs/accounting_unix.go +++ b/fs/accounting_unix.go @@ -21,6 +21,7 @@ func startSignalHandler() { for { <-signals tokenBucketMu.Lock() + bwLimitToggledOff = !bwLimitToggledOff tokenBucket, prevTokenBucket = prevTokenBucket, tokenBucket s := "disabled" if tokenBucket != nil {