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  }