Simplify temp file handling (#260)

This commit is contained in:
Neil O'Toole 2023-06-18 00:44:01 -06:00 committed by GitHub
parent 2ba633fc2a
commit 2abf7222ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 33 deletions

View File

@ -866,35 +866,29 @@ func (d *database) Close() error {
// NewScratchSource returns a new scratch src. Effectively this
// function creates a new sqlite db file in the temp dir, and
// src points at this file. The returned clnup func closes that
// db file and deletes it.
// src points at this file. The returned clnup func will delete
// the file.
func NewScratchSource(ctx context.Context, name string) (src *source.Source, clnup func() error, err error) {
log := lg.FromContext(ctx)
name = stringz.SanitizeAlphaNumeric(name, '_')
_, f, cleanFn, err := source.TempDirFile(name + ".sqlite")
dir, file, err := source.TempDirFile(name + ".sqlite")
if err != nil {
return nil, cleanFn, err
return nil, nil, err
}
// REVISIT: This mechanism is janky: should we be keeping the file open?
// Probably not.
lg.WarnIfCloseError(log, "Close scratch file", f)
log.Debug("Created sqlite3 scratchdb data file", lga.Path, f.Name())
log.Debug("Created sqlite3 scratchdb data file", lga.Path, file)
src = &source.Source{
Type: Type,
Handle: source.ScratchHandle,
Location: Prefix + f.Name(),
Location: Prefix + file,
}
fn := func() error {
log.Debug("Deleting sqlite3 scratchdb data file", lga.Src, src, lga.Path, f.Name())
if cleanFn != nil {
cleanErr := cleanFn()
if cleanErr != nil {
log.Warn("Error cleaning scratch source", lga.Err, cleanErr)
}
log.Debug("Deleting sqlite3 scratchdb file", lga.Src, src, lga.Path, file)
rmErr := errz.Err(os.RemoveAll(dir))
if rmErr != nil {
log.Warn("Delete sqlite3 scratchdb file", lga.Err, rmErr)
}
return nil
}

View File

@ -515,31 +515,30 @@ func httpURL(s string) (u *url.URL, ok bool) {
}
// TempDirFile creates a new temporary file in a new temp dir,
// opens the file for reading and writing, and returns the resulting *os.File,
// as well as the parent dir.
// It is the caller's responsibility to close the file and remove the temp
// dir, which the returned cleanFn encapsulates.
func TempDirFile(filename string) (dir string, f *os.File, cleanFn func() error, err error) {
// opens the file for reading and writing, and then closes it.
// It's probably unnecessary to go through the ceremony of
// opening and closing the file, but maybe it's better to fail early.
// It is the caller's responsibility to remove the file and/or dir
// if desired.
func TempDirFile(filename string) (dir, file string, err error) {
dir, err = os.MkdirTemp("", "sq_")
if err != nil {
return "", nil, nil, errz.Err(err)
return "", "", errz.Err(err)
}
name := filepath.Join(dir, filename)
f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600)
if err != nil {
file = filepath.Join(dir, filename)
var f *os.File
if f, err = os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600); err != nil {
// Silently delete the temp dir
_ = os.RemoveAll(dir)
return "", nil, nil, errz.Err(err)
return "", "", errz.Err(err)
}
cleanFn = func() error {
closeErr := f.Close()
removeErr := os.RemoveAll(dir)
return errz.Append(closeErr, removeErr)
if err = f.Close(); err != nil {
// Silently delete the temp dir
_ = os.RemoveAll(dir)
return "", "", errz.Wrap(err, "close temp file")
}
return dir, f, cleanFn, nil
return dir, file, nil
}