gitee.com/mysnapcore/mysnapd@v0.1.0/asserts/membackstore.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2022 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 n := len(assertType.PrimaryKey) 239 if len(key) > n { 240 return nil, fmt.Errorf("internal error: Backstore.Get given a key longer than expected for %q: %v", assertType.Name, key) 241 } 242 243 internalKey := make([]string, 1+len(assertType.PrimaryKey)) 244 internalKey[0] = assertType.Name 245 copy(internalKey[1:], key) 246 if len(key) < n { 247 for kopt := len(key); kopt < n; kopt++ { 248 defl := assertType.OptionalPrimaryKeyDefaults[assertType.PrimaryKey[kopt]] 249 if defl == "" { 250 return nil, fmt.Errorf("internal error: Backstore.Get given a key missing mandatory elements for %q: %v", assertType.Name, key) 251 } 252 internalKey[kopt+1] = defl 253 } 254 } 255 256 a, err := mbs.top.get(internalKey, maxFormat) 257 if err == errNotFound { 258 return nil, &NotFoundError{Type: assertType} 259 } 260 return a, err 261 } 262 263 func (mbs *memoryBackstore) Search(assertType *AssertionType, headers map[string]string, foundCb func(Assertion), maxFormat int) error { 264 mbs.mu.RLock() 265 defer mbs.mu.RUnlock() 266 267 hint := make([]string, 1+len(assertType.PrimaryKey)) 268 hint[0] = assertType.Name 269 for i, name := range assertType.PrimaryKey { 270 hint[1+i] = headers[name] 271 } 272 273 candCb := func(a Assertion) { 274 if searchMatch(a, headers) { 275 foundCb(a) 276 } 277 } 278 279 mbs.top.search(hint, candCb, maxFormat) 280 return nil 281 } 282 283 func (mbs *memoryBackstore) SequenceMemberAfter(assertType *AssertionType, sequenceKey []string, after, maxFormat int) (SequenceMember, error) { 284 if !assertType.SequenceForming() { 285 panic(fmt.Sprintf("internal error: SequenceMemberAfter on non sequence-forming assertion type %q", assertType.Name)) 286 } 287 if len(sequenceKey) != len(assertType.PrimaryKey)-1 { 288 return nil, fmt.Errorf("internal error: SequenceMemberAfter's sequence key argument length must be exactly 1 less than the assertion type primary key") 289 } 290 291 mbs.mu.RLock() 292 defer mbs.mu.RUnlock() 293 294 internalPrefix := make([]string, len(assertType.PrimaryKey)) 295 internalPrefix[0] = assertType.Name 296 copy(internalPrefix[1:], sequenceKey) 297 298 a, err := mbs.top.sequenceMemberAfter(internalPrefix, after, maxFormat) 299 if err == errNotFound { 300 return nil, &NotFoundError{Type: assertType} 301 } 302 return a.(SequenceMember), err 303 }