From 7a763ff61e048b04321b6f373b4d4af8dff65edf Mon Sep 17 00:00:00 2001 From: Ganesh Vernekar Date: Tue, 14 Jul 2020 14:59:28 +0530 Subject: [PATCH] Avoid empty mmap files by using .tmp files to write headers Signed-off-by: Ganesh Vernekar --- tsdb/chunks/chunks.go | 29 +++++++++++++++++++++++------ tsdb/fileutil/fileutil.go | 16 +--------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/tsdb/chunks/chunks.go b/tsdb/chunks/chunks.go index acdcc4a17..ffd3e5302 100644 --- a/tsdb/chunks/chunks.go +++ b/tsdb/chunks/chunks.go @@ -220,19 +220,20 @@ func (w *Writer) cut() error { func cutSegmentFile(dirFile *os.File, magicNumber uint32, chunksFormat byte, allocSize int64) (headerSize int, newFile *os.File, seq int, err error) { p, seq, err := nextSequenceFile(dirFile.Name()) if err != nil { - return 0, nil, 0, err + return 0, nil, 0, errors.Wrap(err, "next sequence file") } - f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE, 0666) + ptmp := p + ".tmp" + f, err := os.OpenFile(ptmp, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { - return 0, nil, 0, err + return 0, nil, 0, errors.Wrap(err, "open temp file") } if allocSize > 0 { if err = fileutil.Preallocate(f, allocSize, true); err != nil { - return 0, nil, 0, err + return 0, nil, 0, errors.Wrap(err, "preallocate") } } if err = dirFile.Sync(); err != nil { - return 0, nil, 0, err + return 0, nil, 0, errors.Wrap(err, "sync directory") } // Write header metadata for new file. @@ -242,7 +243,23 @@ func cutSegmentFile(dirFile *os.File, magicNumber uint32, chunksFormat byte, all n, err := f.Write(metab) if err != nil { - return 0, nil, 0, err + return 0, nil, 0, errors.Wrap(err, "write header") + } + if err := f.Close(); err != nil { + return 0, nil, 0, errors.Wrap(err, "close temp file") + } + + if err := fileutil.Rename(ptmp, p); err != nil { + return 0, nil, 0, errors.Wrap(err, "replace file") + } + + f, err = os.OpenFile(p, os.O_WRONLY, 0666) + if err != nil { + return 0, nil, 0, errors.Wrap(err, "open final file") + } + // Skip the header for the further writes. + if _, err := f.Seek(int64(n), 0); err != nil { + return 0, nil, 0, errors.Wrap(err, "seek in final file") } return n, f, seq, nil } diff --git a/tsdb/fileutil/fileutil.go b/tsdb/fileutil/fileutil.go index be9c6f226..00bf63950 100644 --- a/tsdb/fileutil/fileutil.go +++ b/tsdb/fileutil/fileutil.go @@ -125,19 +125,5 @@ func Replace(from, to string) error { } } - if err := os.Rename(from, to); err != nil { - return err - } - - // Directory was renamed; sync parent dir to persist rename. - pdir, err := OpenDir(filepath.Dir(to)) - if err != nil { - return err - } - - if err = pdir.Sync(); err != nil { - pdir.Close() - return err - } - return pdir.Close() + return Rename(from, to) }