forked from TrueCloudLab/frostfs-node
83 lines
1.9 KiB
Go
83 lines
1.9 KiB
Go
package blobtree
|
|
|
|
import (
|
|
"errors"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync/atomic"
|
|
"syscall"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util"
|
|
utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync"
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
)
|
|
|
|
var _ common.Storage = &BlobTree{}
|
|
|
|
type BlobTree struct {
|
|
cfg cfg
|
|
dirLock *utilSync.KeyLocker[string]
|
|
fileLock *utilSync.KeyLocker[string]
|
|
compressor *compression.Config
|
|
dispatcher *rootDispatcher
|
|
suffix atomic.Uint64
|
|
}
|
|
|
|
func New(opts ...Option) *BlobTree {
|
|
b := &BlobTree{
|
|
cfg: cfg{
|
|
targetFileSizeBytes: 4 * 1024 * 1024,
|
|
rootPath: "./",
|
|
depth: 3,
|
|
permissions: 0700,
|
|
initWorkersCount: 1000,
|
|
metrics: &noopMetrics{},
|
|
},
|
|
dirLock: utilSync.NewKeyLocker[string](),
|
|
fileLock: utilSync.NewKeyLocker[string](),
|
|
}
|
|
|
|
for _, opt := range opts {
|
|
opt(&b.cfg)
|
|
}
|
|
|
|
b.dispatcher = newRootDispatcher()
|
|
|
|
return b
|
|
}
|
|
|
|
func (b *BlobTree) getDir(addr oid.Address) string {
|
|
sAddr := addr.Object().EncodeToString() + "." + addr.Container().EncodeToString()
|
|
var sb strings.Builder
|
|
size := int(b.cfg.depth * (directoryLength + 1)) // (character + slash for every level)
|
|
sb.Grow(size)
|
|
|
|
for i := uint64(0); i < b.cfg.depth; i++ {
|
|
if i > 0 {
|
|
sb.WriteRune(filepath.Separator)
|
|
}
|
|
sb.WriteString(sAddr[:directoryLength])
|
|
sAddr = sAddr[directoryLength:]
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
func (b *BlobTree) createDir(dir string, isSystemPath bool) error {
|
|
b.dirLock.Lock(dir)
|
|
defer b.dirLock.Unlock(dir)
|
|
|
|
if !isSystemPath {
|
|
dir = b.getSystemPath(dir)
|
|
}
|
|
if err := util.MkdirAllX(dir, b.cfg.permissions); err != nil {
|
|
if errors.Is(err, syscall.ENOSPC) {
|
|
err = common.ErrNoSpace
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|