diff --git a/cmd/neofs-node/config.go b/cmd/neofs-node/config.go index c36028c05..9c4bbce14 100644 --- a/cmd/neofs-node/config.go +++ b/cmd/neofs-node/config.go @@ -129,6 +129,7 @@ type shardCfg struct { maxObjSize uint64 flushWorkerCount int sizeLimit uint64 + noSync bool } piloramaCfg struct { @@ -219,6 +220,7 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { wc.smallObjectSize = writeCacheCfg.SmallObjectSize() wc.flushWorkerCount = writeCacheCfg.WorkersNumber() wc.sizeLimit = writeCacheCfg.SizeLimit() + wc.noSync = writeCacheCfg.NoSync() } // blobstor with substorages @@ -644,7 +646,7 @@ func (c *cfg) shardOpts() []shardOptsWithID { writecache.WithSmallObjectSize(wcRead.smallObjectSize), writecache.WithFlushWorkersCount(wcRead.flushWorkerCount), writecache.WithMaxCacheSize(wcRead.sizeLimit), - + writecache.WithNoSync(wcRead.noSync), writecache.WithLogger(c.log), ) } diff --git a/cmd/neofs-node/config/engine/config_test.go b/cmd/neofs-node/config/engine/config_test.go index 224447271..c57017fb5 100644 --- a/cmd/neofs-node/config/engine/config_test.go +++ b/cmd/neofs-node/config/engine/config_test.go @@ -68,6 +68,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, pl.MaxBatchSize(), 200) require.Equal(t, false, wc.Enabled()) + require.Equal(t, true, wc.NoSync()) require.Equal(t, "tmp/0/cache", wc.Path()) require.EqualValues(t, 16384, wc.SmallObjectSize()) @@ -113,6 +114,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, 100, pl.MaxBatchSize()) require.Equal(t, true, wc.Enabled()) + require.Equal(t, false, wc.NoSync()) require.Equal(t, "tmp/1/cache", wc.Path()) require.EqualValues(t, 16384, wc.SmallObjectSize()) diff --git a/cmd/neofs-node/config/engine/shard/writecache/config.go b/cmd/neofs-node/config/engine/shard/writecache/config.go index 909d15842..2d7082609 100644 --- a/cmd/neofs-node/config/engine/shard/writecache/config.go +++ b/cmd/neofs-node/config/engine/shard/writecache/config.go @@ -115,6 +115,13 @@ func (x *Config) SizeLimit() uint64 { return SizeLimitDefault } +// NoSync returns the value of "no_sync" config parameter. +// +// Returns false if the value is not a boolean. +func (x *Config) NoSync() bool { + return config.BoolSafe((*config.Config)(x), "no_sync") +} + // BoltDB returns config instance for querying bolt db specific parameters. func (x *Config) BoltDB() *boltdbconfig.Config { return (*boltdbconfig.Config)(x) diff --git a/config/example/node.env b/config/example/node.env index e07b467eb..5516a1835 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -92,6 +92,7 @@ NEOFS_STORAGE_SHARD_0_RESYNC_METABASE=false NEOFS_STORAGE_SHARD_0_MODE=read-only ### Write cache config NEOFS_STORAGE_SHARD_0_WRITECACHE_ENABLED=false +NEOFS_STORAGE_SHARD_0_WRITECACHE_NO_SYNC=true NEOFS_STORAGE_SHARD_0_WRITECACHE_PATH=tmp/0/cache NEOFS_STORAGE_SHARD_0_WRITECACHE_SMALL_OBJECT_SIZE=16384 NEOFS_STORAGE_SHARD_0_WRITECACHE_MAX_OBJECT_SIZE=134217728 diff --git a/config/example/node.json b/config/example/node.json index b7d127588..b871a6c81 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -137,6 +137,7 @@ "resync_metabase": false, "writecache": { "enabled": false, + "no_sync": true, "path": "tmp/0/cache", "small_object_size": 16384, "max_object_size": 134217728, diff --git a/config/example/node.yaml b/config/example/node.yaml index e1a7fbf0e..fdc1a7207 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -157,6 +157,7 @@ storage: writecache: enabled: false + no_sync: true path: tmp/0/cache # write-cache root directory capacity: 3221225472 # approximate write-cache total size, bytes diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index 0e3fd05f5..ef38726fe 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -50,6 +50,8 @@ type options struct { maxBatchSize int // maxBatchDelay is the maximum batch wait time for the small object database. maxBatchDelay time.Duration + // noSync is true iff FSTree allows unsynchronized writes. + noSync bool } // WithLogger sets logger. @@ -130,3 +132,13 @@ func WithMaxBatchDelay(d time.Duration) Option { } } } + +// WithNoSync sets an option to allow returning to caller on PUT before write is persisted. +// Note, that we use this flag for FSTree only and DO NOT use it for a bolt DB because +// we cannot yet properly handle the corrupted database during the startup. This SHOULD NOT +// be relied upon and may be changed in future. +func WithNoSync(noSync bool) Option { + return func(o *options) { + o.noSync = noSync + } +} diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 2a27ec691..4e8475c01 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -56,14 +56,12 @@ func (c *cache) openStore(readOnly bool) error { } } - c.fsTree = &fstree.FSTree{ - Info: fstree.Info{ - Permissions: os.ModePerm, - RootPath: c.path, - }, - Depth: 1, - DirNameLen: 1, - } + c.fsTree = fstree.New( + fstree.WithPath(c.path), + fstree.WithPerm(os.ModePerm), + fstree.WithDepth(1), + fstree.WithDirNameLen(1), + fstree.WithNoSync(c.noSync)) // Write-cache can be opened multiple times during `SetMode`. // flushed map must not be re-created in this case.