github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/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 return 150 } 151 152 func (leaf memBSLeaf) search(hint []string, found func(Assertion), maxFormat int) { 153 hint0 := hint[0] 154 if hint0 == "" { 155 for key := range leaf { 156 cand := leaf.cur(key, maxFormat) 157 if cand != nil { 158 found(cand) 159 } 160 } 161 return 162 } 163 164 cur := leaf.cur(hint0, maxFormat) 165 if cur != nil { 166 found(cur) 167 } 168 } 169 170 func (br memBSBranch) sequenceMemberAfter(prefix []string, after, maxFormat int) (Assertion, error) { 171 prefix0 := prefix[0] 172 down := br[prefix0] 173 if down == nil { 174 return nil, errNotFound 175 } 176 return down.sequenceMemberAfter(prefix[1:], after, maxFormat) 177 } 178 179 func (left memBSLeaf) sequenceMemberAfter(prefix []string, after, maxFormat int) (Assertion, error) { 180 panic("internal error: unexpected sequenceMemberAfter on memBSLeaf") 181 } 182 183 func (leaf *memBSSeqLeaf) sequenceMemberAfter(prefix []string, after, maxFormat int) (Assertion, error) { 184 n := len(leaf.sequence) 185 dir := 1 186 var start int 187 if after == -1 { 188 // search for the latest in sequence compatible with 189 // maxFormat: consider all sequence numbers in 190 // sequence backward 191 dir = -1 192 start = n - 1 193 } else { 194 // search for the first in sequence with sequence number 195 // > after and compatible with maxFormat 196 start = sort.SearchInts(leaf.sequence, after) 197 if start == n { 198 // nothing 199 return nil, errNotFound 200 } 201 if leaf.sequence[start] == after { 202 // skip after itself 203 start += 1 204 } 205 } 206 for j := start; j >= 0 && j < n; j += dir { 207 seqkey := strconv.Itoa(leaf.sequence[j]) 208 cur := leaf.cur(seqkey, maxFormat) 209 if cur != nil { 210 return cur, nil 211 } 212 } 213 return nil, errNotFound 214 } 215 216 // NewMemoryBackstore creates a memory backed assertions backstore. 217 func NewMemoryBackstore() Backstore { 218 return &memoryBackstore{ 219 top: make(memBSBranch), 220 } 221 } 222 223 func (mbs *memoryBackstore) Put(assertType *AssertionType, assert Assertion) error { 224 mbs.mu.Lock() 225 defer mbs.mu.Unlock() 226 227 internalKey := make([]string, 1, 1+len(assertType.PrimaryKey)) 228 internalKey[0] = assertType.Name 229 internalKey = append(internalKey, assert.Ref().PrimaryKey...) 230 231 err := mbs.top.put(assertType, internalKey, assert) 232 return err 233 } 234 235 func (mbs *memoryBackstore) Get(assertType *AssertionType, key []string, maxFormat int) (Assertion, error) { 236 mbs.mu.RLock() 237 defer mbs.mu.RUnlock() 238 239 internalKey := make([]string, 1+len(assertType.PrimaryKey)) 240 internalKey[0] = assertType.Name 241 copy(internalKey[1:], key) 242 243 a, err := mbs.top.get(internalKey, maxFormat) 244 if err == errNotFound { 245 return nil, &NotFoundError{Type: assertType} 246 } 247 return a, err 248 } 249 250 func (mbs *memoryBackstore) Search(assertType *AssertionType, headers map[string]string, foundCb func(Assertion), maxFormat int) error { 251 mbs.mu.RLock() 252 defer mbs.mu.RUnlock() 253 254 hint := make([]string, 1+len(assertType.PrimaryKey)) 255 hint[0] = assertType.Name 256 for i, name := range assertType.PrimaryKey { 257 hint[1+i] = headers[name] 258 } 259 260 candCb := func(a Assertion) { 261 if searchMatch(a, headers) { 262 foundCb(a) 263 } 264 } 265 266 mbs.top.search(hint, candCb, maxFormat) 267 return nil 268 } 269 270 func (mbs *memoryBackstore) SequenceMemberAfter(assertType *AssertionType, sequenceKey []string, after, maxFormat int) (SequenceMember, error) { 271 if !assertType.SequenceForming() { 272 panic(fmt.Sprintf("internal error: SequenceMemberAfter on non sequence-forming assertion type %q", assertType.Name)) 273 } 274 if len(sequenceKey) != len(assertType.PrimaryKey)-1 { 275 return nil, fmt.Errorf("internal error: SequenceMemberAfter's sequence key argument length must be exactly 1 less than the assertion type primary key") 276 } 277 278 mbs.mu.RLock() 279 defer mbs.mu.RUnlock() 280 281 internalPrefix := make([]string, len(assertType.PrimaryKey)) 282 internalPrefix[0] = assertType.Name 283 copy(internalPrefix[1:], sequenceKey) 284 285 a, err := mbs.top.sequenceMemberAfter(internalPrefix, after, maxFormat) 286 if err == errNotFound { 287 return nil, &NotFoundError{Type: assertType} 288 } 289 return a.(SequenceMember), err 290 }