github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/asserts/membackstore.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2020 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package asserts 21 22 import ( 23 "errors" 24 "fmt" 25 "sort" 26 "strconv" 27 "sync" 28 ) 29 30 type memoryBackstore struct { 31 top memBSBranch 32 mu sync.RWMutex 33 } 34 35 type memBSNode interface { 36 put(assertType *AssertionType, key []string, assert Assertion) error 37 get(key []string, maxFormat int) (Assertion, error) 38 search(hint []string, found func(Assertion), maxFormat int) 39 sequenceMemberAfter(prefix []string, after, maxFormat int) (Assertion, error) 40 } 41 42 type memBSBranch map[string]memBSNode 43 44 type memBSLeaf map[string]map[int]Assertion 45 46 type memBSSeqLeaf struct { 47 memBSLeaf 48 sequence []int 49 } 50 51 func (br memBSBranch) put(assertType *AssertionType, key []string, assert Assertion) error { 52 key0 := key[0] 53 down := br[key0] 54 if down == nil { 55 if len(key) > 2 { 56 down = make(memBSBranch) 57 } else { 58 leaf := make(memBSLeaf) 59 if assertType.SequenceForming() { 60 down = &memBSSeqLeaf{memBSLeaf: leaf} 61 } else { 62 down = leaf 63 } 64 } 65 br[key0] = down 66 } 67 return down.put(assertType, key[1:], assert) 68 } 69 70 func (leaf memBSLeaf) cur(key0 string, maxFormat int) (a Assertion) { 71 for formatnum, a1 := range leaf[key0] { 72 if formatnum <= maxFormat { 73 if a == nil || a1.Revision() > a.Revision() { 74 a = a1 75 } 76 } 77 } 78 return a 79 } 80 81 func (leaf memBSLeaf) put(assertType *AssertionType, key []string, assert Assertion) error { 82 key0 := key[0] 83 cur := leaf.cur(key0, assertType.MaxSupportedFormat()) 84 if cur != nil { 85 rev := assert.Revision() 86 curRev := cur.Revision() 87 if curRev >= rev { 88 return &RevisionError{Current: curRev, Used: rev} 89 } 90 } 91 if _, ok := leaf[key0]; !ok { 92 leaf[key0] = make(map[int]Assertion) 93 } 94 leaf[key0][assert.Format()] = assert 95 return nil 96 } 97 98 func (leaf *memBSSeqLeaf) put(assertType *AssertionType, key []string, assert Assertion) error { 99 if err := leaf.memBSLeaf.put(assertType, key, assert); err != nil { 100 return err 101 } 102 if len(leaf.memBSLeaf) != len(leaf.sequence) { 103 seqnum := assert.(SequenceMember).Sequence() 104 inspos := sort.SearchInts(leaf.sequence, seqnum) 105 n := len(leaf.sequence) 106 leaf.sequence = append(leaf.sequence, seqnum) 107 if inspos != n { 108 copy(leaf.sequence[inspos+1:n+1], leaf.sequence[inspos:n]) 109 leaf.sequence[inspos] = seqnum 110 } 111 } 112 return nil 113 } 114 115 // errNotFound is used internally by backends, it is converted to the richer 116 // NotFoundError only at their public interface boundary 117 var errNotFound = errors.New("assertion not found") 118 119 func (br memBSBranch) get(key []string, maxFormat int) (Assertion, error) { 120 key0 := key[0] 121 down := br[key0] 122 if down == nil { 123 return nil, errNotFound 124 } 125 return down.get(key[1:], maxFormat) 126 } 127 128 func (leaf memBSLeaf) get(key []string, maxFormat int) (Assertion, error) { 129 key0 := key[0] 130 cur := leaf.cur(key0, maxFormat) 131 if cur == nil { 132 return nil, errNotFound 133 } 134 return cur, nil 135 } 136 137 func (br memBSBranch) search(hint []string, found func(Assertion), maxFormat int) { 138 hint0 := hint[0] 139 if hint0 == "" { 140 for _, down := range br { 141 down.search(hint[1:], found, maxFormat) 142 } 143 return 144 } 145 down := br[hint0] 146 if down != nil { 147 down.search(hint[1:], found, maxFormat) 148 } 149 } 150 151 func (leaf memBSLeaf) search(hint []string, found func(Assertion), maxFormat int) { 152 hint0 := hint[0] 153 if hint0 == "" { 154 for key := range leaf { 155 cand := leaf.cur(key, maxFormat) 156 if cand != nil { 157 found(cand) 158 } 159 } 160 return 161 } 162 163 cur := leaf.cur(hint0, maxFormat) 164 if cur != nil { 165 found(cur) 166 } 167 } 168 169 func (br memBSBranch) sequenceMemberAfter(prefix []string, after, maxFormat int) (Assertion, error) { 170 prefix0 := prefix[0] 171 down := br[prefix0] 172 if down == nil { 173 return nil, errNotFound 174 } 175 return down.sequenceMemberAfter(prefix[1:], after, maxFormat) 176 } 177 178 func (left memBSLeaf) sequenceMemberAfter(prefix []string, after, maxFormat int) (Assertion, error) { 179 panic("internal error: unexpected sequenceMemberAfter on memBSLeaf") 180 } 181 182 func (leaf *memBSSeqLeaf) sequenceMemberAfter(prefix []string, after, maxFormat int) (Assertion, error) { 183 n := len(leaf.sequence) 184 dir := 1 185 var start int 186 if after == -1 { 187 // search for the latest in sequence compatible with 188 // maxFormat: consider all sequence numbers in 189 // sequence backward 190 dir = -1 191 start = n - 1 192 } else { 193 // search for the first in sequence with sequence number 194 // > after and compatible with maxFormat 195 start = sort.SearchInts(leaf.sequence, after) 196 if start == n { 197 // nothing 198 return nil, errNotFound 199 } 200 if leaf.sequence[start] == after { 201 // skip after itself 202 start += 1 203 } 204 } 205 for j := start; j >= 0 && j < n; j += dir { 206 seqkey := strconv.Itoa(leaf.sequence[j]) 207 cur := leaf.cur(seqkey, maxFormat) 208 if cur != nil { 209 return cur, nil 210 } 211 } 212 return nil, errNotFound 213 } 214 215 // NewMemoryBackstore creates a memory backed assertions backstore. 216 func NewMemoryBackstore() Backstore { 217 return &memoryBackstore{ 218 top: make(memBSBranch), 219 } 220 } 221 222 func (mbs *memoryBackstore) Put(assertType *AssertionType, assert Assertion) error { 223 mbs.mu.Lock() 224 defer mbs.mu.Unlock() 225 226 internalKey := make([]string, 1, 1+len(assertType.PrimaryKey)) 227 internalKey[0] = assertType.Name 228 internalKey = append(internalKey, assert.Ref().PrimaryKey...) 229 230 err := mbs.top.put(assertType, internalKey, assert) 231 return err 232 } 233 234 func (mbs *memoryBackstore) Get(assertType *AssertionType, key []string, maxFormat int) (Assertion, error) { 235 mbs.mu.RLock() 236 defer mbs.mu.RUnlock() 237 238 internalKey := make([]string, 1+len(assertType.PrimaryKey)) 239 internalKey[0] = assertType.Name 240 copy(internalKey[1:], key) 241 242 a, err := mbs.top.get(internalKey, maxFormat) 243 if err == errNotFound { 244 return nil, &NotFoundError{Type: assertType} 245 } 246 return a, err 247 } 248 249 func (mbs *memoryBackstore) Search(assertType *AssertionType, headers map[string]string, foundCb func(Assertion), maxFormat int) error { 250 mbs.mu.RLock() 251 defer mbs.mu.RUnlock() 252 253 hint := make([]string, 1+len(assertType.PrimaryKey)) 254 hint[0] = assertType.Name 255 for i, name := range assertType.PrimaryKey { 256 hint[1+i] = headers[name] 257 } 258 259 candCb := func(a Assertion) { 260 if searchMatch(a, headers) { 261 foundCb(a) 262 } 263 } 264 265 mbs.top.search(hint, candCb, maxFormat) 266 return nil 267 } 268 269 func (mbs *memoryBackstore) SequenceMemberAfter(assertType *AssertionType, sequenceKey []string, after, maxFormat int) (SequenceMember, error) { 270 if !assertType.SequenceForming() { 271 panic(fmt.Sprintf("internal error: SequenceMemberAfter on non sequence-forming assertion type %q", assertType.Name)) 272 } 273 if len(sequenceKey) != len(assertType.PrimaryKey)-1 { 274 return nil, fmt.Errorf("internal error: SequenceMemberAfter's sequence key argument length must be exactly 1 less than the assertion type primary key") 275 } 276 277 mbs.mu.RLock() 278 defer mbs.mu.RUnlock() 279 280 internalPrefix := make([]string, len(assertType.PrimaryKey)) 281 internalPrefix[0] = assertType.Name 282 copy(internalPrefix[1:], sequenceKey) 283 284 a, err := mbs.top.sequenceMemberAfter(internalPrefix, after, maxFormat) 285 if err == errNotFound { 286 return nil, &NotFoundError{Type: assertType} 287 } 288 return a.(SequenceMember), err 289 }