core/rawdb: fsync the index file after each freezer write (#28483)
* core/rawdb: fsync the index and data file after each freezer write * core/rawdb: fsync the data file in freezer after write
This commit is contained in:
parent
e38b9f1830
commit
326fa00759
@ -18,6 +18,7 @@ package rawdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
@ -126,6 +127,8 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
|
|||||||
switch freezerName {
|
switch freezerName {
|
||||||
case chainFreezerName:
|
case chainFreezerName:
|
||||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||||
|
case stateFreezerName:
|
||||||
|
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||||
}
|
}
|
||||||
|
@ -182,19 +182,27 @@ func (batch *freezerTableBatch) maybeCommit() error {
|
|||||||
|
|
||||||
// commit writes the batched items to the backing freezerTable.
|
// commit writes the batched items to the backing freezerTable.
|
||||||
func (batch *freezerTableBatch) commit() error {
|
func (batch *freezerTableBatch) commit() error {
|
||||||
// Write data.
|
// Write data. The head file is fsync'd after write to ensure the
|
||||||
|
// data is truly transferred to disk.
|
||||||
_, err := batch.t.head.Write(batch.dataBuffer)
|
_, err := batch.t.head.Write(batch.dataBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := batch.t.head.Sync(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
dataSize := int64(len(batch.dataBuffer))
|
dataSize := int64(len(batch.dataBuffer))
|
||||||
batch.dataBuffer = batch.dataBuffer[:0]
|
batch.dataBuffer = batch.dataBuffer[:0]
|
||||||
|
|
||||||
// Write indices.
|
// Write indices. The index file is fsync'd after write to ensure the
|
||||||
|
// data indexes are truly transferred to disk.
|
||||||
_, err = batch.t.index.Write(batch.indexBuffer)
|
_, err = batch.t.index.Write(batch.indexBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := batch.t.index.Sync(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
indexSize := int64(len(batch.indexBuffer))
|
indexSize := int64(len(batch.indexBuffer))
|
||||||
batch.indexBuffer = batch.indexBuffer[:0]
|
batch.indexBuffer = batch.indexBuffer[:0]
|
||||||
|
|
||||||
|
@ -215,7 +215,9 @@ func (t *freezerTable) repair() error {
|
|||||||
if t.readonly {
|
if t.readonly {
|
||||||
return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize)
|
return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize)
|
||||||
}
|
}
|
||||||
truncateFreezerFile(t.index, stat.Size()-overflow) // New file can't trigger this path
|
if err := truncateFreezerFile(t.index, stat.Size()-overflow); err != nil {
|
||||||
|
return err
|
||||||
|
} // New file can't trigger this path
|
||||||
}
|
}
|
||||||
// Retrieve the file sizes and prepare for truncation
|
// Retrieve the file sizes and prepare for truncation
|
||||||
if stat, err = t.index.Stat(); err != nil {
|
if stat, err = t.index.Stat(); err != nil {
|
||||||
@ -260,8 +262,8 @@ func (t *freezerTable) repair() error {
|
|||||||
// Print an error log if the index is corrupted due to an incorrect
|
// Print an error log if the index is corrupted due to an incorrect
|
||||||
// last index item. While it is theoretically possible to have a zero offset
|
// last index item. While it is theoretically possible to have a zero offset
|
||||||
// by storing all zero-size items, it is highly unlikely to occur in practice.
|
// by storing all zero-size items, it is highly unlikely to occur in practice.
|
||||||
if lastIndex.offset == 0 && offsetsSize%indexEntrySize > 1 {
|
if lastIndex.offset == 0 && offsetsSize/indexEntrySize > 1 {
|
||||||
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "items", offsetsSize%indexEntrySize-1)
|
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "indexes", offsetsSize/indexEntrySize)
|
||||||
}
|
}
|
||||||
if t.readonly {
|
if t.readonly {
|
||||||
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
|
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
|
||||||
@ -416,6 +418,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
|||||||
if err := truncateFreezerFile(t.index, int64(length+1)*indexEntrySize); err != nil {
|
if err := truncateFreezerFile(t.index, int64(length+1)*indexEntrySize); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := t.index.Sync(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// Calculate the new expected size of the data file and truncate it
|
// Calculate the new expected size of the data file and truncate it
|
||||||
var expected indexEntry
|
var expected indexEntry
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
@ -438,6 +443,7 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
|||||||
// Release any files _after the current head -- both the previous head
|
// Release any files _after the current head -- both the previous head
|
||||||
// and any files which may have been opened for reading
|
// and any files which may have been opened for reading
|
||||||
t.releaseFilesAfter(expected.filenum, true)
|
t.releaseFilesAfter(expected.filenum, true)
|
||||||
|
|
||||||
// Set back the historic head
|
// Set back the historic head
|
||||||
t.head = newHead
|
t.head = newHead
|
||||||
t.headId = expected.filenum
|
t.headId = expected.filenum
|
||||||
@ -445,6 +451,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
|||||||
if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil {
|
if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := t.head.Sync(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// All data files truncated, set internal counters and return
|
// All data files truncated, set internal counters and return
|
||||||
t.headBytes = int64(expected.offset)
|
t.headBytes = int64(expected.offset)
|
||||||
t.items.Store(items)
|
t.items.Store(items)
|
||||||
@ -589,10 +598,12 @@ func (t *freezerTable) Close() error {
|
|||||||
// error on Windows.
|
// error on Windows.
|
||||||
doClose(t.index, true, true)
|
doClose(t.index, true, true)
|
||||||
doClose(t.meta, true, true)
|
doClose(t.meta, true, true)
|
||||||
|
|
||||||
// The preopened non-head data-files are all opened in readonly.
|
// The preopened non-head data-files are all opened in readonly.
|
||||||
// The head is opened in rw-mode, so we sync it here - but since it's also
|
// The head is opened in rw-mode, so we sync it here - but since it's also
|
||||||
// part of t.files, it will be closed in the loop below.
|
// part of t.files, it will be closed in the loop below.
|
||||||
doClose(t.head, true, false) // sync but do not close
|
doClose(t.head, true, false) // sync but do not close
|
||||||
|
|
||||||
for _, f := range t.files {
|
for _, f := range t.files {
|
||||||
doClose(f, false, true) // close but do not sync
|
doClose(f, false, true) // close but do not sync
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,7 @@ func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
f = nil
|
f = nil
|
||||||
|
return os.Rename(fname, destPath)
|
||||||
if err := os.Rename(fname, destPath); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// openFreezerFileForAppend opens a freezer table file and seeks to the end
|
// openFreezerFileForAppend opens a freezer table file and seeks to the end
|
||||||
|
Loading…
Reference in New Issue
Block a user