[#1201] writecache: Cancel background flush without lock
All checks were successful
DCO action / DCO (pull_request) Successful in 3m14s
Vulncheck / Vulncheck (pull_request) Successful in 5m14s
Tests and linters / gopls check (pull_request) Successful in 6m26s
Tests and linters / Lint (pull_request) Successful in 7m29s
Tests and linters / Staticcheck (pull_request) Successful in 7m22s
Build / Build Components (1.22) (pull_request) Successful in 7m55s
Build / Build Components (1.21) (pull_request) Successful in 8m1s
Pre-commit hooks / Pre-commit (pull_request) Successful in 12m8s
Tests and linters / Tests with -race (pull_request) Successful in 12m41s
Tests and linters / Tests (1.21) (pull_request) Successful in 13m3s
Tests and linters / Tests (1.22) (pull_request) Successful in 13m32s

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2024-06-26 11:19:33 +03:00
parent 81070ada01
commit 4c7ff159ec

View file

@ -4,6 +4,7 @@ import (
"context"
"os"
"sync"
"sync/atomic"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr"
@ -30,7 +31,7 @@ type cache struct {
// flushCh is a channel with objects to flush.
flushCh chan objectInfo
// cancel is cancel function, protected by modeMtx in Close.
cancel func()
cancel atomic.Value
// wg is a wait group for flush workers.
wg sync.WaitGroup
// store contains underlying database.
@ -54,7 +55,10 @@ const (
defaultMaxCacheSize = 1 << 30 // 1 GiB
)
var defaultBucket = []byte{0}
var (
defaultBucket = []byte{0}
dummyCanceler context.CancelFunc = func() {}
)
// New creates new writecache instance.
func New(opts ...Option) Cache {
@ -114,20 +118,19 @@ func (c *cache) Open(_ context.Context, mod mode.Mode) error {
func (c *cache) Init() error {
c.metrics.SetMode(mode.ConvertToComponentModeDegraded(c.mode))
ctx, cancel := context.WithCancel(context.Background())
c.cancel = cancel
c.cancel.Store(cancel)
c.runFlushLoop(ctx)
return nil
}
// Close closes db connection and stops services. Executes ObjectCounters.FlushAndClose op.
func (c *cache) Close() error {
if cancelValue := c.cancel.Swap(dummyCanceler); cancelValue != nil {
cancelValue.(context.CancelFunc)()
}
// We cannot lock mutex for the whole operation duration
// because it is taken by some background workers, so `wg.Wait()` is done without modeMtx.
c.modeMtx.Lock()
if c.cancel != nil {
c.cancel()
c.cancel = nil
}
c.mode = mode.DegradedReadOnly // prevent new operations from being processed
c.modeMtx.Unlock()