core/rawdb: clean up freezer index truncation logic

Couple modifications here:

- Use switch instead of a condition chain. It seems better to me since the
  idea is comparing the file size with flushOffset and performing different
  actions when it's larger, smaller, equal.
- Rephrase some messages to add context. Users should be able to infer it's
  about the freezer from the message.
- Rename 'offset' to 'size'.
This commit is contained in:
Felix Lange 2025-02-03 23:54:51 +01:00
parent a33bba4773
commit 791988fd32

View file

@ -393,52 +393,57 @@ func (t *freezerTable) repairIndex() error {
if err != nil { if err != nil {
return err return err
} }
offset := stat.Size() size := stat.Size()
// Validate the items in the index file to ensure the data integrity. // Validate the items in the index file to ensure the data integrity.
// It's possible some garbage data is retained in the index file after // It's possible some garbage data is retained in the index file after
// the power failures and should be truncated first. // the power failures and should be truncated first.
offset, err = t.checkIndex(offset) size, err = t.checkIndex(size)
if err != nil { if err != nil {
return err return err
} }
// If legacy metadata is detected, attempt to recover the offset from the // If legacy metadata is detected, attempt to recover the offset from the
// index file to avoid clearing the entire table. // index file to avoid clearing the entire table.
if t.metadata.version == freezerTableV1 { if t.metadata.version == freezerTableV1 {
t.logger.Info("Recover the flush offset for legacy table", "offset", offset) t.logger.Info("Recovering freezer flushOffset for legacy table", "offset", size)
return t.metadata.setFlushOffset(uint64(offset), true) return t.metadata.setFlushOffset(uint64(size), true)
} }
// Move the flush offset to the end of the file for fresh new freezer table
if offset == indexEntrySize && t.metadata.flushOffset == 0 { switch {
return t.metadata.setFlushOffset(uint64(offset), true) case size == indexEntrySize && t.metadata.flushOffset == 0:
} // It's a new freezer table with no content.
// Short circuit if the offset is aligned with the index file // Move the flush offset to the end of the file.
if offset == int64(t.metadata.flushOffset) { return t.metadata.setFlushOffset(uint64(size), true)
case size == int64(t.metadata.flushOffset):
// flushOffset is aligned with the index file, all is well.
return nil return nil
}
case size > int64(t.metadata.flushOffset):
// Extra index items have been detected beyond the flush offset. Since these // Extra index items have been detected beyond the flush offset. Since these
// entries correspond to data that has not been fully flushed to disk in the // entries correspond to data that has not been fully flushed to disk in the
// last run (because of unclean shutdown), their integrity cannot be guaranteed. // last run (because of unclean shutdown), their integrity cannot be guaranteed.
// To ensure consistency, these index items will be truncated, as there is no // To ensure consistency, these index items will be truncated, as there is no
// reliable way to validate or recover their associated data. // reliable way to validate or recover their associated data.
if offset > int64(t.metadata.flushOffset) { extraSize := size - int64(t.metadata.flushOffset)
size := offset - int64(t.metadata.flushOffset)
if t.readonly { if t.readonly {
return fmt.Errorf("index file(path: %s, name: %s) contains garbage data %d", t.path, t.name, size) return fmt.Errorf("index file(path: %s, name: %s) contains %d garbage data bytes", t.path, t.name, extraSize)
} }
t.logger.Info("Truncate excessive items", "size", size) t.logger.Warn("Truncating freezer items after flushOffset", "size", extraSize)
return truncateFreezerFile(t.index, int64(t.metadata.flushOffset)) return truncateFreezerFile(t.index, int64(t.metadata.flushOffset))
}
// Flush offset refers to the position which exceeds the index file. The only default: // size < flushOffset
// possible scenario for this is: power failure or system crash occurs after // Flush offset refers to a position larger than index file. The only
// possible scenario for this is: a power failure or system crash has occurred after
// truncating the segment in index file from head or tail, but without updating // truncating the segment in index file from head or tail, but without updating
// the flush offset. In this case, automatically reset the flush offset with // the flush offset. In this case, automatically reset the flush offset with
// the file size which implies the entire index file is complete. // the file size which implies the entire index file is complete.
if t.readonly { if t.readonly {
return nil // do nothing in read only mode return nil // do nothing in read only mode
} }
t.logger.Info("Rewind the flush offset", "old", t.metadata.flushOffset, "new", offset) t.logger.Warn("Rewinding freezer flushOffset", "old", t.metadata.flushOffset, "new", size)
return t.metadata.setFlushOffset(uint64(offset), true) return t.metadata.setFlushOffset(uint64(size), true)
}
} }
// checkIndex validates the integrity of the index file. According to the design, // checkIndex validates the integrity of the index file. According to the design,