lib/fs: add Must prefix to CopyDirectory and CopyFile functions

Callers of these functions log the returned error and then exit.
Let's log the error with the call stack inside the function itself.
This simplifies the code at callers' side, while leaving the same
level of debuggability in case of errors.
This commit is contained in:
Aliaksandr Valialkin 2023-04-13 23:02:55 -07:00
parent 780abc3b3b
commit 809fbaeaac
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
4 changed files with 18 additions and 39 deletions

View file

@ -300,11 +300,11 @@ func MustSymlinkRelative(srcPath, dstPath string) {
} }
} }
// CopyDirectory copies all the files in srcPath to dstPath. // MustCopyDirectory copies all the files in srcPath to dstPath.
func CopyDirectory(srcPath, dstPath string) error { func MustCopyDirectory(srcPath, dstPath string) {
des, err := os.ReadDir(srcPath) des, err := os.ReadDir(srcPath)
if err != nil { if err != nil {
return err logger.Panicf("FATAL: cannot read srcDir: %s", err)
} }
MustMkdirIfNotExist(dstPath) MustMkdirIfNotExist(dstPath)
for _, de := range des { for _, de := range des {
@ -314,31 +314,27 @@ func CopyDirectory(srcPath, dstPath string) error {
} }
src := filepath.Join(srcPath, de.Name()) src := filepath.Join(srcPath, de.Name())
dst := filepath.Join(dstPath, de.Name()) dst := filepath.Join(dstPath, de.Name())
if err := CopyFile(src, dst); err != nil { MustCopyFile(src, dst)
return err
}
} }
MustSyncPath(dstPath) MustSyncPath(dstPath)
return nil
} }
// CopyFile copies the file from srcPath to dstPath. // MustCopyFile copies the file from srcPath to dstPath.
func CopyFile(srcPath, dstPath string) error { func MustCopyFile(srcPath, dstPath string) {
src, err := os.Open(srcPath) src, err := os.Open(srcPath)
if err != nil { if err != nil {
return err logger.Panicf("FATAL: cannot open srcPath: %s", err)
} }
defer MustClose(src) defer MustClose(src)
dst, err := os.Create(dstPath) dst, err := os.Create(dstPath)
if err != nil { if err != nil {
return err logger.Panicf("FATAL: cannot create dstPath: %s", err)
} }
defer MustClose(dst) defer MustClose(dst)
if _, err := io.Copy(dst, src); err != nil { if _, err := io.Copy(dst, src); err != nil {
return err logger.Panicf("FATAL: cannot copy %q to %q: %s", srcPath, dstPath, err)
} }
MustSyncPath(dstPath) MustSyncPath(dstPath)
return nil
} }
// ReadFullData reads len(data) bytes from r. // ReadFullData reads len(data) bytes from r.

View file

