forked from TrueCloudLab/frostfs-node
[#2197] pilorama: Close database in degraded mode
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
1d21b1e3e8
commit
cedbd380f2
2 changed files with 90 additions and 6 deletions
|
@ -7,6 +7,8 @@ Changelog for FrostFS Node
|
||||||
### Changed
|
### Changed
|
||||||
### Fixed
|
### Fixed
|
||||||
- Big object removal with non-local parts (#1978)
|
- Big object removal with non-local parts (#1978)
|
||||||
|
- Disable pilorama when moving to degraded mode (#2197)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
### Updated
|
### Updated
|
||||||
- `neo-go` to `v0.100.1`
|
- `neo-go` to `v0.100.1`
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
"github.com/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
"github.com/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
|
||||||
"github.com/TrueCloudLab/frostfs-node/pkg/util"
|
"github.com/TrueCloudLab/frostfs-node/pkg/util"
|
||||||
cidSDK "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
|
cidSDK "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
@ -21,7 +22,7 @@ import (
|
||||||
type boltForest struct {
|
type boltForest struct {
|
||||||
db *bbolt.DB
|
db *bbolt.DB
|
||||||
|
|
||||||
modeMtx sync.Mutex
|
modeMtx sync.RWMutex
|
||||||
mode mode.Mode
|
mode mode.Mode
|
||||||
cfg
|
cfg
|
||||||
}
|
}
|
||||||
|
@ -31,6 +32,12 @@ var (
|
||||||
logBucket = []byte{1}
|
logBucket = []byte{1}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrDegradedMode is returned when pilorama is in a degraded mode.
|
||||||
|
var ErrDegradedMode = logicerr.New("pilorama is in a degraded mode")
|
||||||
|
|
||||||
|
// ErrReadOnlyMode is returned when pilorama is in a read-only mode.
|
||||||
|
var ErrReadOnlyMode = logicerr.New("pilorama is in a read-only mode")
|
||||||
|
|
||||||
// NewBoltForest returns storage wrapper for storing operations on CRDT trees.
|
// NewBoltForest returns storage wrapper for storing operations on CRDT trees.
|
||||||
//
|
//
|
||||||
// Each tree is stored in a separate bucket by `CID + treeID` key.
|
// Each tree is stored in a separate bucket by `CID + treeID` key.
|
||||||
|
@ -71,12 +78,9 @@ func (t *boltForest) SetMode(m mode.Mode) error {
|
||||||
if t.mode == m {
|
if t.mode == m {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if t.mode.ReadOnly() == m.ReadOnly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := t.Close()
|
err := t.Close()
|
||||||
if err == nil {
|
if err == nil && !m.NoMetabase() {
|
||||||
if err = t.Open(m.ReadOnly()); err == nil {
|
if err = t.Open(m.ReadOnly()); err == nil {
|
||||||
err = t.Init()
|
err = t.Init()
|
||||||
}
|
}
|
||||||
|
@ -110,7 +114,7 @@ func (t *boltForest) Open(readOnly bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (t *boltForest) Init() error {
|
func (t *boltForest) Init() error {
|
||||||
if t.db.IsReadOnly() {
|
if t.mode.NoMetabase() || t.db.IsReadOnly() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return t.db.Update(func(tx *bbolt.Tx) error {
|
return t.db.Update(func(tx *bbolt.Tx) error {
|
||||||
|
@ -138,6 +142,15 @@ func (t *boltForest) TreeMove(d CIDDescriptor, treeID string, m *Move) (*LogMove
|
||||||
return nil, ErrInvalidCIDDescriptor
|
return nil, ErrInvalidCIDDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return nil, ErrDegradedMode
|
||||||
|
} else if t.mode.ReadOnly() {
|
||||||
|
return nil, ErrReadOnlyMode
|
||||||
|
}
|
||||||
|
|
||||||
var lm LogMove
|
var lm LogMove
|
||||||
lm.Move = *m
|
lm.Move = *m
|
||||||
return &lm, t.db.Batch(func(tx *bbolt.Tx) error {
|
return &lm, t.db.Batch(func(tx *bbolt.Tx) error {
|
||||||
|
@ -156,6 +169,13 @@ func (t *boltForest) TreeMove(d CIDDescriptor, treeID string, m *Move) (*LogMove
|
||||||
|
|
||||||
// TreeExists implements the Forest interface.
|
// TreeExists implements the Forest interface.
|
||||||
func (t *boltForest) TreeExists(cid cidSDK.ID, treeID string) (bool, error) {
|
func (t *boltForest) TreeExists(cid cidSDK.ID, treeID string) (bool, error) {
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return false, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
|
|
||||||
err := t.db.View(func(tx *bbolt.Tx) error {
|
err := t.db.View(func(tx *bbolt.Tx) error {
|
||||||
|
@ -176,6 +196,15 @@ func (t *boltForest) TreeAddByPath(d CIDDescriptor, treeID string, attr string,
|
||||||
return nil, ErrNotPathAttribute
|
return nil, ErrNotPathAttribute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return nil, ErrDegradedMode
|
||||||
|
} else if t.mode.ReadOnly() {
|
||||||
|
return nil, ErrReadOnlyMode
|
||||||
|
}
|
||||||
|
|
||||||
var lm []LogMove
|
var lm []LogMove
|
||||||
var key [17]byte
|
var key [17]byte
|
||||||
|
|
||||||
|
@ -260,6 +289,15 @@ func (t *boltForest) TreeApply(d CIDDescriptor, treeID string, m *Move, backgrou
|
||||||
return ErrInvalidCIDDescriptor
|
return ErrInvalidCIDDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return ErrDegradedMode
|
||||||
|
} else if t.mode.ReadOnly() {
|
||||||
|
return ErrReadOnlyMode
|
||||||
|
}
|
||||||
|
|
||||||
if backgroundSync {
|
if backgroundSync {
|
||||||
var seen bool
|
var seen bool
|
||||||
err := t.db.View(func(tx *bbolt.Tx) error {
|
err := t.db.View(func(tx *bbolt.Tx) error {
|
||||||
|
@ -508,6 +546,13 @@ func (t *boltForest) TreeGetByPath(cid cidSDK.ID, treeID string, attr string, pa
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return nil, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
var nodes []Node
|
var nodes []Node
|
||||||
|
|
||||||
return nodes, t.db.View(func(tx *bbolt.Tx) error {
|
return nodes, t.db.View(func(tx *bbolt.Tx) error {
|
||||||
|
@ -555,6 +600,13 @@ func (t *boltForest) TreeGetByPath(cid cidSDK.ID, treeID string, attr string, pa
|
||||||
|
|
||||||
// TreeGetMeta implements the forest interface.
|
// TreeGetMeta implements the forest interface.
|
||||||
func (t *boltForest) TreeGetMeta(cid cidSDK.ID, treeID string, nodeID Node) (Meta, Node, error) {
|
func (t *boltForest) TreeGetMeta(cid cidSDK.ID, treeID string, nodeID Node) (Meta, Node, error) {
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return Meta{}, 0, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
key := parentKey(make([]byte, 9), nodeID)
|
key := parentKey(make([]byte, 9), nodeID)
|
||||||
|
|
||||||
var m Meta
|
var m Meta
|
||||||
|
@ -578,6 +630,13 @@ func (t *boltForest) TreeGetMeta(cid cidSDK.ID, treeID string, nodeID Node) (Met
|
||||||
|
|
||||||
// TreeGetChildren implements the Forest interface.
|
// TreeGetChildren implements the Forest interface.
|
||||||
func (t *boltForest) TreeGetChildren(cid cidSDK.ID, treeID string, nodeID Node) ([]uint64, error) {
|
func (t *boltForest) TreeGetChildren(cid cidSDK.ID, treeID string, nodeID Node) ([]uint64, error) {
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return nil, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
key := make([]byte, 9)
|
key := make([]byte, 9)
|
||||||
key[0] = 'c'
|
key[0] = 'c'
|
||||||
binary.LittleEndian.PutUint64(key[1:], nodeID)
|
binary.LittleEndian.PutUint64(key[1:], nodeID)
|
||||||
|
@ -603,6 +662,13 @@ func (t *boltForest) TreeGetChildren(cid cidSDK.ID, treeID string, nodeID Node)
|
||||||
|
|
||||||
// TreeList implements the Forest interface.
|
// TreeList implements the Forest interface.
|
||||||
func (t *boltForest) TreeList(cid cidSDK.ID) ([]string, error) {
|
func (t *boltForest) TreeList(cid cidSDK.ID) ([]string, error) {
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return nil, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
var ids []string
|
var ids []string
|
||||||
cidRaw := []byte(cid.EncodeToString())
|
cidRaw := []byte(cid.EncodeToString())
|
||||||
cidLen := len(cidRaw)
|
cidLen := len(cidRaw)
|
||||||
|
@ -628,6 +694,13 @@ func (t *boltForest) TreeList(cid cidSDK.ID) ([]string, error) {
|
||||||
|
|
||||||
// TreeGetOpLog implements the pilorama.Forest interface.
|
// TreeGetOpLog implements the pilorama.Forest interface.
|
||||||
func (t *boltForest) TreeGetOpLog(cid cidSDK.ID, treeID string, height uint64) (Move, error) {
|
func (t *boltForest) TreeGetOpLog(cid cidSDK.ID, treeID string, height uint64) (Move, error) {
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return Move{}, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
key := make([]byte, 8)
|
key := make([]byte, 8)
|
||||||
binary.BigEndian.PutUint64(key, height)
|
binary.BigEndian.PutUint64(key, height)
|
||||||
|
|
||||||
|
@ -651,6 +724,15 @@ func (t *boltForest) TreeGetOpLog(cid cidSDK.ID, treeID string, height uint64) (
|
||||||
|
|
||||||
// TreeDrop implements the pilorama.Forest interface.
|
// TreeDrop implements the pilorama.Forest interface.
|
||||||
func (t *boltForest) TreeDrop(cid cidSDK.ID, treeID string) error {
|
func (t *boltForest) TreeDrop(cid cidSDK.ID, treeID string) error {
|
||||||
|
t.modeMtx.RLock()
|
||||||
|
defer t.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if t.mode.NoMetabase() {
|
||||||
|
return ErrDegradedMode
|
||||||
|
} else if t.mode.ReadOnly() {
|
||||||
|
return ErrReadOnlyMode
|
||||||
|
}
|
||||||
|
|
||||||
return t.db.Batch(func(tx *bbolt.Tx) error {
|
return t.db.Batch(func(tx *bbolt.Tx) error {
|
||||||
if treeID == "" {
|
if treeID == "" {
|
||||||
c := tx.Cursor()
|
c := tx.Cursor()
|
||||||
|
|
Loading…
Reference in a new issue