forked from TrueCloudLab/frostfs-node
[#1523] neofs-node: Refactor configuration
1. Move compression parameters to the `shard` section. 2. Allow to use multiple sub-storage components in the blobstor. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
13cdbde2e2
commit
26b4a258e0
37 changed files with 595 additions and 419 deletions
|
@ -15,6 +15,8 @@ import (
|
|||
contractsconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/contracts"
|
||||
engineconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine"
|
||||
shardconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard"
|
||||
blobovniczaconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/blobstor/blobovnicza"
|
||||
fstreeconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/blobstor/fstree"
|
||||
loggerconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/logger"
|
||||
metricsconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/metrics"
|
||||
nodeconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/node"
|
||||
|
@ -22,6 +24,8 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/pkg/core/container"
|
||||
netmapCore "github.com/nspcc-dev/neofs-node/pkg/core/netmap"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/blobovniczatree"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
|
||||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/pilorama"
|
||||
|
@ -47,6 +51,7 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/util/state"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/version"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
|
@ -418,7 +423,7 @@ func initShardOptions(c *cfg) {
|
|||
}
|
||||
|
||||
blobStorCfg := sc.BlobStor()
|
||||
blobovniczaCfg := blobStorCfg.Blobovnicza()
|
||||
storages := blobStorCfg.Storages()
|
||||
metabaseCfg := sc.Metabase()
|
||||
gcCfg := sc.GC()
|
||||
|
||||
|
@ -426,19 +431,47 @@ func initShardOptions(c *cfg) {
|
|||
|
||||
piloramaCfg := sc.Pilorama()
|
||||
if config.BoolSafe(c.appCfg.Sub("tree"), "enabled") {
|
||||
piloramaPath := piloramaCfg.Path()
|
||||
if piloramaPath == "" {
|
||||
piloramaPath = filepath.Join(blobStorCfg.Path(), "pilorama.db")
|
||||
}
|
||||
|
||||
piloramaOpts = []pilorama.Option{
|
||||
pilorama.WithPath(piloramaPath),
|
||||
pilorama.WithPath(piloramaCfg.Path()),
|
||||
pilorama.WithPerm(piloramaCfg.Perm()),
|
||||
pilorama.WithNoSync(piloramaCfg.NoSync()),
|
||||
pilorama.WithMaxBatchSize(piloramaCfg.MaxBatchSize()),
|
||||
pilorama.WithMaxBatchDelay(piloramaCfg.MaxBatchDelay())}
|
||||
}
|
||||
|
||||
var st []blobstor.SubStorage
|
||||
for i := range storages {
|
||||
switch storages[i].Type() {
|
||||
case "blobovniczas":
|
||||
sub := blobovniczaconfig.From((*config.Config)(storages[i]))
|
||||
lim := sc.SmallSizeLimit()
|
||||
st = append(st, blobstor.SubStorage{
|
||||
Storage: blobovniczatree.NewBlobovniczaTree(
|
||||
blobovniczatree.WithLogger(c.log),
|
||||
blobovniczatree.WithRootPath(storages[i].Path()),
|
||||
blobovniczatree.WithPermissions(storages[i].Perm()),
|
||||
blobovniczatree.WithBlobovniczaSize(sub.Size()),
|
||||
blobovniczatree.WithBlobovniczaShallowDepth(sub.ShallowDepth()),
|
||||
blobovniczatree.WithBlobovniczaShallowWidth(sub.ShallowWidth()),
|
||||
blobovniczatree.WithOpenedCacheSize(sub.OpenedCacheSize())),
|
||||
Policy: func(_ *objectSDK.Object, data []byte) bool {
|
||||
return uint64(len(data)) < lim
|
||||
},
|
||||
})
|
||||
case "fstree":
|
||||
sub := fstreeconfig.From((*config.Config)(storages[i]))
|
||||
st = append(st, blobstor.SubStorage{
|
||||
Storage: fstree.New(
|
||||
fstree.WithPath(storages[i].Path()),
|
||||
fstree.WithPerm(storages[i].Perm()),
|
||||
fstree.WithDepth(sub.Depth())),
|
||||
Policy: func(_ *objectSDK.Object, data []byte) bool {
|
||||
return true
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
metaPath := metabaseCfg.Path()
|
||||
metaPerm := metabaseCfg.BoltDB().Perm()
|
||||
fatalOnErr(util.MkdirAllX(filepath.Dir(metaPath), metaPerm))
|
||||
|
@ -453,15 +486,9 @@ func initShardOptions(c *cfg) {
|
|||
shard.WithRefillMetabase(sc.RefillMetabase()),
|
||||
shard.WithMode(sc.Mode()),
|
||||
shard.WithBlobStorOptions(
|
||||
blobstor.WithRootPath(blobStorCfg.Path()),
|
||||
blobstor.WithCompressObjects(blobStorCfg.Compress()),
|
||||
blobstor.WithRootPerm(blobStorCfg.Perm()),
|
||||
blobstor.WithShallowDepth(blobStorCfg.ShallowDepth()),
|
||||
blobstor.WithSmallSizeLimit(blobStorCfg.SmallSizeLimit()),
|
||||
blobstor.WithBlobovniczaSize(blobovniczaCfg.Size()),
|
||||
blobstor.WithBlobovniczaShallowDepth(blobovniczaCfg.ShallowDepth()),
|
||||
blobstor.WithBlobovniczaShallowWidth(blobovniczaCfg.ShallowWidth()),
|
||||
blobstor.WithBlobovniczaOpenedCacheSize(blobovniczaCfg.OpenedCacheSize()),
|
||||
blobstor.WithCompressObjects(sc.Compress()),
|
||||
blobstor.WithUncompressableContentTypes(sc.UncompressableContentTypes()),
|
||||
blobstor.WithStorages(st),
|
||||
blobstor.WithLogger(c.log),
|
||||
),
|
||||
shard.WithMetaBaseOptions(
|
||||
|
|
|
@ -39,7 +39,7 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config))
|
|||
// must have different paths, so if it is missing, the shard is not here.
|
||||
// At the same time checking for "blobstor" section doesn't work proper
|
||||
// with configuration via the environment.
|
||||
if (*config.Config)(sc).Value("blobstor.path") == nil {
|
||||
if (*config.Config)(sc).Value("metabase.path") == nil {
|
||||
break
|
||||
}
|
||||
(*config.Config)(sc).SetDefault(def)
|
||||
|
|
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config"
|
||||
engineconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine"
|
||||
shardconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard"
|
||||
blobovniczaconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/blobstor/blobovnicza"
|
||||
fstreeconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/blobstor/fstree"
|
||||
piloramaconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/pilorama"
|
||||
configtest "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/test"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode"
|
||||
|
@ -53,7 +55,7 @@ func TestEngineSection(t *testing.T) {
|
|||
wc := sc.WriteCache()
|
||||
meta := sc.Metabase()
|
||||
blob := sc.BlobStor()
|
||||
blz := blob.Blobovnicza()
|
||||
ss := blob.Storages()
|
||||
pl := sc.Pilorama()
|
||||
gc := sc.GC()
|
||||
|
||||
|
@ -79,18 +81,23 @@ func TestEngineSection(t *testing.T) {
|
|||
require.Equal(t, 100, meta.BoltDB().MaxBatchSize())
|
||||
require.Equal(t, 10*time.Millisecond, meta.BoltDB().MaxBatchDelay())
|
||||
|
||||
require.Equal(t, "tmp/0/blob", blob.Path())
|
||||
require.EqualValues(t, 0644, blob.Perm())
|
||||
require.Equal(t, true, blob.Compress())
|
||||
require.Equal(t, []string{"audio/*", "video/*"}, blob.UncompressableContentTypes())
|
||||
require.EqualValues(t, 5, blob.ShallowDepth())
|
||||
require.EqualValues(t, 102400, blob.SmallSizeLimit())
|
||||
require.Equal(t, true, sc.Compress())
|
||||
require.Equal(t, []string{"audio/*", "video/*"}, sc.UncompressableContentTypes())
|
||||
require.EqualValues(t, 102400, sc.SmallSizeLimit())
|
||||
|
||||
require.Equal(t, 2, len(ss))
|
||||
blz := blobovniczaconfig.From((*config.Config)(ss[0]))
|
||||
require.Equal(t, "tmp/0/blob/blobovnicza", ss[0].Path())
|
||||
require.EqualValues(t, 0644, blz.BoltDB().Perm())
|
||||
require.EqualValues(t, 4194304, blz.Size())
|
||||
require.EqualValues(t, 1, blz.ShallowDepth())
|
||||
require.EqualValues(t, 4, blz.ShallowWidth())
|
||||
require.EqualValues(t, 50, blz.OpenedCacheSize())
|
||||
|
||||
require.Equal(t, "tmp/0/blob", ss[1].Path())
|
||||
require.EqualValues(t, 0644, ss[1].Perm())
|
||||
require.EqualValues(t, 5, fstreeconfig.From((*config.Config)(ss[1])).Depth())
|
||||
|
||||
require.EqualValues(t, 150, gc.RemoverBatchSize())
|
||||
require.Equal(t, 2*time.Minute, gc.RemoverSleepInterval())
|
||||
|
||||
|
@ -117,18 +124,23 @@ func TestEngineSection(t *testing.T) {
|
|||
require.Equal(t, 200, meta.BoltDB().MaxBatchSize())
|
||||
require.Equal(t, 20*time.Millisecond, meta.BoltDB().MaxBatchDelay())
|
||||
|
||||
require.Equal(t, "tmp/1/blob", blob.Path())
|
||||
require.EqualValues(t, 0644, blob.Perm())
|
||||
require.Equal(t, false, blob.Compress())
|
||||
require.Equal(t, []string(nil), blob.UncompressableContentTypes())
|
||||
require.EqualValues(t, 5, blob.ShallowDepth())
|
||||
require.EqualValues(t, 102400, blob.SmallSizeLimit())
|
||||
require.Equal(t, false, sc.Compress())
|
||||
require.Equal(t, []string(nil), sc.UncompressableContentTypes())
|
||||
require.EqualValues(t, 102400, sc.SmallSizeLimit())
|
||||
|
||||
require.Equal(t, 2, len(ss))
|
||||
|
||||
blz := blobovniczaconfig.From((*config.Config)(ss[0]))
|
||||
require.Equal(t, "tmp/1/blob/blobovnicza", ss[0].Path())
|
||||
require.EqualValues(t, 4194304, blz.Size())
|
||||
require.EqualValues(t, 1, blz.ShallowDepth())
|
||||
require.EqualValues(t, 4, blz.ShallowWidth())
|
||||
require.EqualValues(t, 50, blz.OpenedCacheSize())
|
||||
|
||||
require.Equal(t, "tmp/1/blob", ss[1].Path())
|
||||
require.EqualValues(t, 0644, ss[1].Perm())
|
||||
require.EqualValues(t, 5, fstreeconfig.From((*config.Config)(ss[1])).Depth())
|
||||
|
||||
require.EqualValues(t, 200, gc.RemoverBatchSize())
|
||||
require.Equal(t, 5*time.Minute, gc.RemoverSleepInterval())
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@ func From(c *config.Config) *Config {
|
|||
return (*Config)(c)
|
||||
}
|
||||
|
||||
// Type returns the storage type.
|
||||
func (x *Config) Type() string {
|
||||
return "blobovnicza"
|
||||
}
|
||||
|
||||
// Size returns the value of "size" config parameter.
|
||||
//
|
||||
// Returns SizeDefault if the value is not a positive number.
|
||||
|
|
|
@ -1,122 +1,36 @@
|
|||
package blobstorconfig
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"strconv"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config"
|
||||
blobovniczaconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/blobstor/blobovnicza"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard/blobstor/storage"
|
||||
)
|
||||
|
||||
// Config is a wrapper over the config section
|
||||
// which provides access to BlobStor configurations.
|
||||
type Config config.Config
|
||||
|
||||
// config defaults
|
||||
const (
|
||||
// PermDefault are default permission bits for BlobStor data.
|
||||
PermDefault = 0660
|
||||
|
||||
// ShallowDepthDefault is a default shallow dir depth.
|
||||
ShallowDepthDefault = 4
|
||||
|
||||
// SmallSizeLimitDefault is a default limit of small objects payload in bytes.
|
||||
SmallSizeLimitDefault = 1 << 20
|
||||
)
|
||||
|
||||
// From wraps config section into Config.
|
||||
func From(c *config.Config) *Config {
|
||||
return (*Config)(c)
|
||||
}
|
||||
|
||||
// Path returns the value of "path" config parameter.
|
||||
//
|
||||
// Panics if the value is not a non-empty string.
|
||||
func (x *Config) Path() string {
|
||||
p := config.String(
|
||||
(*config.Config)(x),
|
||||
"path",
|
||||
)
|
||||
|
||||
if p == "" {
|
||||
panic("blobstor path not set")
|
||||
// Storages returns the value of storage subcomponents.
|
||||
func (x *Config) Storages() []*storage.Config {
|
||||
var ss []*storage.Config
|
||||
for i := 0; ; i++ {
|
||||
typ := config.String(
|
||||
(*config.Config)(x),
|
||||
strconv.Itoa(i)+".type")
|
||||
switch typ {
|
||||
case "":
|
||||
return ss
|
||||
case "fstree", "blobovnicza":
|
||||
sub := storage.From((*config.Config)(x).Sub(strconv.Itoa(i)))
|
||||
ss = append(ss, sub)
|
||||
default:
|
||||
panic("invalid type")
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// Perm returns the value of "perm" config parameter as a fs.FileMode.
|
||||
//
|
||||
// Returns PermDefault if the value is not a non-zero number.
|
||||
func (x *Config) Perm() fs.FileMode {
|
||||
p := config.UintSafe(
|
||||
(*config.Config)(x),
|
||||
"perm",
|
||||
)
|
||||
|
||||
if p == 0 {
|
||||
p = PermDefault
|
||||
}
|
||||
|
||||
return fs.FileMode(p)
|
||||
}
|
||||
|
||||
// ShallowDepth returns the value of "depth" config parameter.
|
||||
//
|
||||
// Returns ShallowDepthDefault if the value is out of
|
||||
// [1:fstree.MaxDepth] range.
|
||||
func (x *Config) ShallowDepth() int {
|
||||
d := config.IntSafe(
|
||||
(*config.Config)(x),
|
||||
"depth",
|
||||
)
|
||||
|
||||
if d >= 1 && d <= fstree.MaxDepth {
|
||||
return int(d)
|
||||
}
|
||||
|
||||
return ShallowDepthDefault
|
||||
}
|
||||
|
||||
// Compress returns the value of "compress" config parameter.
|
||||
//
|
||||
// Returns false if the value is not a valid bool.
|
||||
func (x *Config) Compress() bool {
|
||||
return config.BoolSafe(
|
||||
(*config.Config)(x),
|
||||
"compress",
|
||||
)
|
||||
}
|
||||
|
||||
// UncompressableContentTypes returns the value of "compress_skip_content_types" config parameter.
|
||||
//
|
||||
// Returns nil if a the value is missing or is invalid.
|
||||
func (x *Config) UncompressableContentTypes() []string {
|
||||
return config.StringSliceSafe(
|
||||
(*config.Config)(x),
|
||||
"compression_exclude_content_types")
|
||||
}
|
||||
|
||||
// SmallSizeLimit returns the value of "small_object_size" config parameter.
|
||||
//
|
||||
// Returns SmallSizeLimitDefault if the value is not a positive number.
|
||||
func (x *Config) SmallSizeLimit() uint64 {
|
||||
l := config.SizeInBytesSafe(
|
||||
(*config.Config)(x),
|
||||
"small_object_size",
|
||||
)
|
||||
|
||||
if l > 0 {
|
||||
return l
|
||||
}
|
||||
|
||||
return SmallSizeLimitDefault
|
||||
}
|
||||
|
||||
// Blobovnicza returns "blobovnicza" subsection as a blobovniczaconfig.Config.
|
||||
func (x *Config) Blobovnicza() *blobovniczaconfig.Config {
|
||||
return blobovniczaconfig.From(
|
||||
(*config.Config)(x).
|
||||
Sub("blobovnicza"),
|
||||
)
|
||||
}
|
||||
|
|
40
cmd/neofs-node/config/engine/shard/blobstor/fstree/config.go
Normal file
40
cmd/neofs-node/config/engine/shard/blobstor/fstree/config.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package fstree
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
|
||||
)
|
||||
|
||||
// Config is a wrapper over the config section
|
||||
// which provides access to Blobovnicza configurations.
|
||||
type Config config.Config
|
||||
|
||||
// DepthDefault is a default shallow dir depth.
|
||||
const DepthDefault = 4
|
||||
|
||||
// From wraps config section into Config.
|
||||
func From(c *config.Config) *Config {
|
||||
return (*Config)(c)
|
||||
}
|
||||
|
||||
// Type returns the storage type.
|
||||
func (x *Config) Type() string {
|
||||
return "fstree"
|
||||
}
|
||||
|
||||
// Depth returns the value of "depth" config parameter.
|
||||
//
|
||||
// Returns DepthDefault if the value is out of
|
||||
// [1:fstree.MaxDepth] range.
|
||||
func (x *Config) Depth() int {
|
||||
d := config.IntSafe(
|
||||
(*config.Config)(x),
|
||||
"depth",
|
||||
)
|
||||
|
||||
if d >= 1 && d <= fstree.MaxDepth {
|
||||
return int(d)
|
||||
}
|
||||
|
||||
return DepthDefault
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
|
||||
"github.com/nspcc-dev/neofs-node/cmd/neofs-node/config"
|
||||
)
|
||||
|
||||
type Config config.Config
|
||||
|
||||
// PermDefault are default permission bits for BlobStor data.
|
||||
const PermDefault = 0660
|
||||
|
||||
func From(x *config.Config) *Config {
|
||||
return (*Config)(x)
|
||||
}
|
||||
|
||||
// Type returns storage type.
|
||||
func (x *Config) Type() string {
|
||||
return config.String(
|
||||
(*config.Config)(x),
|
||||
"type")
|
||||
}
|
||||
|
||||
// Path returns the value of "path" config parameter.
|
||||
//
|
||||
// Panics if the value is not a non-empty string.
|
||||
func (x *Config) Path() string {
|
||||
p := config.String(
|
||||
(*config.Config)(x),
|
||||
"path",
|
||||
)
|
||||
|
||||
if p == "" {
|
||||
panic("blobstor path not set")
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// Perm returns the value of "perm" config parameter as a fs.FileMode.
|
||||
//
|
||||
// Returns PermDefault if the value is not a non-zero number.
|
||||
func (x *Config) Perm() fs.FileMode {
|
||||
p := config.UintSafe(
|
||||
(*config.Config)(x),
|
||||
"perm",
|
||||
)
|
||||
|
||||
if p == 0 {
|
||||
p = PermDefault
|
||||
}
|
||||
|
||||
return fs.FileMode(p)
|
||||
}
|
|
@ -16,11 +16,49 @@ import (
|
|||
// which provides access to Shard configurations.
|
||||
type Config config.Config
|
||||
|
||||
// SmallSizeLimitDefault is a default limit of small objects payload in bytes.
|
||||
const SmallSizeLimitDefault = 1 << 20
|
||||
|
||||
// From wraps config section into Config.
|
||||
func From(c *config.Config) *Config {
|
||||
return (*Config)(c)
|
||||
}
|
||||
|
||||
// Compress returns the value of "compress" config parameter.
|
||||
//
|
||||
// Returns false if the value is not a valid bool.
|
||||
func (x *Config) Compress() bool {
|
||||
return config.BoolSafe(
|
||||
(*config.Config)(x),
|
||||
"compress",
|
||||
)
|
||||
}
|
||||
|
||||
// UncompressableContentTypes returns the value of "compress_skip_content_types" config parameter.
|
||||
//
|
||||
// Returns nil if a the value is missing or is invalid.
|
||||
func (x *Config) UncompressableContentTypes() []string {
|
||||
return config.StringSliceSafe(
|
||||
(*config.Config)(x),
|
||||
"compression_exclude_content_types")
|
||||
}
|
||||
|
||||
// SmallSizeLimit returns the value of "small_object_size" config parameter.
|
||||
//
|
||||
// Returns SmallSizeLimitDefault if the value is not a positive number.
|
||||
func (x *Config) SmallSizeLimit() uint64 {
|
||||
l := config.SizeInBytesSafe(
|
||||
(*config.Config)(x),
|
||||
"small_object_size",
|
||||
)
|
||||
|
||||
if l > 0 {
|
||||
return l
|
||||
}
|
||||
|
||||
return SmallSizeLimitDefault
|
||||
}
|
||||
|
||||
// BlobStor returns "blobstor" subsection as a blobstorconfig.Config.
|
||||
func (x *Config) BlobStor() *blobstorconfig.Config {
|
||||
return blobstorconfig.From(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue