forked from TrueCloudLab/frostfs-node
[#1337] blobovniczatree: Add rebuild by fill percent
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
007827255e
commit
d508da8397
9 changed files with 470 additions and 119 deletions
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -59,7 +60,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm
|
|||
b.log.Debug(logs.BlobovniczaTreeCompletedPreviousRebuildSuccess)
|
||||
|
||||
b.log.Debug(logs.BlobovniczaTreeCollectingDBToRebuild)
|
||||
dbsToMigrate, err := b.getDBsToRebuild(ctx)
|
||||
dbsToMigrate, err := b.getDBsToRebuild(ctx, prm.Action)
|
||||
if err != nil {
|
||||
b.log.Warn(logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err))
|
||||
success = false
|
||||
|
@ -93,7 +94,33 @@ func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common.
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) {
|
||||
func (b *Blobovniczas) getDBsToRebuild(ctx context.Context, action common.RebuildAction) ([]string, error) {
|
||||
schemaChange := make(map[string]struct{})
|
||||
fillPercent := make(map[string]struct{})
|
||||
var err error
|
||||
if action.SchemaChange {
|
||||
schemaChange, err = b.selectDBsDoNotMatchSchema(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if action.FillPercent {
|
||||
fillPercent, err = b.selectDBsDoNotMatchFillPercent(ctx, action.FillPercentValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for k := range fillPercent {
|
||||
schemaChange[k] = struct{}{}
|
||||
}
|
||||
result := make([]string, 0, len(schemaChange))
|
||||
for db := range schemaChange {
|
||||
result = append(result, db)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (b *Blobovniczas) selectDBsDoNotMatchSchema(ctx context.Context) (map[string]struct{}, error) {
|
||||
dbsToMigrate := make(map[string]struct{})
|
||||
if err := b.iterateExistingDBPaths(ctx, func(s string) (bool, error) {
|
||||
dbsToMigrate[s] = struct{}{}
|
||||
|
@ -107,13 +134,69 @@ func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) {
|
|||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]string, 0, len(dbsToMigrate))
|
||||
for db := range dbsToMigrate {
|
||||
result = append(result, db)
|
||||
return dbsToMigrate, nil
|
||||
}
|
||||
|
||||
func (b *Blobovniczas) selectDBsDoNotMatchFillPercent(ctx context.Context, target int) (map[string]struct{}, error) {
|
||||
if target <= 0 || target > 100 {
|
||||
return nil, fmt.Errorf("invalid fill percent value %d: must be (0; 100]", target)
|
||||
}
|
||||
result := make(map[string]struct{})
|
||||
if err := b.iterateDeepest(ctx, oid.Address{}, func(lvlPath string) (bool, error) {
|
||||
dir := filepath.Join(b.rootPath, lvlPath)
|
||||
entries, err := os.ReadDir(dir)
|
||||
if os.IsNotExist(err) { // non initialized tree
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hasDBs := false
|
||||
// db with maxIdx could be an active, so it should not be rebuilded
|
||||
var maxIdx uint64
|
||||
for _, e := range entries {
|
||||
if e.IsDir() || strings.HasSuffix(e.Name(), rebuildSuffix) {
|
||||
continue
|
||||
}
|
||||
hasDBs = true
|
||||
maxIdx = max(u64FromHexString(e.Name()), maxIdx)
|
||||
}
|
||||
if !hasDBs {
|
||||
return false, nil
|
||||
}
|
||||
for _, e := range entries {
|
||||
if e.IsDir() || strings.HasSuffix(e.Name(), rebuildSuffix) {
|
||||
continue
|
||||
}
|
||||
if u64FromHexString(e.Name()) == maxIdx {
|
||||
continue
|
||||
}
|
||||
path := filepath.Join(lvlPath, e.Name())
|
||||
resettlementRequired, err := b.fillPercentIsLow(path, target)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if resettlementRequired {
|
||||
result[path] = struct{}{}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (b *Blobovniczas) fillPercentIsLow(path string, target int) (bool, error) {
|
||||
shDB := b.getBlobovnicza(path)
|
||||
blz, err := shDB.Open()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer shDB.Close()
|
||||
return blz.FillPercent() < target, nil
|
||||
}
|
||||
|
||||
func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) {
|
||||
shDB := b.getBlobovnicza(path)
|
||||
blz, err := shDB.Open()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue