forked from TrueCloudLab/frostfs-node
[#970] fstree: Move write functions to a separate file
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
9a622a750d
commit
ff488b53a1
2 changed files with 74 additions and 63 deletions
|
@ -360,69 +360,6 @@ func (t *FSTree) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, err
|
|||
return common.PutRes{StorageID: []byte{}}, t.writeData(p, prm.RawData)
|
||||
}
|
||||
|
||||
func (t *FSTree) writeData(p string, data []byte) error {
|
||||
tmpPath := p + "#" + strconv.FormatUint(t.suffix.Add(1), 10)
|
||||
return t.writeAndRename(tmpPath, p, data)
|
||||
}
|
||||
|
||||
// writeAndRename opens tmpPath exclusively, writes data to it and renames it to p.
|
||||
func (t *FSTree) writeAndRename(tmpPath, p string, data []byte) error {
|
||||
if t.fileCounterEnabled {
|
||||
t.fileGuard.Lock(p)
|
||||
defer t.fileGuard.Unlock(p)
|
||||
}
|
||||
|
||||
err := t.writeFile(tmpPath, data)
|
||||
if err != nil {
|
||||
var pe *fs.PathError
|
||||
if errors.As(err, &pe) {
|
||||
switch pe.Err {
|
||||
case syscall.ENOSPC:
|
||||
err = common.ErrNoSpace
|
||||
_ = os.RemoveAll(tmpPath)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if t.fileCounterEnabled {
|
||||
t.fileCounter.Inc()
|
||||
var targetFileExists bool
|
||||
if _, e := os.Stat(p); e == nil {
|
||||
targetFileExists = true
|
||||
}
|
||||
err = os.Rename(tmpPath, p)
|
||||
if err == nil && targetFileExists {
|
||||
t.fileCounter.Dec()
|
||||
}
|
||||
} else {
|
||||
err = os.Rename(tmpPath, p)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *FSTree) writeFlags() int {
|
||||
flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL
|
||||
if t.noSync {
|
||||
return flags
|
||||
}
|
||||
return flags | os.O_SYNC
|
||||
}
|
||||
|
||||
// writeFile writes data to a file with path p.
|
||||
// The code is copied from `os.WriteFile` with minor corrections for flags.
|
||||
func (t *FSTree) writeFile(p string, data []byte) error {
|
||||
f, err := os.OpenFile(p, t.writeFlags(), t.Permissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = f.Write(data)
|
||||
if err1 := f.Close(); err1 != nil && err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Get returns an object from the storage by address.
|
||||
func (t *FSTree) Get(ctx context.Context, prm common.GetPrm) (common.GetRes, error) {
|
||||
var (
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package fstree
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
||||
)
|
||||
|
||||
func (t *FSTree) writeData(p string, data []byte) error {
|
||||
tmpPath := p + "#" + strconv.FormatUint(t.suffix.Add(1), 10)
|
||||
return t.writeAndRename(tmpPath, p, data)
|
||||
}
|
||||
|
||||
// writeAndRename opens tmpPath exclusively, writes data to it and renames it to p.
|
||||
func (t *FSTree) writeAndRename(tmpPath, p string, data []byte) error {
|
||||
if t.fileCounterEnabled {
|
||||
t.fileGuard.Lock(p)
|
||||
defer t.fileGuard.Unlock(p)
|
||||
}
|
||||
|
||||
err := t.writeFile(tmpPath, data)
|
||||
if err != nil {
|
||||
var pe *fs.PathError
|
||||
if errors.As(err, &pe) {
|
||||
switch pe.Err {
|
||||
case syscall.ENOSPC:
|
||||
err = common.ErrNoSpace
|
||||
_ = os.RemoveAll(tmpPath)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if t.fileCounterEnabled {
|
||||
t.fileCounter.Inc()
|
||||
var targetFileExists bool
|
||||
if _, e := os.Stat(p); e == nil {
|
||||
targetFileExists = true
|
||||
}
|
||||
err = os.Rename(tmpPath, p)
|
||||
if err == nil && targetFileExists {
|
||||
t.fileCounter.Dec()
|
||||
}
|
||||
} else {
|
||||
err = os.Rename(tmpPath, p)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *FSTree) writeFlags() int {
|
||||
flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL
|
||||
if t.noSync {
|
||||
return flags
|
||||
}
|
||||
return flags | os.O_SYNC
|
||||
}
|
||||
|
||||
// writeFile writes data to a file with path p.
|
||||
// The code is copied from `os.WriteFile` with minor corrections for flags.
|
||||
func (t *FSTree) writeFile(p string, data []byte) error {
|
||||
f, err := os.OpenFile(p, t.writeFlags(), t.Permissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = f.Write(data)
|
||||
if err1 := f.Close(); err1 != nil && err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
Loading…
Reference in a new issue