LCOV - code coverage report
Current view: top level - pebble/metamorphic - utils.go (source / functions) Hit Total Coverage
Test: 2024-07-04 08:15Z fad89cfb - tests + meta.lcov Lines: 47 51 92.2 %
Date: 2024-07-04 08:17:01 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2019 The LevelDB-Go and Pebble Authors. All rights reserved. Use
       2             : // of this source code is governed by a BSD-style license that can be found in
       3             : // the LICENSE file.
       4             : 
       5             : package metamorphic
       6             : 
       7             : import (
       8             :         "fmt"
       9             :         "sort"
      10             :         "strconv"
      11             :         "strings"
      12             : 
      13             :         "github.com/cockroachdb/errors"
      14             :         "golang.org/x/exp/rand"
      15             : )
      16             : 
      17             : // objTag identifies the type for an object: DB, Batch, Iter, or Snapshot.
      18             : type objTag uint8
      19             : 
      20             : const (
      21             :         dbTag objTag = iota + 1
      22             :         batchTag
      23             :         iterTag
      24             :         snapTag
      25             :         externalObjTag
      26             :         numObjTags
      27             : )
      28             : 
      29             : var objTagPrefix = [numObjTags]string{
      30             :         dbTag:          "db",
      31             :         batchTag:       "batch",
      32             :         iterTag:        "iter",
      33             :         snapTag:        "snap",
      34             :         externalObjTag: "external",
      35             : }
      36             : 
      37             : // objID identifies a particular object. The top 4-bits store the tag
      38             : // identifying the type of object, while the bottom 28-bits store the slot used
      39             : // to index with the test.{batches,iters,snapshots,externalObjs} slices.
      40             : type objID uint32
      41             : 
      42           2 : func makeObjID(t objTag, slot uint32) objID {
      43           2 :         return objID((uint32(t) << 28) | slot)
      44           2 : }
      45             : 
      46           2 : func (i objID) tag() objTag {
      47           2 :         return objTag(i >> 28)
      48           2 : }
      49             : 
      50           2 : func (i objID) slot() uint32 {
      51           2 :         return uint32(i) & ((1 << 28) - 1)
      52           2 : }
      53             : 
      54           2 : func (i objID) String() string {
      55           2 :         return fmt.Sprintf("%s%d", objTagPrefix[i.tag()], i.slot())
      56           2 : }
      57             : 
      58           2 : func parseObjID(str string) (objID, error) {
      59           2 :         // To provide backward compatibility, treat "db" as "db1". Note that unlike
      60           2 :         // the others, db slots are 1-indexed.
      61           2 :         if str == "db" {
      62           1 :                 str = "db1"
      63           1 :         }
      64           2 :         for tag := objTag(1); tag < numObjTags; tag++ {
      65           2 :                 if strings.HasPrefix(str, objTagPrefix[tag]) {
      66           2 :                         id, err := strconv.ParseInt(str[len(objTagPrefix[tag]):], 10, 32)
      67           2 :                         if err != nil {
      68           0 :                                 return 0, err
      69           0 :                         }
      70           2 :                         return makeObjID(tag, uint32(id)), nil
      71             :                 }
      72             :         }
      73           1 :         return 0, errors.Newf("unknown object type: %q", str)
      74             : }
      75             : 
      76             : // objIDSlice is an unordered set of integers used when random selection of an
      77             : // element is required.
      78             : type objIDSlice []objID
      79             : 
      80           1 : func (s objIDSlice) Len() int           { return len(s) }
      81           1 : func (s objIDSlice) Less(i, j int) bool { return s[i] < s[j] }
      82           1 : func (s objIDSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
      83             : 
      84             : // Remove removes the specified integer from the set.
      85             : //
      86             : // TODO(peter): If this proves slow, we can replace this implementation with a
      87             : // map and a slice. The slice would provide for random selection of an element,
      88             : // while the map would provide quick location of an element to remove.
      89           1 : func (s *objIDSlice) remove(id objID) {
      90           1 :         n := len(*s)
      91           1 :         for j := 0; j < n; j++ {
      92           1 :                 if (*s)[j] == id {
      93           1 :                         (*s)[j], (*s)[n-1] = (*s)[n-1], (*s)[j]
      94           1 :                         (*s) = (*s)[:n-1]
      95           1 :                         break
      96             :                 }
      97             :         }
      98             : }
      99             : 
     100           1 : func (s *objIDSlice) rand(rng *rand.Rand) objID {
     101           1 :         return (*s)[rng.Intn(len(*s))]
     102           1 : }
     103             : 
     104             : // objIDSet is an unordered set of object IDs.
     105             : type objIDSet map[objID]struct{}
     106             : 
     107             : // sortedKeys returns a sorted slice of the set's keys for deterministic
     108             : // iteration.
     109           1 : func (s objIDSet) sorted() []objID {
     110           1 :         keys := make(objIDSlice, 0, len(s))
     111           1 :         for id := range s {
     112           1 :                 keys = append(keys, id)
     113           1 :         }
     114           1 :         sort.Sort(keys)
     115           1 :         return keys
     116             : }
     117             : 
     118             : // firstError returns the first non-nil error of err0 and err1, or nil if both
     119             : // are nil.
     120           2 : func firstError(err0, err1 error) error {
     121           2 :         if err0 != nil {
     122           0 :                 return err0
     123           0 :         }
     124           2 :         return err1
     125             : }

Generated by: LCOV version 1.14