agones.dev/agones@v1.54.0/pkg/gameserverallocations/cache.go (about) 1 // Copyright 2019 Google LLC All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package gameserverallocations 16 17 import ( 18 "sync" 19 20 agonesv1 "agones.dev/agones/pkg/apis/agones/v1" 21 ) 22 23 // gameserver cache to keep the Ready state gameserver. 24 // 25 //nolint:govet // ignore fieldalignment, singleton embedded in AllocationCache 26 type gameServerCache struct { 27 mu sync.RWMutex 28 cache map[string]*agonesv1.GameServer 29 } 30 31 // Store saves the data in the cache. 32 // If there is already a value for this key, the incoming gs object is ignored 33 // if its Generation metadata is less than the existing one, or if its Generation 34 // is equal and its ResourceVersion is the same as the existing one. 35 // Otherwise, the incoming gs object replaces the existing one. 36 func (e *gameServerCache) Store(key string, gs *agonesv1.GameServer) { 37 e.mu.Lock() 38 defer e.mu.Unlock() 39 if e.cache == nil { 40 e.cache = map[string]*agonesv1.GameServer{} 41 } 42 43 // Check if there's already a value for this key 44 if existingGS, ok := e.cache[key]; ok { 45 // If the incoming gs object's Generation is less than the existing one, ignore it, but also check the ResourceVersion 46 // saves us a deep copy if we don't need to 47 if gs.ObjectMeta.Generation < existingGS.ObjectMeta.Generation || gs.ObjectMeta.ResourceVersion == existingGS.ObjectMeta.ResourceVersion { 48 return 49 } 50 } 51 // If the incoming gs object's Generation is greater, store it 52 e.cache[key] = gs.DeepCopy() 53 } 54 55 // Delete deletes the data. If it exists returns true. 56 func (e *gameServerCache) Delete(key string) bool { 57 e.mu.Lock() 58 defer e.mu.Unlock() 59 ret := false 60 if e.cache != nil { 61 if _, ok := e.cache[key]; ok { 62 delete(e.cache, key) 63 ret = true 64 } 65 } 66 67 return ret 68 } 69 70 // Load returns the data from cache. It return true if the value exists in the cache 71 func (e *gameServerCache) Load(key string) (*agonesv1.GameServer, bool) { 72 e.mu.RLock() 73 defer e.mu.RUnlock() 74 val, ok := e.cache[key] 75 76 return val, ok 77 } 78 79 // Range extracts data from the cache based on provided function f. 80 func (e *gameServerCache) Range(f func(key string, gs *agonesv1.GameServer) bool) { 81 e.mu.RLock() 82 defer e.mu.RUnlock() 83 for k, v := range e.cache { 84 if !f(k, v) { 85 break 86 } 87 } 88 } 89 90 // Len returns the current length of the cache 91 func (e *gameServerCache) Len() int { 92 e.mu.RLock() 93 defer e.mu.RUnlock() 94 return len(e.cache) 95 }