atomic file write

Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
jsvisa 2025-06-18 08:22:08 +00:00 committed by Gary Rong
parent 82d57f9377
commit c7d2d30f49

View file

@ -332,13 +332,22 @@ func (db *Database) Journal(root common.Hash) error {
} }
var journal io.Writer var journal io.Writer
var file *os.File
// Store the journal into the database and return // Store the journal into the database and return
if db.config.Journal != "" { if db.config.Journal != "" {
file, err := os.OpenFile(db.config.Journal, os.O_WRONLY|os.O_CREATE, 0644) // Write into a temp file first
var err error
file, err = os.OpenFile(db.config.Journal+".new", os.O_WRONLY|os.O_CREATE, 0644)
if err != nil { if err != nil {
return fmt.Errorf("failed to open journal file %s: %w", db.config.Journal, err) return fmt.Errorf("failed to open journal file %s: %w", db.config.Journal, err)
} }
defer file.Close() defer func() {
if file != nil {
file.Close()
// Clean up temp file if we didn't successfully rename it
os.Remove(db.config.Journal + ".new")
}
}()
journal = file journal = file
} else { } else {
journal = new(bytes.Buffer) journal = new(bytes.Buffer)
@ -369,8 +378,17 @@ func (db *Database) Journal(root common.Hash) error {
size = data.Len() size = data.Len()
rawdb.WriteTrieJournal(db.diskdb, data.Bytes()) rawdb.WriteTrieJournal(db.diskdb, data.Bytes())
} else { } else {
// Close the temporary file and atomically rename it
if err := file.Close(); err != nil {
return fmt.Errorf("failed to close temporary journal file: %w", err)
}
// Replace the live journal with the newly generated one
if err := os.Rename(db.config.Journal+".new", db.config.Journal); err != nil {
return fmt.Errorf("failed to rename temporary journal file: %w", err)
}
stat, _ := journal.(*os.File).Stat() stat, _ := journal.(*os.File).Stat()
size = int(stat.Size()) size = int(stat.Size())
file = nil
} }
// Set the db in read only mode to reject all following mutations // Set the db in read only mode to reject all following mutations