2023-08-24 17:44:09 +03:00
|
|
|
package blobtree
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression"
|
|
|
|
"golang.org/x/sync/errgroup"
|
|
|
|
)
|
|
|
|
|
|
|
|
var Type = "blobtree"
|
|
|
|
|
|
|
|
func (b *BlobTree) Open(readOnly bool) error {
|
|
|
|
b.cfg.readOnly = readOnly
|
2023-10-04 14:35:13 +03:00
|
|
|
b.cfg.metrics.SetMode(readOnly)
|
2023-08-24 17:44:09 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) Init() error {
|
|
|
|
if err := b.createDir(b.cfg.rootPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var eg errgroup.Group
|
|
|
|
eg.SetLimit(b.cfg.initWorkersCount)
|
|
|
|
eg.Go(func() error {
|
|
|
|
return b.initDir(&eg, b.cfg.rootPath, 0)
|
|
|
|
})
|
|
|
|
return eg.Wait()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) initDir(eg *errgroup.Group, dir string, depth uint64) error {
|
|
|
|
entities, err := os.ReadDir(dir)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, entity := range entities {
|
|
|
|
if depth < b.cfg.depth && entity.IsDir() {
|
|
|
|
eg.Go(func() error {
|
|
|
|
return b.initDir(eg, filepath.Join(dir, entity.Name()), depth+1)
|
|
|
|
})
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if depth != b.cfg.depth {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if b.isTempFile(entity.Name()) {
|
|
|
|
if err = os.Remove(filepath.Join(dir, entity.Name())); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
idx, err := b.parseIdx(entity.Name())
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
b.dispatcher.Init(dir, idx)
|
2023-10-04 14:35:13 +03:00
|
|
|
b.cfg.metrics.IncFilesCount()
|
2023-08-24 17:44:09 +03:00
|
|
|
|
|
|
|
stat, err := os.Stat(filepath.Join(dir, entity.Name()))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if stat.Size() < int64(b.cfg.targetFileSizeBytes) {
|
|
|
|
b.dispatcher.ReturnIdx(dir, idx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) isTempFile(name string) bool {
|
|
|
|
return strings.Contains(name, tempFileSymbols)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) parseIdx(name string) (uint64, error) {
|
2023-10-09 10:13:21 +03:00
|
|
|
return strconv.ParseUint(strings.TrimSuffix(name, dataExtension), 16, 64)
|
2023-08-24 17:44:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) Close() error {
|
2023-10-04 14:35:13 +03:00
|
|
|
b.cfg.metrics.Close()
|
2023-08-24 17:44:09 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) Type() string { return Type }
|
|
|
|
func (b *BlobTree) Path() string { return b.cfg.rootPath }
|
|
|
|
|
|
|
|
func (b *BlobTree) SetCompressor(cc *compression.Config) {
|
|
|
|
b.compressor = cc
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) Compressor() *compression.Config {
|
|
|
|
return b.compressor
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BlobTree) SetReportErrorFunc(_ func(string, error)) {}
|
2023-10-04 14:35:13 +03:00
|
|
|
|
|
|
|
func (b *BlobTree) SetParentID(parentID string) {
|
|
|
|
b.cfg.metrics.SetParentID(parentID)
|
|
|
|
}
|