mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-20 15:15:18 +00:00
105 lines
2.5 KiB
Go
105 lines
2.5 KiB
Go
// Copyright 2019 The LevelDB-Go and Pebble Authors. All rights reserved. Use
|
|
// of this source code is governed by a BSD-style license that can be found in
|
|
// the LICENSE file.
|
|
|
|
package metamorphic
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
"golang.org/x/exp/rand"
|
|
)
|
|
|
|
// objTag identifies the type for an object: DB, Batch, Iter, or Snapshot.
|
|
type objTag uint8
|
|
|
|
const (
|
|
dbTag objTag = iota + 1
|
|
batchTag
|
|
iterTag
|
|
snapTag
|
|
)
|
|
|
|
// objID identifies a particular object. The top 4-bits store the tag
|
|
// identifying the type of object, while the bottom 28-bits store the slot used
|
|
// to index with the test.{batches,iters,snapshots} slices.
|
|
type objID uint32
|
|
|
|
func makeObjID(t objTag, slot uint32) objID {
|
|
return objID((uint32(t) << 28) | slot)
|
|
}
|
|
|
|
func (i objID) tag() objTag {
|
|
return objTag(i >> 28)
|
|
}
|
|
|
|
func (i objID) slot() uint32 {
|
|
return uint32(i) & ((1 << 28) - 1)
|
|
}
|
|
|
|
func (i objID) String() string {
|
|
switch i.tag() {
|
|
case dbTag:
|
|
return fmt.Sprintf("db%d", i.slot())
|
|
case batchTag:
|
|
return fmt.Sprintf("batch%d", i.slot())
|
|
case iterTag:
|
|
return fmt.Sprintf("iter%d", i.slot())
|
|
case snapTag:
|
|
return fmt.Sprintf("snap%d", i.slot())
|
|
}
|
|
return fmt.Sprintf("unknown%d", i.slot())
|
|
}
|
|
|
|
// objIDSlice is an unordered set of integers used when random selection of an
|
|
// element is required.
|
|
type objIDSlice []objID
|
|
|
|
func (s objIDSlice) Len() int { return len(s) }
|
|
func (s objIDSlice) Less(i, j int) bool { return s[i] < s[j] }
|
|
func (s objIDSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
|
|
// Remove removes the specified integer from the set.
|
|
//
|
|
// TODO(peter): If this proves slow, we can replace this implementation with a
|
|
// map and a slice. The slice would provide for random selection of an element,
|
|
// while the map would provide quick location of an element to remove.
|
|
func (s *objIDSlice) remove(id objID) {
|
|
n := len(*s)
|
|
for j := 0; j < n; j++ {
|
|
if (*s)[j] == id {
|
|
(*s)[j], (*s)[n-1] = (*s)[n-1], (*s)[j]
|
|
(*s) = (*s)[:n-1]
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *objIDSlice) rand(rng *rand.Rand) objID {
|
|
return (*s)[rng.Intn(len(*s))]
|
|
}
|
|
|
|
// objIDSet is an unordered set of object IDs.
|
|
type objIDSet map[objID]struct{}
|
|
|
|
// sortedKeys returns a sorted slice of the set's keys for deterministic
|
|
// iteration.
|
|
func (s objIDSet) sorted() []objID {
|
|
keys := make(objIDSlice, 0, len(s))
|
|
for id := range s {
|
|
keys = append(keys, id)
|
|
}
|
|
sort.Sort(keys)
|
|
return keys
|
|
}
|
|
|
|
// firstError returns the first non-nil error of err0 and err1, or nil if both
|
|
// are nil.
|
|
func firstError(err0, err1 error) error {
|
|
if err0 != nil {
|
|
return err0
|
|
}
|
|
return err1
|
|
}
|