Skip to content

Commit 00edb77

Browse files
fix: create TSI MANIFEST files atomically (#23539) (#23546)
When a MANIFEST file is created in TSI, it should be written to a temp file, then atomically renamed, to avoid overwriting the existing file only to fail on the later write. closes #23536 (cherry picked from commit 061cf55) closes #23538
1 parent 4789d54 commit 00edb77

File tree

1 file changed

+27
-1
lines changed

1 file changed

+27
-1
lines changed

tsdb/index/tsi1/partition.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,9 +1395,35 @@ func (m *Manifest) Write() (int64, error) {
13951395
}
13961396
buf = append(buf, '\n')
13971397

1398-
if err := os.WriteFile(m.path, buf, 0666); err != nil {
1398+
f, err := os.CreateTemp(filepath.Dir(m.path), ManifestFileName)
1399+
1400+
if err != nil {
1401+
return 0, err
1402+
}
1403+
1404+
tmp := f.Name()
1405+
// In correct operation, Remove() should fail because the file was renamed
1406+
defer os.Remove(tmp)
1407+
err = func() (rErr error) {
1408+
// Close() before rename for Windows
1409+
defer errors2.Capture(&rErr, f.Close)()
1410+
if _, err = f.Write(buf); err != nil {
1411+
return fmt.Errorf("failed writing temporary manifest file %q: %w", tmp, err)
1412+
}
1413+
return nil
1414+
}()
1415+
if err != nil {
1416+
return 0, err
1417+
}
1418+
1419+
if err = os.Chmod(tmp, 0666); err != nil {
13991420
return 0, err
14001421
}
1422+
1423+
if err = os.Rename(tmp, m.path); err != nil {
1424+
return 0, err
1425+
}
1426+
14011427
return int64(len(buf)), nil
14021428
}
14031429

0 commit comments

Comments
 (0)