package shard import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "go.uber.org/zap" ) // ErrReadOnlyMode is returned when it is impossible to apply operation // that changes shard's memory due to the "read-only" shard's mode. var ErrReadOnlyMode = logicerr.New("shard is in read-only mode") // ErrDegradedMode is returned when operation requiring metabase is executed in degraded mode. var ErrDegradedMode = logicerr.New("shard is in degraded mode") // SetMode sets mode of the shard. // // Returns any error encountered that did not allow // setting shard mode. func (s *Shard) SetMode(ctx context.Context, m mode.Mode) error { unlock := s.lockExclusive() defer unlock() return s.setMode(ctx, m) } func (s *Shard) setMode(ctx context.Context, m mode.Mode) error { s.log.Info(ctx, logs.ShardSettingShardMode, zap.Stringer("old_mode", s.info.Mode), zap.Stringer("new_mode", m)) components := []interface { SetMode(context.Context, mode.Mode) error }{ s.metaBase, s.blobStor, } if s.hasWriteCache() { components = append(components, s.writeCache) } if s.pilorama != nil { components = append(components, s.pilorama) } // The usual flow of the requests (pilorama is independent): // writecache -> blobstor -> metabase // For mode.ReadOnly and mode.Degraded the order is: // writecache -> blobstor -> metabase // For mode.ReadWrite it is the opposite: // metabase -> blobstor -> writecache if m != mode.ReadWrite { if s.hasWriteCache() { components[0], components[2] = components[2], components[0] } else { components[0], components[1] = components[1], components[0] } } if !m.Disabled() { for i := range components { if err := components[i].SetMode(ctx, m); err != nil { return err } } } s.info.Mode = m s.metricsWriter.SetMode(s.info.Mode) s.log.Info(ctx, logs.ShardShardModeSetSuccessfully, zap.Stringer("mode", s.info.Mode)) return nil } // GetMode returns mode of the shard. func (s *Shard) GetMode() mode.Mode { s.m.RLock() defer s.m.RUnlock() return s.info.Mode }