Skip to content
This repository was archived by the owner on Aug 13, 2019. It is now read-only.

Commit 34f13c2

Browse files
committed
cleanup tmp file if file renaming failed
Signed-off-by: zhulongcheng <[email protected]>
1 parent 4b3a5ac commit 34f13c2

File tree

7 files changed

+75
-42
lines changed

7 files changed

+75
-42
lines changed

block.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/prometheus/tsdb/chunkenc"
3030
"github.com/prometheus/tsdb/chunks"
3131
tsdb_errors "github.com/prometheus/tsdb/errors"
32+
"github.com/prometheus/tsdb/fileutil"
3233
"github.com/prometheus/tsdb/index"
3334
"github.com/prometheus/tsdb/labels"
3435
)
@@ -230,12 +231,17 @@ func readMetaFile(dir string) (*BlockMeta, error) {
230231
return &m, nil
231232
}
232233

233-
func writeMetaFile(dir string, meta *BlockMeta) error {
234+
func writeMetaFile(logger log.Logger, dir string, meta *BlockMeta) error {
234235
meta.Version = 1
235236

236237
// Make any changes to the file appear atomic.
237238
path := filepath.Join(dir, metaFilename)
238239
tmp := path + ".tmp"
240+
defer func() {
241+
if err := os.RemoveAll(tmp); err != nil {
242+
level.Error(logger).Log("msg", "remove tmp file", "err", err.Error())
243+
}
244+
}()
239245

240246
f, err := os.Create(tmp)
241247
if err != nil {
@@ -246,7 +252,6 @@ func writeMetaFile(dir string, meta *BlockMeta) error {
246252
enc.SetIndent("", "\t")
247253

248254
var merr tsdb_errors.MultiError
249-
250255
if merr.Add(enc.Encode(meta)); merr.Err() != nil {
251256
merr.Add(f.Close())
252257
return merr.Err()
@@ -259,7 +264,12 @@ func writeMetaFile(dir string, meta *BlockMeta) error {
259264
if err := f.Close(); err != nil {
260265
return err
261266
}
262-
return renameFile(tmp, path)
267+
268+
if err := fileutil.Replace(tmp, path); err != nil {
269+
return err
270+
}
271+
272+
return nil
263273
}
264274

265275
// Block represents a directory of time series data covering a continuous time range.
@@ -278,6 +288,8 @@ type Block struct {
278288
chunkr ChunkReader
279289
indexr IndexReader
280290
tombstones TombstoneReader
291+
292+
logger log.Logger
281293
}
282294

283295
// OpenBlock opens the block in the directory. It can be passed a chunk pool, which is used
@@ -322,7 +334,7 @@ func OpenBlock(logger log.Logger, dir string, pool chunkenc.Pool) (pb *Block, er
322334
// that would be the logical place for a block size to be calculated.
323335
bs := blockSize(cr, ir, tsr)
324336
meta.Stats.NumBytes = bs
325-
err = writeMetaFile(dir, meta)
337+
err = writeMetaFile(logger, dir, meta)
326338
if err != nil {
327339
level.Warn(logger).Log("msg", "couldn't write the meta file for the block size", "block", dir, "err", err)
328340
}
@@ -334,6 +346,7 @@ func OpenBlock(logger log.Logger, dir string, pool chunkenc.Pool) (pb *Block, er
334346
indexr: ir,
335347
tombstones: tr,
336348
symbolTableSize: ir.SymbolTableSize(),
349+
logger: logger,
337350
}
338351
return pb, nil
339352
}
@@ -429,7 +442,7 @@ func (pb *Block) GetSymbolTableSize() uint64 {
429442

430443
func (pb *Block) setCompactionFailed() error {
431444
pb.meta.Compaction.Failed = true
432-
return writeMetaFile(pb.dir, &pb.meta)
445+
return writeMetaFile(pb.logger, pb.dir, &pb.meta)
433446
}
434447

435448
type blockIndexReader struct {
@@ -553,10 +566,10 @@ Outer:
553566
pb.tombstones = stones
554567
pb.meta.Stats.NumTombstones = pb.tombstones.Total()
555568

556-
if err := writeTombstoneFile(pb.dir, pb.tombstones); err != nil {
569+
if err := writeTombstoneFile(pb.logger, pb.dir, pb.tombstones); err != nil {
557570
return err
558571
}
559-
return writeMetaFile(pb.dir, &pb.meta)
572+
return writeMetaFile(pb.logger, pb.dir, &pb.meta)
560573
}
561574

562575
// CleanTombstones will remove the tombstones and rewrite the block (only if there are any tombstones).

block_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestBlockMetaMustNeverBeVersion2(t *testing.T) {
3939
testutil.Ok(t, os.RemoveAll(dir))
4040
}()
4141

42-
testutil.Ok(t, writeMetaFile(dir, &BlockMeta{}))
42+
testutil.Ok(t, writeMetaFile(log.NewNopLogger(), dir, &BlockMeta{}))
4343

4444
meta, err := readMetaFile(dir)
4545
testutil.Ok(t, err)

compact.go

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ func (c *LeveledCompactor) Compact(dest string, dirs []string, open []*Block) (u
426426
if meta.Stats.NumSamples == 0 {
427427
for _, b := range bs {
428428
b.meta.Compaction.Deletable = true
429-
if err = writeMetaFile(b.dir, &b.meta); err != nil {
429+
if err = writeMetaFile(c.logger, b.dir, &b.meta); err != nil {
430430
level.Error(c.logger).Log(
431431
"msg", "Failed to write 'Deletable' to meta file after compaction",
432432
"ulid", b.meta.ULID,
@@ -609,12 +609,12 @@ func (c *LeveledCompactor) write(dest string, meta *BlockMeta, blocks ...BlockRe
609609
return nil
610610
}
611611

612-
if err = writeMetaFile(tmp, meta); err != nil {
612+
if err = writeMetaFile(c.logger, tmp, meta); err != nil {
613613
return errors.Wrap(err, "write merged meta")
614614
}
615615

616616
// Create an empty tombstones file.
617-
if err := writeTombstoneFile(tmp, newMemTombstones()); err != nil {
617+
if err := writeTombstoneFile(c.logger, tmp, newMemTombstones()); err != nil {
618618
return errors.Wrap(err, "write new tombstones file")
619619
}
620620

@@ -639,7 +639,7 @@ func (c *LeveledCompactor) write(dest string, meta *BlockMeta, blocks ...BlockRe
639639
df = nil
640640

641641
// Block successfully written, make visible and remove old ones.
642-
if err := renameFile(tmp, dir); err != nil {
642+
if err := fileutil.Replace(tmp, dir); err != nil {
643643
return errors.Wrap(err, "rename block dir")
644644
}
645645

@@ -1013,24 +1013,3 @@ func (c *compactionMerger) Err() error {
10131013
func (c *compactionMerger) At() (labels.Labels, []chunks.Meta, Intervals) {
10141014
return c.l, c.c, c.intervals
10151015
}
1016-
1017-
func renameFile(from, to string) error {
1018-
if err := os.RemoveAll(to); err != nil {
1019-
return err
1020-
}
1021-
if err := os.Rename(from, to); err != nil {
1022-
return err
1023-
}
1024-
1025-
// Directory was renamed; sync parent dir to persist rename.
1026-
pdir, err := fileutil.OpenDir(filepath.Dir(to))
1027-
if err != nil {
1028-
return err
1029-
}
1030-
1031-
if err = pdir.Sync(); err != nil {
1032-
pdir.Close()
1033-
return err
1034-
}
1035-
return pdir.Close()
1036-
}

repair.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"github.com/go-kit/kit/log"
2424
"github.com/go-kit/kit/log/level"
2525
"github.com/pkg/errors"
26+
tsdb_errors "github.com/prometheus/tsdb/errors"
27+
"github.com/prometheus/tsdb/fileutil"
2628
)
2729

2830
// repairBadIndexVersion repairs an issue in index and meta.json persistence introduced in
@@ -38,6 +40,16 @@ func repairBadIndexVersion(logger log.Logger, dir string) error {
3840
wrapErr := func(err error, d string) error {
3941
return errors.Wrapf(err, "block dir: %q", d)
4042
}
43+
44+
tmpFiles := make([]string, 0, len(dir))
45+
defer func() {
46+
for _, tmp := range tmpFiles {
47+
if err := os.RemoveAll(tmp); err != nil {
48+
level.Error(logger).Log("msg", "remove tmp file", "err", err.Error())
49+
}
50+
}
51+
}()
52+
4153
for _, d := range dirs {
4254
meta, err := readBogusMetaFile(d)
4355
if err != nil {
@@ -63,32 +75,41 @@ func repairBadIndexVersion(logger log.Logger, dir string) error {
6375
if err != nil {
6476
return wrapErr(err, d)
6577
}
78+
tmpFiles = append(tmpFiles, repl.Name())
79+
6680
broken, err := os.Open(filepath.Join(d, indexFilename))
6781
if err != nil {
6882
return wrapErr(err, d)
6983
}
7084
if _, err := io.Copy(repl, broken); err != nil {
7185
return wrapErr(err, d)
7286
}
87+
88+
var merr tsdb_errors.MultiError
89+
7390
// Set the 5th byte to 2 to indicate the correct file format version.
7491
if _, err := repl.WriteAt([]byte{2}, 4); err != nil {
75-
return wrapErr(err, d)
92+
merr.Add(wrapErr(err, d))
93+
merr.Add(wrapErr(repl.Close(), d))
94+
return merr.Err()
7695
}
7796
if err := repl.Sync(); err != nil {
78-
return wrapErr(err, d)
97+
merr.Add(wrapErr(err, d))
98+
merr.Add(wrapErr(repl.Close(), d))
99+
return merr.Err()
79100
}
80101
if err := repl.Close(); err != nil {
81102
return wrapErr(err, d)
82103
}
83104
if err := broken.Close(); err != nil {
84105
return wrapErr(err, d)
85106
}
86-
if err := renameFile(repl.Name(), broken.Name()); err != nil {
107+
if err := fileutil.Replace(repl.Name(), broken.Name()); err != nil {
87108
return wrapErr(err, d)
88109
}
89110
// Reset version of meta.json to 1.
90111
meta.Version = 1
91-
if err := writeMetaFile(d, meta); err != nil {
112+
if err := writeMetaFile(logger, d, meta); err != nil {
92113
return wrapErr(err, d)
93114
}
94115
}

tombstones.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ import (
2222
"path/filepath"
2323
"sync"
2424

25+
"github.com/go-kit/kit/log"
26+
"github.com/go-kit/kit/log/level"
2527
"github.com/pkg/errors"
2628
"github.com/prometheus/tsdb/encoding"
2729
tsdb_errors "github.com/prometheus/tsdb/errors"
30+
"github.com/prometheus/tsdb/fileutil"
2831
)
2932

3033
const tombstoneFilename = "tombstones"
@@ -51,7 +54,7 @@ type TombstoneReader interface {
5154
Close() error
5255
}
5356

54-
func writeTombstoneFile(dir string, tr TombstoneReader) error {
57+
func writeTombstoneFile(logger log.Logger, dir string, tr TombstoneReader) error {
5558
path := filepath.Join(dir, tombstoneFilename)
5659
tmp := path + ".tmp"
5760
hash := newCRC32()
@@ -62,7 +65,12 @@ func writeTombstoneFile(dir string, tr TombstoneReader) error {
6265
}
6366
defer func() {
6467
if f != nil {
65-
f.Close()
68+
if err := f.Close(); err != nil {
69+
level.Error(logger).Log("msg", "close tmp file", "err", err.Error())
70+
}
71+
}
72+
if err := os.RemoveAll(tmp); err != nil {
73+
level.Error(logger).Log("msg", "remove tmp file", "err", err.Error())
6674
}
6775
}()
6876

@@ -111,7 +119,11 @@ func writeTombstoneFile(dir string, tr TombstoneReader) error {
111119
return err
112120
}
113121
f = nil
114-
return renameFile(tmp, path)
122+
123+
if err := fileutil.Replace(tmp, path); err != nil {
124+
return err
125+
}
126+
return nil
115127
}
116128

117129
// Stone holds the information on the posting and time-range

tombstones_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"testing"
2222
"time"
2323

24+
"github.com/go-kit/kit/log"
2425
"github.com/prometheus/tsdb/testutil"
2526
)
2627

@@ -46,7 +47,7 @@ func TestWriteAndReadbackTombStones(t *testing.T) {
4647
stones.addInterval(ref, dranges...)
4748
}
4849

49-
testutil.Ok(t, writeTombstoneFile(tmpdir, stones))
50+
testutil.Ok(t, writeTombstoneFile(log.NewNopLogger(), tmpdir, stones))
5051

5152
restr, _, err := readTombstones(tmpdir)
5253
testutil.Ok(t, err)

wal.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,12 @@ func (w *SegmentWAL) Truncate(mint int64, keep func(uint64) bool) error {
338338
if err != nil {
339339
return errors.Wrap(err, "create compaction segment")
340340
}
341+
defer func() {
342+
if err := os.RemoveAll(f.Name()); err != nil {
343+
level.Error(w.logger).Log("msg", "remove tmp file", "err", err.Error())
344+
}
345+
}()
346+
341347
var (
342348
csf = newSegmentFile(f)
343349
crc32 = newCRC32()
@@ -389,9 +395,10 @@ func (w *SegmentWAL) Truncate(mint int64, keep func(uint64) bool) error {
389395
csf.Close()
390396

391397
candidates[0].Close() // need close before remove on platform windows
392-
if err := renameFile(csf.Name(), candidates[0].Name()); err != nil {
398+
if err := fileutil.Replace(csf.Name(), candidates[0].Name()); err != nil {
393399
return errors.Wrap(err, "rename compaction segment")
394400
}
401+
395402
for _, f := range candidates[1:] {
396403
f.Close() // need close before remove on platform windows
397404
if err := os.RemoveAll(f.Name()); err != nil {

0 commit comments

Comments
 (0)