github.com/google/cadvisor@v0.49.1/cache/memory/memory.go (about) 1 // Copyright 2014 Google Inc. 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 memory 16 17 import ( 18 "errors" 19 "sync" 20 "time" 21 22 info "github.com/google/cadvisor/info/v1" 23 "github.com/google/cadvisor/storage" 24 "github.com/google/cadvisor/utils" 25 26 "k8s.io/klog/v2" 27 ) 28 29 // ErrDataNotFound is the error resulting if failed to find a container in memory cache. 30 var ErrDataNotFound = errors.New("unable to find data in memory cache") 31 32 // TODO(vmarmol): See about refactoring this class, we have an unnecessary redirection of containerCache and InMemoryCache. 33 // containerCache is used to store per-container information 34 type containerCache struct { 35 ref info.ContainerReference 36 recentStats *utils.TimedStore 37 maxAge time.Duration 38 lock sync.RWMutex 39 } 40 41 func (c *containerCache) AddStats(stats *info.ContainerStats) error { 42 c.lock.Lock() 43 defer c.lock.Unlock() 44 45 // Add the stat to storage. 46 c.recentStats.Add(stats.Timestamp, stats) 47 return nil 48 } 49 50 func (c *containerCache) RecentStats(start, end time.Time, maxStats int) ([]*info.ContainerStats, error) { 51 c.lock.RLock() 52 defer c.lock.RUnlock() 53 result := c.recentStats.InTimeRange(start, end, maxStats) 54 converted := make([]*info.ContainerStats, len(result)) 55 for i, el := range result { 56 converted[i] = el.(*info.ContainerStats) 57 } 58 return converted, nil 59 } 60 61 func newContainerStore(ref info.ContainerReference, maxAge time.Duration) *containerCache { 62 return &containerCache{ 63 ref: ref, 64 recentStats: utils.NewTimedStore(maxAge, -1), 65 maxAge: maxAge, 66 } 67 } 68 69 type InMemoryCache struct { 70 lock sync.RWMutex 71 containerCacheMap map[string]*containerCache 72 maxAge time.Duration 73 backend []storage.StorageDriver 74 } 75 76 func (c *InMemoryCache) AddStats(cInfo *info.ContainerInfo, stats *info.ContainerStats) error { 77 var cstore *containerCache 78 var ok bool 79 80 func() { 81 c.lock.Lock() 82 defer c.lock.Unlock() 83 if cstore, ok = c.containerCacheMap[cInfo.ContainerReference.Name]; !ok { 84 cstore = newContainerStore(cInfo.ContainerReference, c.maxAge) 85 c.containerCacheMap[cInfo.ContainerReference.Name] = cstore 86 } 87 }() 88 89 for _, backend := range c.backend { 90 // TODO(monnand): To deal with long delay write operations, we 91 // may want to start a pool of goroutines to do write 92 // operations. 93 if err := backend.AddStats(cInfo, stats); err != nil { 94 klog.Error(err) 95 } 96 } 97 return cstore.AddStats(stats) 98 } 99 100 func (c *InMemoryCache) RecentStats(name string, start, end time.Time, maxStats int) ([]*info.ContainerStats, error) { 101 var cstore *containerCache 102 var ok bool 103 err := func() error { 104 c.lock.RLock() 105 defer c.lock.RUnlock() 106 if cstore, ok = c.containerCacheMap[name]; !ok { 107 return ErrDataNotFound 108 } 109 return nil 110 }() 111 if err != nil { 112 return nil, err 113 } 114 115 return cstore.RecentStats(start, end, maxStats) 116 } 117 118 func (c *InMemoryCache) Close() error { 119 c.lock.Lock() 120 c.containerCacheMap = make(map[string]*containerCache, 32) 121 c.lock.Unlock() 122 return nil 123 } 124 125 func (c *InMemoryCache) RemoveContainer(containerName string) error { 126 c.lock.Lock() 127 delete(c.containerCacheMap, containerName) 128 c.lock.Unlock() 129 return nil 130 } 131 132 func New( 133 maxAge time.Duration, 134 backend []storage.StorageDriver, 135 ) *InMemoryCache { 136 ret := &InMemoryCache{ 137 containerCacheMap: make(map[string]*containerCache, 32), 138 maxAge: maxAge, 139 backend: backend, 140 } 141 return ret 142 }