Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions cmd/neofs-node/config/cast.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package config

import (
"strings"
"time"
"unicode"

"github.com/spf13/cast"
)
Expand Down Expand Up @@ -144,3 +146,63 @@ func Int(c *Config, name string) int64 {
func IntSafe(c *Config, name string) int64 {
return cast.ToInt64(c.Value(name))
}

// SizeInBytesSafe reads configuration value
// from c by name and casts it to size in bytes (uint64).
//
// The suffix can be single-letter (b, k, m, g, t) or with
// an additional b at the end. Spaces between the number and the suffix
// are allowed. All multipliers are power of 2 (i.e. k is for kibi-byte).
//
// Returns 0 if a value can't be casted.
func SizeInBytesSafe(c *Config, name string) uint64 {
s := StringSafe(c, name)
return parseSizeInBytes(s)
}

// The following code is taken from https://github.com/spf13/viper/blob/master/util.go
// with minor corrections (allow to use both `k` and `kb` forms.
// Seems like viper allows to convert sizes but corresponding parser in `cast` package
// is missing.
func safeMul(a, b uint64) uint64 {
c := a * b
if a > 1 && b > 1 && c/b != a {
return 0
}
return c
}

// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
func parseSizeInBytes(sizeStr string) uint64 {
sizeStr = strings.TrimSpace(sizeStr)
lastChar := len(sizeStr) - 1
multiplier := uint64(1)

if lastChar > 0 {
if sizeStr[lastChar] == 'b' || sizeStr[lastChar] == 'B' {
lastChar--
}
if lastChar > 0 {
switch unicode.ToLower(rune(sizeStr[lastChar])) {
case 'k':
multiplier = 1 << 10
sizeStr = strings.TrimSpace(sizeStr[:lastChar])
case 'm':
multiplier = 1 << 20
sizeStr = strings.TrimSpace(sizeStr[:lastChar])
case 'g':
multiplier = 1 << 30
sizeStr = strings.TrimSpace(sizeStr[:lastChar])
case 't':
multiplier = 1 << 40
sizeStr = strings.TrimSpace(sizeStr[:lastChar])
default:
multiplier = 1
sizeStr = strings.TrimSpace(sizeStr[:lastChar+1])
}
}
}

size := cast.ToUint64(sizeStr)
return safeMul(size, multiplier)
}
19 changes: 19 additions & 0 deletions cmd/neofs-node/config/cast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,22 @@ func TestNumbers(t *testing.T) {
require.Zero(t, config.UintSafe(c, incorrect))
})
}

func TestSizeInBytes(t *testing.T) {
const (
kb = 1024
mb = 1024 * kb
gb = 1024 * mb
tb = 1024 * gb
)
configtest.ForEachFileType("test/config", func(c *config.Config) {
c = c.Sub("sizes")
require.EqualValues(t, kb, config.SizeInBytesSafe(c, "size_kb"))
require.EqualValues(t, 2*kb, config.SizeInBytesSafe(c, "size_kb_no_space"))
require.EqualValues(t, 12*mb, config.SizeInBytesSafe(c, "size_mb"))
require.EqualValues(t, 4*gb, config.SizeInBytesSafe(c, "size_gb"))
require.EqualValues(t, 5*tb, config.SizeInBytesSafe(c, "size_tb"))
require.EqualValues(t, 2048, config.SizeInBytesSafe(c, "size_bytes"))
require.EqualValues(t, 123456, config.SizeInBytesSafe(c, "size_bytes_no_suffix"))
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func From(c *config.Config) *Config {
//
// Returns SizeDefault if value is not a positive number.
func (x *Config) Size() uint64 {
s := config.UintSafe(
s := config.SizeInBytesSafe(
(*config.Config)(x),
"size",
)
Expand Down
2 changes: 1 addition & 1 deletion cmd/neofs-node/config/engine/shard/blobstor/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (x *Config) Compress() bool {
//
// Returns SmallSizeLimitDefault if value is not a positive number.
func (x *Config) SmallSizeLimit() uint64 {
l := config.UintSafe(
l := config.SizeInBytesSafe(
(*config.Config)(x),
"small_size_limit",
)
Expand Down
8 changes: 4 additions & 4 deletions cmd/neofs-node/config/engine/shard/writecache/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (x *Config) Path() string {
//
// Returns MemSizeDefault if value is not a positive number.
func (x *Config) MemSize() uint64 {
s := config.UintSafe(
s := config.SizeInBytesSafe(
(*config.Config)(x),
"mem_size",
)
Expand All @@ -67,7 +67,7 @@ func (x *Config) MemSize() uint64 {
//
// Returns SmallSizeDefault if value is not a positive number.
func (x *Config) SmallObjectSize() uint64 {
s := config.UintSafe(
s := config.SizeInBytesSafe(
(*config.Config)(x),
"small_size",
)
Expand All @@ -83,7 +83,7 @@ func (x *Config) SmallObjectSize() uint64 {
//
// Returns MaxSizeDefault if value is not a positive number.
func (x *Config) MaxObjectSize() uint64 {
s := config.UintSafe(
s := config.SizeInBytesSafe(
(*config.Config)(x),
"max_size",
)
Expand Down Expand Up @@ -115,7 +115,7 @@ func (x *Config) WorkersNumber() int {
//
// Returns SizeLimitDefault if value is not a positive number.
func (x *Config) SizeLimit() uint64 {
c := config.UintSafe(
c := config.SizeInBytesSafe(
(*config.Config)(x),
"size_limit",
)
Expand Down
10 changes: 10 additions & 0 deletions cmd/neofs-node/config/test/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,15 @@
"correct": true,
"correct_string": "true",
"incorrect": "not true"
},

"sizes": {
"size_kb": "1 kb",
"size_kb_no_space": "2kb",
"size_mb": "12m",
"size_gb": "4g",
"size_tb": "5 TB",
"size_bytes": "2048b",
"size_bytes_no_suffix": 123456
}
}
9 changes: 9 additions & 0 deletions cmd/neofs-node/config/test/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,12 @@ bool:
correct: true
correct_string: "true"
incorrect: not true

sizes:
size_kb: 1 kb
size_kb_no_space: 2kb
size_mb: 12m
size_gb: 4g
size_tb: 5 TB
size_bytes: 2048b
size_bytes_no_suffix: 123456