github.com/cockroachdb/pebble@v1.1.2/metamorphic/utils.go (about) 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 11 "golang.org/x/exp/rand" 12 ) 13 14 // objTag identifies the type for an object: DB, Batch, Iter, or Snapshot. 15 type objTag uint8 16 17 const ( 18 dbTag objTag = iota + 1 19 batchTag 20 iterTag 21 snapTag 22 ) 23 24 // objID identifies a particular object. The top 4-bits store the tag 25 // identifying the type of object, while the bottom 28-bits store the slot used 26 // to index with the test.{batches,iters,snapshots} slices. 27 type objID uint32 28 29 func makeObjID(t objTag, slot uint32) objID { 30 return objID((uint32(t) << 28) | slot) 31 } 32 33 func (i objID) tag() objTag { 34 return objTag(i >> 28) 35 } 36 37 func (i objID) slot() uint32 { 38 return uint32(i) & ((1 << 28) - 1) 39 } 40 41 func (i objID) String() string { 42 switch i.tag() { 43 case dbTag: 44 return "db" 45 case batchTag: 46 return fmt.Sprintf("batch%d", i.slot()) 47 case iterTag: 48 return fmt.Sprintf("iter%d", i.slot()) 49 case snapTag: 50 return fmt.Sprintf("snap%d", i.slot()) 51 } 52 return fmt.Sprintf("unknown%d", i.slot()) 53 } 54 55 // objIDSlice is an unordered set of integers used when random selection of an 56 // element is required. 57 type objIDSlice []objID 58 59 func (s objIDSlice) Len() int { return len(s) } 60 func (s objIDSlice) Less(i, j int) bool { return s[i] < s[j] } 61 func (s objIDSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 62 63 // Remove removes the specified integer from the set. 64 // 65 // TODO(peter): If this proves slow, we can replace this implementation with a 66 // map and a slice. The slice would provide for random selection of an element, 67 // while the map would provide quick location of an element to remove. 68 func (s *objIDSlice) remove(id objID) { 69 n := len(*s) 70 for j := 0; j < n; j++ { 71 if (*s)[j] == id { 72 (*s)[j], (*s)[n-1] = (*s)[n-1], (*s)[j] 73 (*s) = (*s)[:n-1] 74 break 75 } 76 } 77 } 78 79 func (s *objIDSlice) rand(rng *rand.Rand) objID { 80 return (*s)[rng.Intn(len(*s))] 81 } 82 83 // objIDSet is an unordered set of object IDs. 84 type objIDSet map[objID]struct{} 85 86 // sortedKeys returns a sorted slice of the set's keys for deterministic 87 // iteration. 88 func (s objIDSet) sorted() []objID { 89 keys := make(objIDSlice, 0, len(s)) 90 for id := range s { 91 keys = append(keys, id) 92 } 93 sort.Sort(keys) 94 return keys 95 } 96 97 // firstError returns the first non-nil error of err0 and err1, or nil if both 98 // are nil. 99 func firstError(err0, err1 error) error { 100 if err0 != nil { 101 return err0 102 } 103 return err1 104 }