@ -1849,10 +1849,10 @@ func mustCloseParts(pws []*partWrapper) {
} }
} }
// CreateSnapshotAt creates pt snapshot at the given smallPath and bigPath dirs. // MustCreateSnapshotAt creates pt snapshot at the given smallPath and bigPath dirs.
// //
// Snapshot is created using linux hard links, so it is usually created very quickly. // Snapshot is created using linux hard links, so it is usually created very quickly.
func (pt *partition) CreateSnapshotAt(smallPath, bigPath string) error { func (pt *partition) MustCreateSnapshotAt(smallPath, bigPath string) {
logger.Infof("creating partition snapshot of %q and %q...", pt.smallPartsPath, pt.bigPartsPath) logger.Infof("creating partition snapshot of %q and %q...", pt.smallPartsPath, pt.bigPartsPath)
startTime := time.Now() startTime := time.Now()
@ -1877,22 +1877,15 @@ func (pt *partition) CreateSnapshotAt(smallPath, bigPath string) error {
// Create a file with part names at smallPath // Create a file with part names at smallPath
mustWritePartNames(pwsSmall, pwsBig, smallPath) mustWritePartNames(pwsSmall, pwsBig, smallPath)
if err := pt.createSnapshot(pt.smallPartsPath, smallPath, pwsSmall); err != nil { pt.mustCreateSnapshot(pt.smallPartsPath, smallPath, pwsSmall)
return fmt.Errorf("cannot create snapshot for %q: %w", pt.smallPartsPath, err) pt.mustCreateSnapshot(pt.bigPartsPath, bigPath, pwsBig)
}
if err := pt.createSnapshot(pt.bigPartsPath, bigPath, pwsBig); err != nil {
return fmt.Errorf("cannot create snapshot for %q: %w", pt.bigPartsPath, err)
}
logger.Infof("created partition snapshot of %q and %q at %q and %q in %.3f seconds", logger.Infof("created partition snapshot of %q and %q at %q and %q in %.3f seconds",
pt.smallPartsPath, pt.bigPartsPath, smallPath, bigPath, time.Since(startTime).Seconds()) pt.smallPartsPath, pt.bigPartsPath, smallPath, bigPath, time.Since(startTime).Seconds())
return nil
} }
// createSnapshot creates a snapshot from srcDir to dstDir. // mustCreateSnapshot creates a snapshot from srcDir to dstDir.
// func (pt *partition) mustCreateSnapshot(srcDir, dstDir string, pws []*partWrapper) {
// The caller is responsible for deleting dstDir if createSnapshot() returns error.
func (pt *partition) createSnapshot(srcDir, dstDir string, pws []*partWrapper) error {
// Make hardlinks for pws at dstDir // Make hardlinks for pws at dstDir
for _, pw := range pws { for _, pw := range pws {
srcPartPath := pw.p.path srcPartPath := pw.p.path
@ -1907,16 +1900,12 @@ func (pt *partition) createSnapshot(srcDir, dstDir string, pws []*partWrapper) e
srcPath := filepath.Join(srcDir, appliedRetentionFilename) srcPath := filepath.Join(srcDir, appliedRetentionFilename)
if fs.IsPathExist(srcPath) { if fs.IsPathExist(srcPath) {
dstPath := filepath.Join(dstDir, filepath.Base(srcPath)) dstPath := filepath.Join(dstDir, filepath.Base(srcPath))
if err := fs.CopyFile(srcPath, dstPath); err != nil { fs.MustCopyFile(srcPath, dstPath)
return fmt.Errorf("cannot copy %q to %q: %w", srcPath, dstPath, err)
}
} }
fs.MustSyncPath(dstDir) fs.MustSyncPath(dstDir)
parentDir := filepath.Dir(dstDir) parentDir := filepath.Dir(dstDir)
fs.MustSyncPath(parentDir) fs.MustSyncPath(parentDir)
return nil
} }
type partNamesJSON struct { type partNamesJSON struct {

View file

@ -341,9 +341,7 @@ func (s *Storage) CreateSnapshot(deadline uint64) (string, error) {
srcMetadataDir := filepath.Join(srcDir, metadataDirname) srcMetadataDir := filepath.Join(srcDir, metadataDirname)
dstMetadataDir := filepath.Join(dstDir, metadataDirname) dstMetadataDir := filepath.Join(dstDir, metadataDirname)
if err := fs.CopyDirectory(srcMetadataDir, dstMetadataDir); err != nil { fs.MustCopyDirectory(srcMetadataDir, dstMetadataDir)
return "", fmt.Errorf("cannot copy metadata: %w", err)
}
idbSnapshot := filepath.Join(srcDir, indexdbDirname, snapshotsDirname, snapshotName) idbSnapshot := filepath.Join(srcDir, indexdbDirname, snapshotsDirname, snapshotName)
idb := s.idb() idb := s.idb()

View file

@ -158,11 +158,7 @@ func (tb *table) CreateSnapshot(snapshotName string, deadline uint64) (string, s
smallPath := filepath.Join(dstSmallDir, ptw.pt.name) smallPath := filepath.Join(dstSmallDir, ptw.pt.name)
bigPath := filepath.Join(dstBigDir, ptw.pt.name) bigPath := filepath.Join(dstBigDir, ptw.pt.name)
if err := ptw.pt.CreateSnapshotAt(smallPath, bigPath); err != nil { ptw.pt.MustCreateSnapshotAt(smallPath, bigPath)
fs.MustRemoveAll(dstSmallDir)
fs.MustRemoveAll(dstBigDir)
return "", "", fmt.Errorf("cannot create snapshot for partition %q in %q: %w", ptw.pt.name, tb.path, err)
}
} }
fs.MustSyncPath(dstSmallDir) fs.MustSyncPath(dstSmallDir)