github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/wait/wait.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package wait 18 19 import ( 20 "errors" 21 "math/rand" 22 "time" 23 24 "k8s.io/kubernetes/pkg/util/runtime" 25 ) 26 27 // For any test of the style: 28 // ... 29 // <- time.After(timeout): 30 // t.Errorf("Timed out") 31 // The value for timeout should effectively be "forever." Obviously we don't want our tests to truly lock up forever, but 30s 32 // is long enough that it is effectively forever for the things that can slow down a run on a heavily contended machine 33 // (GC, seeks, etc), but not so long as to make a developer ctrl-c a test run if they do happen to break that test. 34 var ForeverTestTimeout = time.Second * 30 35 36 // NeverStop may be passed to Until to make it never stop. 37 var NeverStop <-chan struct{} = make(chan struct{}) 38 39 // Forever is syntactic sugar on top of Until 40 func Forever(f func(), period time.Duration) { 41 Until(f, period, NeverStop) 42 } 43 44 // Until loops until stop channel is closed, running f every period. 45 // Until is syntactic sugar on top of JitterUntil with zero jitter factor 46 func Until(f func(), period time.Duration, stopCh <-chan struct{}) { 47 JitterUntil(f, period, 0.0, stopCh) 48 } 49 50 // JitterUntil loops until stop channel is closed, running f every period. 51 // If jitterFactor is positive, the period is jittered before every run of f. 52 // If jitterFactor is not positive, the period is unchanged. 53 // Catches any panics, and keeps going. f may not be invoked if 54 // stop channel is already closed. Pass NeverStop to Until if you 55 // don't want it stop. 56 func JitterUntil(f func(), period time.Duration, jitterFactor float64, stopCh <-chan struct{}) { 57 select { 58 case <-stopCh: 59 return 60 default: 61 } 62 63 for { 64 func() { 65 defer runtime.HandleCrash() 66 f() 67 }() 68 69 jitteredPeriod := period 70 if jitterFactor > 0.0 { 71 jitteredPeriod = Jitter(period, jitterFactor) 72 } 73 74 select { 75 case <-stopCh: 76 return 77 case <-time.After(jitteredPeriod): 78 } 79 } 80 } 81 82 // Jitter returns a time.Duration between duration and duration + maxFactor * duration, 83 // to allow clients to avoid converging on periodic behavior. If maxFactor is 0.0, a 84 // suggested default value will be chosen. 85 func Jitter(duration time.Duration, maxFactor float64) time.Duration { 86 if maxFactor <= 0.0 { 87 maxFactor = 1.0 88 } 89 wait := duration + time.Duration(rand.Float64()*maxFactor*float64(duration)) 90 return wait 91 } 92 93 // ErrWaitTimeout is returned when the condition exited without success 94 var ErrWaitTimeout = errors.New("timed out waiting for the condition") 95 96 // ConditionFunc returns true if the condition is satisfied, or an error 97 // if the loop should be aborted. 98 type ConditionFunc func() (done bool, err error) 99 100 // Backoff is parameters applied to a Backoff function. 101 type Backoff struct { 102 Duration time.Duration 103 Factor float64 104 Jitter float64 105 Steps int 106 } 107 108 // ExponentialBackoff repeats a condition check up to steps times, increasing the wait 109 // by multipling the previous duration by factor. If jitter is greater than zero, 110 // a random amount of each duration is added (between duration and duration*(1+jitter)). 111 // If the condition never returns true, ErrWaitTimeout is returned. All other errors 112 // terminate immediately. 113 func ExponentialBackoff(backoff Backoff, condition ConditionFunc) error { 114 duration := backoff.Duration 115 for i := 0; i < backoff.Steps; i++ { 116 if i != 0 { 117 adjusted := duration 118 if backoff.Jitter > 0.0 { 119 adjusted = Jitter(duration, backoff.Jitter) 120 } 121 time.Sleep(adjusted) 122 duration = time.Duration(float64(duration) * backoff.Factor) 123 } 124 if ok, err := condition(); err != nil || ok { 125 return err 126 } 127 } 128 return ErrWaitTimeout 129 } 130 131 // Poll tries a condition func until it returns true, an error, or the timeout 132 // is reached. condition will always be invoked at least once but some intervals 133 // may be missed if the condition takes too long or the time window is too short. 134 // If you want to Poll something forever, see PollInfinite. 135 // Poll always waits the interval before the first check of the condition. 136 func Poll(interval, timeout time.Duration, condition ConditionFunc) error { 137 return pollInternal(poller(interval, timeout), condition) 138 } 139 140 func pollInternal(wait WaitFunc, condition ConditionFunc) error { 141 done := make(chan struct{}) 142 defer close(done) 143 return WaitFor(wait, condition, done) 144 } 145 146 // PollImmediate is identical to Poll, except that it performs the first check 147 // immediately, not waiting interval beforehand. 148 func PollImmediate(interval, timeout time.Duration, condition ConditionFunc) error { 149 return pollImmediateInternal(poller(interval, timeout), condition) 150 } 151 152 func pollImmediateInternal(wait WaitFunc, condition ConditionFunc) error { 153 done, err := condition() 154 if err != nil { 155 return err 156 } 157 if done { 158 return nil 159 } 160 return pollInternal(wait, condition) 161 } 162 163 // PollInfinite polls forever. 164 func PollInfinite(interval time.Duration, condition ConditionFunc) error { 165 done := make(chan struct{}) 166 defer close(done) 167 return WaitFor(poller(interval, 0), condition, done) 168 } 169 170 // WaitFunc creates a channel that receives an item every time a test 171 // should be executed and is closed when the last test should be invoked. 172 type WaitFunc func(done <-chan struct{}) <-chan struct{} 173 174 // WaitFor gets a channel from wait(), and then invokes fn once for every value 175 // placed on the channel and once more when the channel is closed. If fn 176 // returns an error the loop ends and that error is returned, and if fn returns 177 // true the loop ends and nil is returned. ErrWaitTimeout will be returned if 178 // the channel is closed without fn ever returning true. 179 func WaitFor(wait WaitFunc, fn ConditionFunc, done <-chan struct{}) error { 180 c := wait(done) 181 for { 182 _, open := <-c 183 ok, err := fn() 184 if err != nil { 185 return err 186 } 187 if ok { 188 return nil 189 } 190 if !open { 191 break 192 } 193 } 194 return ErrWaitTimeout 195 } 196 197 // poller returns a WaitFunc that will send to the channel every 198 // interval until timeout has elapsed and then close the channel. 199 // Over very short intervals you may receive no ticks before 200 // the channel is closed. If timeout is 0, the channel 201 // will never be closed. 202 func poller(interval, timeout time.Duration) WaitFunc { 203 return WaitFunc(func(done <-chan struct{}) <-chan struct{} { 204 ch := make(chan struct{}) 205 206 go func() { 207 defer close(ch) 208 209 tick := time.NewTicker(interval) 210 defer tick.Stop() 211 212 var after <-chan time.Time 213 if timeout != 0 { 214 // time.After is more convenient, but it 215 // potentially leaves timers around much longer 216 // than necessary if we exit early. 217 timer := time.NewTimer(timeout) 218 after = timer.C 219 defer timer.Stop() 220 } 221 222 for { 223 select { 224 case <-tick.C: 225 // If the consumer isn't ready for this signal drop it and 226 // check the other channels. 227 select { 228 case ch <- struct{}{}: 229 default: 230 } 231 case <-after: 232 return 233 case <-done: 234 return 235 } 236 } 237 }() 238 239 return ch 240 }) 241 }