1 /* 2 Copyright 2014 The Kubernetes Authors. 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 volume 18 19 import ( 20 "sync" 21 "sync/atomic" 22 ) 23 24 var _ MetricsProvider = &cachedMetrics{} 25 26 // cachedMetrics represents a MetricsProvider that wraps another provider and 27 // caches the result. 28 type cachedMetrics struct { 29 wrapped MetricsProvider 30 resultError error 31 resultMetrics *Metrics 32 once cacheOnce 33 } 34 35 // NewCachedMetrics creates a new cachedMetrics wrapping another 36 // MetricsProvider and caching the results. 37 func NewCachedMetrics(provider MetricsProvider) MetricsProvider { 38 return &cachedMetrics{wrapped: provider} 39 } 40 41 // GetMetrics runs the wrapped metrics provider's GetMetrics method once and 42 // caches the result. Will not cache result if there is an error. 43 // See MetricsProvider.GetMetrics 44 func (md *cachedMetrics) GetMetrics() (*Metrics, error) { 45 md.once.cache(func() error { 46 md.resultMetrics, md.resultError = md.wrapped.GetMetrics() 47 return md.resultError 48 }) 49 return md.resultMetrics, md.resultError 50 } 51 52 // Copied from sync.Once but we don't want to cache the results if there is an 53 // error 54 type cacheOnce struct { 55 m sync.Mutex 56 done uint32 57 } 58 59 // Copied from sync.Once but we don't want to cache the results if there is an 60 // error 61 func (o *cacheOnce) cache(f func() error) { 62 if atomic.LoadUint32(&o.done) == 1 { 63 return 64 } 65 // Slow-path. 66 o.m.Lock() 67 defer o.m.Unlock() 68 if o.done == 0 { 69 err := f() 70 if err == nil { 71 atomic.StoreUint32(&o.done, 1) 72 } 73 } 74 } 75