crushkv/crushmap/common.go

242 lines
5.6 KiB
Go
Raw Permalink Normal View History

package crushmap
import (
"fmt"
"sort"
"strconv"
)
const (
ReplicatedPG = 1
ErasurePG = 3
)
type CrushBucketType uint16
type CrushAlgType uint8
type CrushBucketHashType uint8
const (
CrushAlgInvalid CrushAlgType = iota
CrushAlgUniform
CrushAlgList
CrushAlgTree
CrushAlgStraw
CrushAlgStraw2
)
const (
CrushLegacyAllowedBucketAlgs = (1 << CrushAlgUniform) | (1 << CrushAlgList) | (1 << CrushAlgStraw)
)
var (
crushAlgTypeStringMap = map[CrushAlgType]string{
CrushAlgUniform: "uniform",
CrushAlgList: "list",
CrushAlgTree: "tree",
CrushAlgStraw: "straw",
CrushAlgStraw2: "straw2",
}
crushAlgStringTypeMap = map[string]CrushAlgType{
"uniform": CrushAlgUniform,
"list": CrushAlgList,
"tree": CrushAlgTree,
"straw": CrushAlgStraw,
"straw2": CrushAlgStraw2,
}
)
func (t CrushBucketType) String() string {
return fmt.Sprintf(strconv.Itoa(int(t)))
}
func (t CrushBucketHashType) String() string {
if t == 0 {
return "rjenkins1"
}
return fmt.Sprintf(strconv.Itoa(int(t)))
}
func (t CrushAlgType) String() string {
alg, ok := crushAlgTypeStringMap[t]
if !ok {
alg = "invalid"
}
return alg
}
func CrushAlgFromType(t CrushAlgType) (string, error) {
alg, ok := crushAlgTypeStringMap[t]
if !ok {
return "", fmt.Errorf("unknown crush bucket alg: %d", t)
}
return alg, nil
}
func CrushAlgFromString(t string) (CrushAlgType, error) {
alg, ok := crushAlgStringTypeMap[t]
if !ok {
return CrushAlgInvalid, fmt.Errorf("unknown crush bucket algo: %s", t)
}
return alg, nil
}
type Tunables struct {
// new block
ChooseLocalTries uint32 `json:"choose_local_tries,omitempty"`
ChooseLocalFallbackTries uint32 `json:"choose_local_fallback_tries,omitempty"`
ChooseTotalTries uint32 `json:"choose_total_tries,omitempty"`
// new block must be equal 1
ChooseleafDescendOnce uint32 `json:"chooseleaf_descend_once,omitempty"`
// new block must be equal 1
ChooseleafVaryR uint8 `json:"chooseleaf_vary_r,omitempty"`
// new block must be equal 1
StrawCalcVersion uint8 `json:"straw_calc_version,omitempty"`
// new block must be equal ??
AllowedBucketAlgs uint32 `json:"allowed_bucket_algs,omitempty"`
// new block must be equal 1
ChooseleafStable uint8 `json:"chooseleaf_stable,omitempty"`
//
/*
"profile": "firefly",
"optimal_tunables": 0,
"legacy_tunables": 0,
"minimum_required_version": "firefly",
"require_feature_tunables": 1,
"require_feature_tunables2": 1,
"has_v2_rules": 1,
"require_feature_tunables3": 1,
"has_v3_rules": 0,
"has_v4_buckets": 0,
"require_feature_tunables5": 0,
"has_v5_rules": 0
*/
}
type Step struct {
Op string `json:"op"`
Item int `json:"item,omitempty"`
ItemName string `json:"item_name,omitempty"`
ItemClass string `json:"item_class,omitempty"`
Num int32 `json:"num,omitempty"`
ItemType string `json:"type,omitempty"`
ItemTypeID int32 `json:"-"`
}
type Rule struct {
Name string `json:"rule_name"`
ID uint8 `json:"rule_id"`
Ruleset uint8 `json:"ruleset,omitempty"`
Type uint8 `json:"type"`
MinSize uint8 `json:"min_size,omitempty"`
MaxSize uint8 `json:"max_size,omitempty"`
Steps []*Step `json:"steps"`
}
type Item struct {
ID int32 `json:"id"`
Name string `json:"-,omitempty"`
Weight float32 `json:"weight"`
Pos int `json:"pos"`
}
type Bucket struct {
Name string `json:"name"`
TypeID CrushBucketType `json:"type_id"`
TypeName string `json:"type_name"`
Weight float32 `json:"weight"`
ID int32 `json:"id"`
IDClass string `json:"id_class,omitempty"`
Alg string `json:"alg"`
Hash string `json:"hash"`
Size uint32 `json:"-"`
Items []*Item `json:"items"`
}
type Device struct {
ID int32 `json:"id"`
Name string `json:"name"`
Class string `json:"class,omitempty"`
}
type Type struct {
ID int32 `json:"type_id"`
Name string `json:"name"`
}
type ChooseArg struct {
BucketID int32 `json:"bucket_id,omitempty"`
WeightSet []float64 `json:"weight_set,omitempty"`
IDs []int `json:"ids,omitempty"`
}
type Map struct {
Tunables map[string]interface{} `json:"tunables,omitempty"`
Devices []*Device `json:"devices"`
Types []*Type `json:"types"`
Buckets []*Bucket `json:"buckets"`
Rules []*Rule `json:"rules"`
ChooseArgs map[string]ChooseArg `json:"choose_args,omitempty"`
}
type CrushChild struct {
ID int `json:"id"`
Name string `json:"name"`
Weight float32 `json:"weight"`
}
type CrushTree struct {
Type string `json:"type"`
Name string `json:"name"`
ID int `json:"id"`
Children []*CrushChild `json:"children"`
}
type CrushRule struct {
Data [][]string `json:"data"`
}
type Crushmap struct {
Trees []*CrushTree `json:"trees"`
Rules []*CrushRule `json:"rules"`
}
func (m *Map) rulesSort() {
sort.Slice(m.Rules, func(i, j int) bool { return m.Rules[i].ID < m.Rules[j].ID })
}
func (m *Map) bucketsSort() {
sort.Slice(m.Buckets, func(i, j int) bool { return m.Buckets[i].TypeID > m.Buckets[j].TypeID })
}
func (m *Map) GetTypeIDByName(name string) uint16 {
for _, t := range m.Types {
if t.Name == name {
return uint16(t.ID)
}
}
return 0
}
func (m *Map) GetBucketByName(name string) *Bucket {
for _, b := range m.Buckets {
if b.Name == name {
return b
}
}
return nil
}
func (m *Map) GetBucketByID(id int32) *Bucket {
for _, b := range m.Buckets {
if b.ID == id {
return b
}
}
return nil
}
func NewMap() *Map {
return &Map{Tunables: make(map[string]interface{})}
}