diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 151e3560..048935ad 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -1,5 +1,10 @@ package blobstor +import ( + "errors" + "fmt" +) + // Open opens BlobStor. func (b *BlobStor) Open() error { b.log.Debug("opening...") @@ -7,13 +12,23 @@ func (b *BlobStor) Open() error { return nil } +// ErrInitBlobovniczas is returned when blobovnicza initialization fails. +var ErrInitBlobovniczas = errors.New("failure on blobovnicza initialization stage") + // Init initializes internal data structures and system resources. // // If BlobStor is already initialized, no action is taken. +// +// Returns wrapped ErrInitBlobovniczas on blobovnicza tree's initializaiton failure. func (b *BlobStor) Init() error { b.log.Debug("initializing...") - return b.blobovniczas.init() + err := b.blobovniczas.init() + if err != nil { + return fmt.Errorf("%w: %v", ErrInitBlobovniczas, err) + } + + return nil } // Close releases all internal resources of BlobStor. diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 4fc39da8..2698cb07 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -5,10 +5,16 @@ import ( "fmt" "sync" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard" "go.uber.org/zap" ) +type shardInitError struct { + err error + id string +} + // Open opens all StorageEngine's components. func (e *StorageEngine) Open() error { return e.open() @@ -44,30 +50,46 @@ func (e *StorageEngine) open() error { // Init initializes all StorageEngine's components. func (e *StorageEngine) Init() error { - e.mtx.RLock() - defer e.mtx.RUnlock() + e.mtx.Lock() + defer e.mtx.Unlock() var wg sync.WaitGroup - var errCh = make(chan error, len(e.shards)) + var errCh = make(chan shardInitError, len(e.shards)) for id, sh := range e.shards { wg.Add(1) go func(id string, sh *shard.Shard) { defer wg.Done() if err := sh.Init(); err != nil { - errCh <- fmt.Errorf("could not initialize shard %s: %w", id, err) + errCh <- shardInitError{ + err: err, + id: id, + } } }(id, sh.Shard) } wg.Wait() close(errCh) - for err := range errCh { - if err != nil { - return err + for res := range errCh { + if res.err != nil { + if errors.Is(res.err, blobstor.ErrInitBlobovniczas) { + delete(e.shards, res.id) + + e.log.Error("shard initialization failure, skipping", + zap.String("id", res.id), + zap.Error(res.err)) + + continue + } + return fmt.Errorf("could not initialize shard %s: %w", res.id, res.err) } } + if len(e.shards) == 0 { + return errors.New("failed initialization on all shards") + } + return nil }