crushkv/crushmap/binary_bucket.go
Vasiliy Tolstov 24f641df0d initial rewrite
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2019-04-18 23:13:04 +03:00

303 lines
7.2 KiB
Go

package crushmap
import (
"encoding/binary"
"fmt"
"math"
)
type binaryBucket interface {
BucketID() int32
BucketType() CrushBucketType
BucketAlg() CrushAlgType
BucketHash() CrushBucketHashType
BucketWeight() float32
BucketSize() uint32
}
func (b *BucketUniform) BucketID() int32 {
return b.ID
}
func (b *BucketUniform) BucketType() CrushBucketType {
return b.Type
}
func (b *BucketUniform) BucketAlg() CrushAlgType {
return b.Alg
}
func (b *BucketUniform) BucketHash() CrushBucketHashType {
return b.Hash
}
func (b *BucketUniform) BucketWeight() float32 {
return b.Weight
}
func (b *BucketUniform) BucketSize() uint32 {
return b.Size
}
func (b *BucketList) BucketID() int32 {
return b.ID
}
func (b *BucketList) BucketType() CrushBucketType {
return b.Type
}
func (b *BucketList) BucketAlg() CrushAlgType {
return b.Alg
}
func (b *BucketList) BucketHash() CrushBucketHashType {
return b.Hash
}
func (b *BucketList) BucketWeight() float32 {
return b.Weight
}
func (b *BucketList) BucketSize() uint32 {
return b.Size
}
func (b *BucketTree) BucketID() int32 {
return b.ID
}
func (b *BucketTree) BucketType() CrushBucketType {
return b.Type
}
func (b *BucketTree) BucketAlg() CrushAlgType {
return b.Alg
}
func (b *BucketTree) BucketHash() CrushBucketHashType {
return b.Hash
}
func (b *BucketTree) BucketWeight() float32 {
return b.Weight
}
func (b *BucketTree) BucketSize() uint32 {
return b.Size
}
func (b *BucketStraw) BucketID() int32 {
return b.ID
}
func (b *BucketStraw) BucketType() CrushBucketType {
return b.Type
}
func (b *BucketStraw) BucketAlg() CrushAlgType {
return b.Alg
}
func (b *BucketStraw) BucketHash() CrushBucketHashType {
return b.Hash
}
func (b *BucketStraw) BucketWeight() float32 {
return b.Weight
}
func (b *BucketStraw) BucketSize() uint32 {
return b.Size
}
func (b *BucketStraw2) BucketID() int32 {
return b.ID
}
func (b *BucketStraw2) BucketType() CrushBucketType {
return b.Type
}
func (b *BucketStraw2) BucketAlg() CrushAlgType {
return b.Alg
}
func (b *BucketStraw2) BucketHash() CrushBucketHashType {
return b.Hash
}
func (b *BucketStraw2) BucketWeight() float32 {
return b.Weight
}
func (b *BucketStraw2) BucketSize() uint32 {
return b.Size
}
type binaryBucketHeader struct {
ID int32
Type CrushBucketType
Alg CrushAlgType
Hash CrushBucketHashType
Weight float32
Size uint32
}
type binaryBucketCommon struct {
binaryBucketHeader
Items []int32
}
type BucketUniform struct {
binaryBucketCommon
ItemWeight float32
}
type BucketList struct {
binaryBucketCommon
ItemWeights []float32
SumWeights []float32
}
type BucketTree struct {
binaryBucketCommon
NumNodes uint8
NodeWeights []float32
}
type BucketStraw struct {
binaryBucketCommon
ItemWeights []float32
Straws []uint32
}
type BucketStraw2 struct {
binaryBucketCommon
ItemWeights []float32
}
func (b *binaryBucketHeader) String() string {
return fmt.Sprintf("id: %d, type: %s, alg: %s, hash: %s, weight: %f, size: %d",
b.ID, b.Type, b.Alg, b.Hash, b.Weight, b.Size)
}
func (p *binaryParser) handleBucket() (*Bucket, error) {
var err error
ibucket := &Bucket{}
var bucket binaryBucket
var alg uint32
err = binary.Read(p.r, binary.LittleEndian, &alg)
if err != nil {
return nil, err
}
if CrushAlgType(alg) == CrushAlgInvalid {
return nil, nil
}
bucketHeader := binaryBucketHeader{}
err = binary.Read(p.r, binary.LittleEndian, &bucketHeader.ID)
if err != nil {
return nil, err
}
err = binary.Read(p.r, binary.LittleEndian, &bucketHeader.Type)
if err != nil {
return nil, err
}
err = binary.Read(p.r, binary.LittleEndian, &bucketHeader.Alg)
if err != nil {
return nil, err
}
err = binary.Read(p.r, binary.LittleEndian, &bucketHeader.Hash)
if err != nil {
return nil, err
}
var weight uint32
err = binary.Read(p.r, binary.LittleEndian, &weight)
if err != nil {
return nil, err
}
bucketHeader.Weight = math.Float32frombits(weight)
err = binary.Read(p.r, binary.LittleEndian, &bucketHeader.Size)
if err != nil {
return nil, err
}
bucketCommon := binaryBucketCommon{binaryBucketHeader: bucketHeader}
bucketCommon.Items = make([]int32, bucketHeader.Size)
for i := uint32(0); i < bucketHeader.Size; i++ {
err = binary.Read(p.r, binary.LittleEndian, &bucketCommon.Items[i])
if err != nil {
return nil, err
}
}
switch bucketHeader.Alg {
case CrushAlgUniform:
bucketUniform := &BucketUniform{
binaryBucketCommon: bucketCommon,
}
var itemWeight uint32
err = binary.Read(p.r, binary.LittleEndian, &itemWeight)
if err != nil {
return nil, err
}
bucketUniform.ItemWeight = math.Float32frombits(itemWeight)
bucket = bucketUniform
case CrushAlgList:
itemWeights := make([]uint32, bucketHeader.Size)
sumWeights := make([]uint32, bucketHeader.Size)
bucketList := &BucketList{
binaryBucketCommon: bucketCommon,
ItemWeights: make([]float32, bucketHeader.Size),
SumWeights: make([]float32, bucketHeader.Size),
}
for i := uint32(0); i <= bucketHeader.Size; i++ {
err = binary.Read(p.r, binary.LittleEndian, &itemWeights[i])
if err != nil {
return nil, err
}
bucketList.ItemWeights[i] = math.Float32frombits(itemWeights[i])
err = binary.Read(p.r, binary.LittleEndian, &sumWeights[i])
if err != nil {
return nil, err
}
bucketList.SumWeights[i] = math.Float32frombits(sumWeights[i])
}
bucket = bucketList
case CrushAlgTree:
bucketTree := &BucketTree{
binaryBucketCommon: bucketCommon,
}
err = binary.Read(p.r, binary.LittleEndian, &bucketTree.NumNodes)
if err != nil {
return nil, err
}
nodeWeights := make([]uint32, bucketTree.NumNodes*4)
bucketTree.NodeWeights = make([]float32, bucketTree.NumNodes*4)
err = binary.Read(p.r, binary.LittleEndian, &nodeWeights)
if err != nil {
return nil, err
}
for i := 0; i < int(bucketTree.NumNodes*4); i++ {
bucketTree.NodeWeights[i] = math.Float32frombits(nodeWeights[i])
}
bucket = bucketTree
case CrushAlgStraw:
itemWeights := make([]uint32, (bucketHeader.Size)*4)
bucketStraw := &BucketStraw{
binaryBucketCommon: bucketCommon,
Straws: make([]uint32, (bucketHeader.Size)*4),
ItemWeights: make([]float32, (bucketHeader.Size)*4),
}
for i := uint32(0); i < bucketHeader.Size; i++ {
err = binary.Read(p.r, binary.LittleEndian, &itemWeights[i])
if err != nil {
return nil, err
}
bucketStraw.ItemWeights[i] = math.Float32frombits(itemWeights[i])
err = binary.Read(p.r, binary.LittleEndian, &bucketStraw.Straws[i])
if err != nil {
return nil, err
}
}
bucket = bucketStraw
case CrushAlgStraw2:
itemWeights := make([]uint32, (bucketHeader.Size+1)*4)
bucketStraw2 := &BucketStraw2{
binaryBucketCommon: bucketCommon,
ItemWeights: make([]float32, (bucketHeader.Size+1)*4),
}
err = binary.Read(p.r, binary.LittleEndian, &itemWeights)
if err != nil {
return nil, err
}
for i := uint32(0); i < (bucketHeader.Size+1)*4; i++ {
bucketStraw2.ItemWeights[i] = math.Float32frombits(itemWeights[i])
}
bucket = bucketStraw2
}
ibucket.ID = bucketHeader.ID
ibucket.Alg = bucketHeader.Alg.String()
ibucket.Hash = bucketHeader.Hash.String()
ibucket.TypeID = bucketHeader.Type
ibucket.Weight = bucketHeader.Weight
ibucket.Size = bucketHeader.Size
_ = bucket
return ibucket, nil
}