github.com/doitroot/helm@v3.0.0-beta.3+incompatible/pkg/storage/driver/memory.go (about) 1 /* 2 Copyright The Helm 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 driver 18 19 import ( 20 "strconv" 21 "strings" 22 "sync" 23 24 rspb "helm.sh/helm/pkg/release" 25 ) 26 27 var _ Driver = (*Memory)(nil) 28 29 // MemoryDriverName is the string name of this driver. 30 const MemoryDriverName = "Memory" 31 32 // Memory is the in-memory storage driver implementation. 33 type Memory struct { 34 sync.RWMutex 35 cache map[string]records 36 } 37 38 // NewMemory initializes a new memory driver. 39 func NewMemory() *Memory { 40 return &Memory{cache: map[string]records{}} 41 } 42 43 // Name returns the name of the driver. 44 func (mem *Memory) Name() string { 45 return MemoryDriverName 46 } 47 48 // Get returns the release named by key or returns ErrReleaseNotFound. 49 func (mem *Memory) Get(key string) (*rspb.Release, error) { 50 defer unlock(mem.rlock()) 51 52 switch elems := strings.Split(key, ".v"); len(elems) { 53 case 2: 54 name, ver := elems[0], elems[1] 55 if _, err := strconv.Atoi(ver); err != nil { 56 return nil, ErrInvalidKey 57 } 58 if recs, ok := mem.cache[name]; ok { 59 if r := recs.Get(key); r != nil { 60 return r.rls, nil 61 } 62 } 63 return nil, ErrReleaseNotFound 64 default: 65 return nil, ErrInvalidKey 66 } 67 } 68 69 // List returns the list of all releases such that filter(release) == true 70 func (mem *Memory) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error) { 71 defer unlock(mem.rlock()) 72 73 var ls []*rspb.Release 74 for _, recs := range mem.cache { 75 recs.Iter(func(_ int, rec *record) bool { 76 if filter(rec.rls) { 77 ls = append(ls, rec.rls) 78 } 79 return true 80 }) 81 } 82 return ls, nil 83 } 84 85 // Query returns the set of releases that match the provided set of labels 86 func (mem *Memory) Query(keyvals map[string]string) ([]*rspb.Release, error) { 87 defer unlock(mem.rlock()) 88 89 var lbs labels 90 91 lbs.init() 92 lbs.fromMap(keyvals) 93 94 var ls []*rspb.Release 95 for _, recs := range mem.cache { 96 recs.Iter(func(_ int, rec *record) bool { 97 // A query for a release name that doesn't exist (has been deleted) 98 // can cause rec to be nil. 99 if rec == nil { 100 return false 101 } 102 if rec.lbs.match(lbs) { 103 ls = append(ls, rec.rls) 104 } 105 return true 106 }) 107 } 108 return ls, nil 109 } 110 111 // Create creates a new release or returns ErrReleaseExists. 112 func (mem *Memory) Create(key string, rls *rspb.Release) error { 113 defer unlock(mem.wlock()) 114 115 if recs, ok := mem.cache[rls.Name]; ok { 116 if err := recs.Add(newRecord(key, rls)); err != nil { 117 return err 118 } 119 mem.cache[rls.Name] = recs 120 return nil 121 } 122 mem.cache[rls.Name] = records{newRecord(key, rls)} 123 return nil 124 } 125 126 // Update updates a release or returns ErrReleaseNotFound. 127 func (mem *Memory) Update(key string, rls *rspb.Release) error { 128 defer unlock(mem.wlock()) 129 130 if rs, ok := mem.cache[rls.Name]; ok && rs.Exists(key) { 131 rs.Replace(key, newRecord(key, rls)) 132 return nil 133 } 134 return ErrReleaseNotFound 135 } 136 137 // Delete deletes a release or returns ErrReleaseNotFound. 138 func (mem *Memory) Delete(key string) (*rspb.Release, error) { 139 defer unlock(mem.wlock()) 140 141 elems := strings.Split(key, ".v") 142 143 if len(elems) != 2 { 144 return nil, ErrInvalidKey 145 } 146 147 name, ver := elems[0], elems[1] 148 if _, err := strconv.Atoi(ver); err != nil { 149 return nil, ErrInvalidKey 150 } 151 if recs, ok := mem.cache[name]; ok { 152 if r := recs.Remove(key); r != nil { 153 // recs.Remove changes the slice reference, so we have to re-assign it. 154 mem.cache[name] = recs 155 return r.rls, nil 156 } 157 } 158 return nil, ErrReleaseNotFound 159 } 160 161 // wlock locks mem for writing 162 func (mem *Memory) wlock() func() { 163 mem.Lock() 164 return func() { mem.Unlock() } 165 } 166 167 // rlock locks mem for reading 168 func (mem *Memory) rlock() func() { 169 mem.RLock() 170 return func() { mem.RUnlock() } 171 } 172 173 // unlock calls fn which reverses a mem.rlock or mem.wlock. e.g: 174 // ```defer unlock(mem.rlock())```, locks mem for reading at the 175 // call point of defer and unlocks upon exiting the block. 176 func unlock(fn func()) { fn() }