minFreeSpace refactored

This commit is contained in:
bingoohuang
2021-04-27 10:37:24 +08:00
parent 31f1cdeac2
commit cf552417a7
10 changed files with 147 additions and 77 deletions

View File

@@ -5,7 +5,6 @@ import (
"crypto/md5"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"io"
"math"
@@ -176,23 +175,12 @@ func EmptyTo(s, to string) string {
return s
}
var ErrMinFreeSpaceBadValue = errors.New("minFreeSpace is invalid")
// ParseMinFreeSpace parses min free space expression s as percentage like 1,10 or human readable size like 10G
func ParseMinFreeSpace(s string) (float32, error) {
if value, e := strconv.ParseFloat(s, 32); e == nil {
if value < 0 || value > 100 {
return 0, ErrMinFreeSpaceBadValue
}
return float32(value), nil
} else if directSize, e2 := ParseBytes(s); e2 == nil {
if directSize <= 100 {
return 0, ErrMinFreeSpaceBadValue
}
return float32(directSize), nil
// IfElse works like b ? this : that.
func IfElse(b bool, this, that string) string {
if b {
return this
}
return 0, ErrMinFreeSpaceBadValue
return that
}
// ParseBytes parses a string representation of bytes into the number

View File

@@ -2,32 +2,6 @@ package util
import "testing"
func TestParseMinFreeSpace(t *testing.T) {
tests := []struct {
in string
ok bool
value float32
}{
{in: "42", ok: true, value: 42},
{in: "-1", ok: false, value: 0},
{in: "101", ok: false, value: 0},
{in: "100B", ok: false, value: 0},
{in: "100Ki", ok: true, value: 100 * 1024},
{in: "100GiB", ok: true, value: 100 * 1024 * 1024 * 1024},
{in: "42M", ok: true, value: 42 * 1000 * 1000},
}
for _, p := range tests {
got, err := ParseMinFreeSpace(p.in)
if p.ok != (err == nil) {
t.Errorf("failed to test %v", p.in)
}
if p.ok && err == nil && got != p.value {
t.Errorf("failed to test %v", p.in)
}
}
}
func TestByteParsing(t *testing.T) {
tests := []struct {
in string

90
weed/util/minfreespace.go Normal file
View File

@@ -0,0 +1,90 @@
package util
import (
"errors"
"fmt"
"github.com/chrislusf/seaweedfs/weed/glog"
"strconv"
"strings"
)
// MinFreeSpaceType is the type of MinFreeSpace.
type MinFreeSpaceType int
const (
// AsPercent set the MinFreeSpaceType to a percentage value from 0 to 100.
AsPercent MinFreeSpaceType = iota
// AsBytes set the MinFreeSpaceType to a absolute value bytes.
AsBytes
)
// MinFreeSpace is type that defines the limit for the minimum free space.
type MinFreeSpace struct {
Type MinFreeSpaceType
Bytes uint64
Percent float32
Raw string
}
// IsLow tells whether the free space is low or not.
func (s MinFreeSpace) IsLow(freeBytes uint64, freePercent float32) (yes bool, desc string) {
switch s.Type {
case AsPercent:
yes = freePercent < s.Percent
op := IfElse(yes, "<", ">=")
return yes, fmt.Sprintf("disk free %.2f%% %s required %.2f%%", freePercent, op, s.Percent)
case AsBytes:
yes = freeBytes < s.Bytes
op := IfElse(yes, "<", ">=")
return yes, fmt.Sprintf("disk free %s %s required %s",
BytesToHumanReadable(freeBytes), op, BytesToHumanReadable(s.Bytes))
}
return false, ""
}
// String returns a string representation of MinFreeSpace.
func (s MinFreeSpace) String() string {
switch s.Type {
case AsPercent:
return fmt.Sprintf("%.2f%%", s.Percent)
default:
return s.Raw
}
}
// MustParseMinFreeSpace parses comma-separated argument for min free space setting.
// minFreeSpace has the high priority than minFreeSpacePercent if it is set.
func MustParseMinFreeSpace(minFreeSpace string, minFreeSpacePercent string) (spaces []MinFreeSpace) {
ss := strings.Split(EmptyTo(minFreeSpace, minFreeSpacePercent), ",")
for _, freeString := range ss {
if vv, e := ParseMinFreeSpace(freeString); e == nil {
spaces = append(spaces, *vv)
} else {
glog.Fatalf("The value specified in -minFreeSpace not a valid value %s", freeString)
}
}
return spaces
}
var ErrMinFreeSpaceBadValue = errors.New("minFreeSpace is invalid")
// ParseMinFreeSpace parses min free space expression s as percentage like 1,10 or human readable size like 10G
func ParseMinFreeSpace(s string) (*MinFreeSpace, error) {
if percent, e := strconv.ParseFloat(s, 32); e == nil {
if percent < 0 || percent > 100 {
return nil, ErrMinFreeSpaceBadValue
}
return &MinFreeSpace{Type: AsPercent, Percent: float32(percent), Raw: s}, nil
}
if directSize, e := ParseBytes(s); e == nil {
if directSize <= 100 {
return nil, ErrMinFreeSpaceBadValue
}
return &MinFreeSpace{Type: AsBytes, Bytes: directSize, Raw: s}, nil
}
return nil, ErrMinFreeSpaceBadValue
}

View File

@@ -0,0 +1,29 @@
package util
import "testing"
func TestParseMinFreeSpace(t *testing.T) {
tests := []struct {
in string
ok bool
value *MinFreeSpace
}{
{in: "42", ok: true, value: &MinFreeSpace{Type: AsPercent, Percent: 42, Raw: "42"}},
{in: "-1", ok: false, value: nil},
{in: "101", ok: false, value: nil},
{in: "100B", ok: false, value: nil},
{in: "100Ki", ok: true, value: &MinFreeSpace{Type: AsBytes, Bytes: 100 * 1024, Raw: "100Ki"}},
{in: "100GiB", ok: true, value: &MinFreeSpace{Type: AsBytes, Bytes: 100 * 1024 * 1024 * 1024, Raw: "100GiB"}},
{in: "42M", ok: true, value: &MinFreeSpace{Type: AsBytes, Bytes: 42 * 1000 * 1000, Raw: "42M"}},
}
for _, p := range tests {
got, err := ParseMinFreeSpace(p.in)
if p.ok != (err == nil) {
t.Errorf("failed to test %v", p.in)
}
if p.ok && err == nil && *got != *p.value {
t.Errorf("failed to test %v", p.in)
}
}
}