lib/fs: remove logging redundant path values in a single error message

This commit is contained in:
Aliaksandr Valialkin 2022-12-03 22:00:20 -08:00
parent 7c3c08d102
commit 4f28513b1a
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
4 changed files with 43 additions and 24 deletions

View file

@ -25,11 +25,38 @@ func MustSyncPath(path string) {
mustSyncPath(path)
}
// WriteFileAndSync writes data to the file at path and then calls fsync on the created file.
//
// The fsync guarantees that the written data survives hardware reset after successful call.
//
// This function may leave the file at the path in inconsistent state on app crash
// in the middle of the write.
// Use WriteFileAtomically if the file at the path must be either written in full
// or not written at all on app crash in the middle of the write.
func WriteFileAndSync(path string, data []byte) error {
f, err := filestream.Create(path, false)
if err != nil {
return err
}
if _, err := f.Write(data); err != nil {
f.MustClose()
// Do not call MustRemoveAll(path), so the user could inpsect
// the file contents during investigation of the issue.
return fmt.Errorf("cannot write %d bytes to %q: %w", len(data), path, err)
}
// Sync and close the file.
f.MustClose()
return nil
}
// WriteFileAtomically atomically writes data to the given file path.
//
// WriteFileAtomically returns only after the file is fully written and synced
// This function returns only after the file is fully written and synced
// to the underlying storage.
//
// This function guarantees that the file at path either fully written or not written at all on app crash
// in the middle of the write.
//
// If the file at path already exists, then the file is overwritten atomically if canOverwrite is true.
// Otherwise error is returned.
func WriteFileAtomically(path string, data []byte, canOverwrite bool) error {
@ -40,26 +67,18 @@ func WriteFileAtomically(path string, data []byte, canOverwrite bool) error {
return fmt.Errorf("cannot create file %q, since it already exists", path)
}
// Write data to a temporary file.
n := atomic.AddUint64(&tmpFileNum, 1)
tmpPath := fmt.Sprintf("%s.tmp.%d", path, n)
f, err := filestream.Create(tmpPath, false)
if err != nil {
return fmt.Errorf("cannot create file %q: %w", tmpPath, err)
}
if _, err := f.Write(data); err != nil {
f.MustClose()
MustRemoveAll(tmpPath)
return fmt.Errorf("cannot write %d bytes to file %q: %w", len(data), tmpPath, err)
if err := WriteFileAndSync(tmpPath, data); err != nil {
return fmt.Errorf("cannot write data to temporary file: %w", err)
}
// Sync and close the file.
f.MustClose()
// Atomically move the file from tmpPath to path.
// Atomically move the temporary file from tmpPath to path.
if err := os.Rename(tmpPath, path); err != nil {
// do not call MustRemoveAll(tmpPath) here, so the user could inspect
// the file contents during investigating the issue.
return fmt.Errorf("cannot move %q to %q: %w", tmpPath, path, err)
// the file contents during investigation of the issue.
return fmt.Errorf("cannot move temporary file %q to %q: %w", tmpPath, path, err)
}
// Sync the containing directory, so the file is guaranteed to appear in the directory.
@ -123,7 +142,7 @@ func RemoveDirContents(dir string) {
}
d, err := os.Open(dir)
if err != nil {
logger.Panicf("FATAL: cannot open dir %q: %s", dir, err)
logger.Panicf("FATAL: cannot open dir: %s", err)
}
defer MustClose(d)
names, err := d.Readdirnames(-1)
@ -185,7 +204,7 @@ func IsEmptyDir(path string) bool {
// See https://stackoverflow.com/a/30708914/274937
f, err := os.Open(path)
if err != nil {
logger.Panicf("FATAL: unexpected error when opening directory %q: %s", path, err)
logger.Panicf("FATAL: cannot open dir: %s", err)
}
_, err = f.Readdirnames(1)
MustClose(f)
@ -230,7 +249,7 @@ var atomicDirRemoveCounter = uint64(time.Now().UnixNano())
func MustRemoveTemporaryDirs(dir string) {
d, err := os.Open(dir)
if err != nil {
logger.Panicf("FATAL: cannot open dir %q: %s", dir, err)
logger.Panicf("FATAL: cannot open dir: %s", err)
}
defer MustClose(d)
fis, err := d.Readdir(-1)
@ -259,7 +278,7 @@ func HardLinkFiles(srcDir, dstDir string) error {
d, err := os.Open(srcDir)
if err != nil {
return fmt.Errorf("cannot open srcDir=%q: %w", srcDir, err)
return fmt.Errorf("cannot open srcDir: %w", err)
}
defer func() {
if err := d.Close(); err != nil {

View file

@ -19,7 +19,7 @@ func mUnmap(data []byte) error {
func mustSyncPath(path string) {
d, err := os.Open(path)
if err != nil {
logger.Panicf("FATAL: cannot open %q: %s", path, err)
logger.Panicf("FATAL: cannot open file for fsync: %s", err)
}
if err := d.Sync(); err != nil {
_ = d.Close()
@ -51,7 +51,7 @@ func createFlockFile(flockFile string) (*os.File, error) {
func mustGetFreeSpace(path string) uint64 {
d, err := os.Open(path)
if err != nil {
logger.Panicf("FATAL: cannot determine free disk space on %q: %s", path, err)
logger.Panicf("FATAL: cannot open dir for determining free disk space: %s", err)
}
defer MustClose(d)

View file

@ -22,7 +22,7 @@ func mUnmap(data []byte) error {
func mustSyncPath(path string) {
d, err := os.Open(path)
if err != nil {
logger.Panicf("FATAL: cannot open %q: %s", path, err)
logger.Panicf("FATAL: cannot open file for fsync: %s", err)
}
if err := d.Sync(); err != nil {
_ = d.Close()
@ -47,7 +47,7 @@ func createFlockFile(flockFile string) (*os.File, error) {
func mustGetFreeSpace(path string) uint64 {
d, err := os.Open(path)
if err != nil {
logger.Panicf("FATAL: cannot determine free disk space on %q: %s", path, err)
logger.Panicf("FATAL: cannot open dir for determining free disk space: %s", err)
}
defer MustClose(d)

View file

@ -89,7 +89,7 @@ func (r *ReaderAt) MustFadviseSequentialRead(prefetch bool) {
func MustOpenReaderAt(path string) *ReaderAt {
f, err := os.Open(path)
if err != nil {
logger.Panicf("FATAL: cannot open file %q for reading: %s", path, err)
logger.Panicf("FATAL: cannot open file for reading: %s", err)
}
var r ReaderAt
r.f = f