forked from TrueCloudLab/frostfs-node
[#903] config: support floating-point sizes
Rounding is done using the suffix boundary (i.e. floating point value with `gb` suffix will return size which is an integer number of megabytes). Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
e7fd980951
commit
aba09bb853
4 changed files with 31 additions and 5 deletions
|
@ -1,6 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/bits"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
@ -164,12 +165,28 @@ func SizeInBytesSafe(c *Config, name string) uint64 {
|
||||||
// with minor corrections (allow to use both `k` and `kb` forms.
|
// with minor corrections (allow to use both `k` and `kb` forms.
|
||||||
// Seems like viper allows to convert sizes but corresponding parser in `cast` package
|
// Seems like viper allows to convert sizes but corresponding parser in `cast` package
|
||||||
// is missing.
|
// is missing.
|
||||||
func safeMul(a, b uint64) uint64 {
|
|
||||||
c := a * b
|
// safeMul returns size*multiplier, rounding down to the
|
||||||
if a > 1 && b > 1 && c/b != a {
|
// multiplier/1024 number of bytes.
|
||||||
|
// Returns 0 if overflow is detected.
|
||||||
|
func safeMul(size float64, multiplier uint64) uint64 {
|
||||||
|
n := uint64(size)
|
||||||
|
f := uint64((size - float64(n)) * 1024)
|
||||||
|
if f != 0 && multiplier != 1 {
|
||||||
|
s := n<<10 + f
|
||||||
|
if s < n {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return c
|
|
||||||
|
n = s
|
||||||
|
multiplier >>= 10
|
||||||
|
}
|
||||||
|
|
||||||
|
hi, lo := bits.Mul64(n, multiplier)
|
||||||
|
if hi != 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return lo
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
|
// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
|
||||||
|
@ -203,6 +220,6 @@ func parseSizeInBytes(sizeStr string) uint64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size := cast.ToUint64(sizeStr)
|
size := cast.ToFloat64(sizeStr)
|
||||||
return safeMul(size, multiplier)
|
return safeMul(size, multiplier)
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,9 @@ func TestSizeInBytes(t *testing.T) {
|
||||||
require.EqualValues(t, 12*mb, config.SizeInBytesSafe(c, "size_mb"))
|
require.EqualValues(t, 12*mb, config.SizeInBytesSafe(c, "size_mb"))
|
||||||
require.EqualValues(t, 4*gb, config.SizeInBytesSafe(c, "size_gb"))
|
require.EqualValues(t, 4*gb, config.SizeInBytesSafe(c, "size_gb"))
|
||||||
require.EqualValues(t, 5*tb, config.SizeInBytesSafe(c, "size_tb"))
|
require.EqualValues(t, 5*tb, config.SizeInBytesSafe(c, "size_tb"))
|
||||||
|
require.EqualValues(t, 12, config.SizeInBytesSafe(c, "size_i_am_not_very_clever"))
|
||||||
|
require.EqualValues(t, tb/2, config.SizeInBytesSafe(c, "size_float"))
|
||||||
|
require.EqualValues(t, uint64(14*gb+(gb*123/1000/mb*mb)), config.SizeInBytesSafe(c, "size_float_big"))
|
||||||
require.EqualValues(t, 2048, config.SizeInBytesSafe(c, "size_bytes"))
|
require.EqualValues(t, 2048, config.SizeInBytesSafe(c, "size_bytes"))
|
||||||
require.EqualValues(t, 123456, config.SizeInBytesSafe(c, "size_bytes_no_suffix"))
|
require.EqualValues(t, 123456, config.SizeInBytesSafe(c, "size_bytes_no_suffix"))
|
||||||
})
|
})
|
||||||
|
|
|
@ -54,6 +54,9 @@
|
||||||
"size_mb": "12m",
|
"size_mb": "12m",
|
||||||
"size_gb": "4g",
|
"size_gb": "4g",
|
||||||
"size_tb": "5 TB",
|
"size_tb": "5 TB",
|
||||||
|
"size_float": ".5t",
|
||||||
|
"size_float_big": "14.123 gb",
|
||||||
|
"size_i_am_not_very_clever": "12.12345678",
|
||||||
"size_bytes": "2048b",
|
"size_bytes": "2048b",
|
||||||
"size_bytes_no_suffix": 123456
|
"size_bytes_no_suffix": 123456
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,6 +47,9 @@ sizes:
|
||||||
size_mb: 12m
|
size_mb: 12m
|
||||||
size_gb: 4g
|
size_gb: 4g
|
||||||
size_tb: 5 TB
|
size_tb: 5 TB
|
||||||
|
size_float: .5t
|
||||||
|
size_float_big: 14.123 gb
|
||||||
|
size_i_am_not_very_clever: 12.12345678
|
||||||
size_bytes: 2048b
|
size_bytes: 2048b
|
||||||
size_bytes_no_suffix: 123456
|
size_bytes_no_suffix: 123456
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue