Merge pull request #963 from AtakanColak/simpler-virt-cache

Simplify Fix Virtualization Cache Race Condition
pull/972/head
Lomanic 5 years ago committed by GitHub
commit 34fbc94ac1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -111,49 +111,24 @@ func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background()) return VirtualizationWithContext(context.Background())
} }
type virtCache struct { // required variables for concurrency safe virtualization caching
cache map[string]string
lock sync.Mutex
ok bool
}
func (v *virtCache) setValue(system, role string) {
v.lock.Lock()
defer v.lock.Unlock()
v.cache["system"] = system
v.cache["role"] = role
v.ok = true
}
func (v *virtCache) getValue() (string, string, bool) {
v.lock.Lock()
defer v.lock.Unlock()
return v.cache["system"], v.cache["role"], v.ok
}
var ( var (
once sync.Once cachedVirtMap map[string]string
virtualization *virtCache cachedVirtMutex sync.RWMutex
cachedVirtOnce sync.Once
) )
func virtualizationCache() *virtCache {
once.Do(func() {
virtualization = &virtCache{
cache: make(map[string]string),
lock: sync.Mutex{},
ok: false,
}
})
return virtualization
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) { func VirtualizationWithContext(ctx context.Context) (string, string, error) {
var system, role string
// if cached already, return from cache // if cached already, return from cache
system, role, ok := virtualizationCache().getValue() cachedVirtMutex.RLock() // unlock won't be deferred so concurrent reads don't wait for long
if ok { if cachedVirtMap != nil {
return system, role, nil cachedSystem, cachedRole := cachedVirtMap["system"], cachedVirtMap["role"]
cachedVirtMutex.RUnlock()
return cachedSystem, cachedRole, nil
} }
cachedVirtMutex.RUnlock()
filename := HostProc("xen") filename := HostProc("xen")
if PathExists(filename) { if PathExists(filename) {
@ -274,7 +249,15 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
// before returning for the first time, cache the system and role // before returning for the first time, cache the system and role
virtualizationCache().setValue(system, role) cachedVirtOnce.Do(func() {
cachedVirtMutex.Lock()
defer cachedVirtMutex.Unlock()
cachedVirtMap = map[string]string{
"system": system,
"role": role,
}
})
return system, role, nil return system, role, nil
} }

Loading…
Cancel
Save