forked from TrueCloudLab/frostfs-node
96 lines
2 KiB
Go
96 lines
2 KiB
Go
package blobtree
|
|
|
|
import (
|
|
"context"
|
|
"encoding/binary"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
|
)
|
|
|
|
func (b *BlobTree) Iterate(_ context.Context, prm common.IteratePrm) (common.IterateRes, error) {
|
|
return common.IterateRes{}, b.iterateDir(b.cfg.rootPath, 0, prm)
|
|
}
|
|
|
|
func (b *BlobTree) iterateDir(dir string, depth uint64, prm common.IteratePrm) error {
|
|
entities, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
if prm.IgnoreErrors {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
for _, entity := range entities {
|
|
if depth < b.cfg.depth && entity.IsDir() {
|
|
err := b.iterateDir(filepath.Join(dir, entity.Name()), depth+1, prm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if depth != b.cfg.depth {
|
|
continue
|
|
}
|
|
if b.isTempFile(entity.Name()) {
|
|
continue
|
|
}
|
|
idx, err := b.parseIdx(entity.Name())
|
|
if err != nil {
|
|
continue
|
|
}
|
|
path := b.getFilePath(dir, idx)
|
|
err = b.iterateRecords(idx, path, prm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *BlobTree) iterateRecords(idx uint64, path string, prm common.IteratePrm) error {
|
|
b.fileLock.RLock(path)
|
|
defer b.fileLock.RUnlock(path)
|
|
|
|
records, err := b.readFileContent(path)
|
|
if err != nil {
|
|
if prm.IgnoreErrors {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
for _, record := range records {
|
|
if prm.LazyHandler != nil {
|
|
if err = prm.LazyHandler(record.Address, func() ([]byte, error) {
|
|
return record.Data, nil
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
|
|
record.Data, err = b.compressor.Decompress(record.Data)
|
|
if err != nil {
|
|
if prm.IgnoreErrors {
|
|
if prm.ErrorHandler != nil {
|
|
return prm.ErrorHandler(record.Address, err)
|
|
}
|
|
continue
|
|
}
|
|
return err
|
|
}
|
|
|
|
storageID := make([]byte, storageIDLength)
|
|
binary.LittleEndian.PutUint64(storageID, idx)
|
|
err = prm.Handler(common.IterationElement{
|
|
Address: record.Address,
|
|
ObjectData: record.Data,
|
|
StorageID: storageID,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|