Skip to content

Commit

Permalink
core/rawdb, cmd, ethdb, eth: implement freezer tail deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
rjl493456442 committed Nov 23, 2021
1 parent 16341e0 commit 9b08ce3
Show file tree
Hide file tree
Showing 14 changed files with 643 additions and 139 deletions.
4 changes: 2 additions & 2 deletions cmd/geth/dbcmd.go
Expand Up @@ -516,9 +516,9 @@ func freezerInspect(ctx *cli.Context) error {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
}
kind := ctx.Args().Get(0)
if noSnap, ok := rawdb.FreezerNoSnappy[kind]; !ok {
if noSnap, ok := rawdb.ChainFreezerNoSnappy[kind]; !ok {
var options []string
for opt := range rawdb.FreezerNoSnappy {
for opt := range rawdb.ChainFreezerNoSnappy {
options = append(options, opt)
}
sort.Strings(options)
Expand Down
18 changes: 9 additions & 9 deletions core/blockchain.go
Expand Up @@ -274,7 +274,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
rawdb.InitDatabaseFromFreezer(bc.db)
// If ancient database is not empty, reconstruct all missing
// indices in the background.
frozen, _ := bc.db.Ancients()
frozen, _ := bc.db.Ancients(rawdb.ChainFreezer)
if frozen > 0 {
txIndexBlock = frozen
}
Expand Down Expand Up @@ -313,7 +313,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
}

// Ensure that a previous crash in SetHead doesn't leave extra ancients
if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 {
if frozen, err := bc.db.Ancients(rawdb.ChainFreezer); err == nil && frozen > 0 {
var (
needRewind bool
low uint64
Expand Down Expand Up @@ -506,7 +506,7 @@ func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64,
// Retrieve the last pivot block to short circuit rollbacks beyond it and the
// current freezer limit to start nuking id underflown
pivot := rawdb.ReadLastPivotNumber(bc.db)
frozen, _ := bc.db.Ancients()
frozen, _ := bc.db.Ancients(rawdb.ChainFreezer)

updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (uint64, bool) {
// Rewind the block chain, ensuring we don't end up with a stateless head
Expand Down Expand Up @@ -590,11 +590,11 @@ func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64,
// Rewind the header chain, deleting all block bodies until then
delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) {
// Ignore the error here since light client won't hit this path
frozen, _ := bc.db.Ancients()
frozen, _ := bc.db.Ancients(rawdb.ChainFreezer)
if num+1 <= frozen {
// Truncate all relative data(header, total difficulty, body, receipt
// and canonical hash) from ancient store.
if err := bc.db.TruncateAncients(num); err != nil {
if err := bc.db.TruncateHead(rawdb.ChainFreezer, num); err != nil {
log.Crit("Failed to truncate ancient data", "number", num, "err", err)
}
// Remove the hash <-> number mapping from the active store.
Expand Down Expand Up @@ -949,7 +949,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [

// Ensure genesis is in ancients.
if first.NumberU64() == 1 {
if frozen, _ := bc.db.Ancients(); frozen == 0 {
if frozen, _ := bc.db.Ancients(rawdb.ChainFreezer); frozen == 0 {
b := bc.genesisBlock
td := bc.genesisBlock.Difficulty()
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{b}, []types.Receipts{nil}, td)
Expand Down Expand Up @@ -1004,14 +1004,14 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// The tx index data could not be written.
// Roll back the ancient store update.
fastBlock := bc.CurrentFastBlock().NumberU64()
if err := bc.db.TruncateAncients(fastBlock + 1); err != nil {
if err := bc.db.TruncateHead(rawdb.ChainFreezer, fastBlock+1); err != nil {
log.Error("Can't truncate ancient store after failed insert", "err", err)
}
return 0, err
}

// Sync the ancient store explicitly to ensure all data has been flushed to disk.
if err := bc.db.Sync(); err != nil {
if err := bc.db.Sync(rawdb.ChainFreezer); err != nil {
return 0, err
}

Expand All @@ -1020,7 +1020,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
if !updateHead(blockChain[len(blockChain)-1]) {
// We end up here if the header chain has reorg'ed, and the blocks/receipts
// don't match the canonical chain.
if err := bc.db.TruncateAncients(previousFastBlock + 1); err != nil {
if err := bc.db.TruncateHead(rawdb.ChainFreezer, previousFastBlock+1); err != nil {
log.Error("Can't truncate ancient store after failed insert", "err", err)
}
return 0, errSideChainReceipts
Expand Down
40 changes: 25 additions & 15 deletions core/rawdb/accessors_chain.go
Expand Up @@ -36,7 +36,7 @@ import (
// ReadCanonicalHash retrieves the hash assigned to a canonical block number.
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
data, _ = reader.Ancient(freezerHashTable, number)
if len(data) == 0 {
// Get it by hash from leveldb
Expand Down Expand Up @@ -83,8 +83,8 @@ type NumberHash struct {
Hash common.Hash
}

// ReadAllHashes retrieves all the hashes assigned to blocks at a certain heights,
// both canonical and reorged forks included.
// ReadAllHashesInRange retrieves all the hashes assigned to blocks at a certain
// heights, both canonical and reorged forks included.
// This method considers both limits to be _inclusive_.
func ReadAllHashesInRange(db ethdb.Iteratee, first, last uint64) []*NumberHash {
var (
Expand Down Expand Up @@ -300,7 +300,7 @@ func WriteFastTxLookupLimit(db ethdb.KeyValueWriter, number uint64) {
// ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// First try to look up the data in ancient database. Extra hash
// comparison is necessary since ancient database only maintains
// the canonical data.
Expand Down Expand Up @@ -377,25 +377,35 @@ func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number
}
}

// isCanon is an internal utility method, to check whether the given number/hash
// isCanonOp is an internal utility method, to check whether the given number/hash
// is part of the ancient (canon) set.
func isCanon(reader ethdb.AncientReader, number uint64, hash common.Hash) bool {
func isCanonOp(reader ethdb.AncientReadOp, number uint64, hash common.Hash) bool {
h, err := reader.Ancient(freezerHashTable, number)
if err != nil {
return false
}
return bytes.Equal(h, hash[:])
}

// isCanonOp is an internal utility method, to check whether the given number/hash
// is part of the ancient (canon) set.
func isCanon(reader ethdb.AncientReader, number uint64, hash common.Hash) bool {
h, err := reader.Ancient(ChainFreezer, freezerHashTable, number)
if err != nil {
return false
}
return bytes.Equal(h, hash[:])
}

// ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
// First try to look up the data in ancient database. Extra hash
// comparison is necessary since ancient database only maintains
// the canonical data.
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// Check if the data is in ancients
if isCanon(reader, number, hash) {
if isCanonOp(reader, number, hash) {
data, _ = reader.Ancient(freezerBodiesTable, number)
return nil
}
Expand All @@ -410,7 +420,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
// block at number, in RLP encoding.
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
data, _ = reader.Ancient(freezerBodiesTable, number)
if len(data) > 0 {
return nil
Expand Down Expand Up @@ -473,9 +483,9 @@ func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// Check if the data is in ancients
if isCanon(reader, number, hash) {
if isCanonOp(reader, number, hash) {
data, _ = reader.Ancient(freezerDifficultyTable, number)
return nil
}
Expand Down Expand Up @@ -533,9 +543,9 @@ func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
db.ReadAncients(func(reader ethdb.AncientReader) error {
db.ReadAncients(ChainFreezer, func(reader ethdb.AncientReadOp) error {
// Check if the data is in ancients
if isCanon(reader, number, hash) {
if isCanonOp(reader, number, hash) {
data, _ = reader.Ancient(freezerReceiptTable, number)
return nil
}
Expand Down Expand Up @@ -741,13 +751,13 @@ func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
WriteHeader(db, block.Header())
}

// WriteAncientBlock writes entire block data into ancient store and returns the total written size.
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []types.Receipts, td *big.Int) (int64, error) {
var (
tdSum = new(big.Int).Set(td)
stReceipts []*types.ReceiptForStorage
)
return db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
return db.ModifyAncients(ChainFreezer, func(op ethdb.AncientWriteOp) error {
for i, block := range blocks {
// Convert receipts to storage format and sum up total difficulty.
stReceipts = stReceipts[:0]
Expand Down
4 changes: 2 additions & 2 deletions core/rawdb/chain_iterator.go
Expand Up @@ -34,7 +34,7 @@ import (
// injects into the database the block hash->number mappings.
func InitDatabaseFromFreezer(db ethdb.Database) {
// If we can't access the freezer or it's empty, abort
frozen, err := db.Ancients()
frozen, err := db.Ancients(ChainFreezer)
if err != nil || frozen == 0 {
return
}
Expand All @@ -49,7 +49,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
// it would be 'neat' to read more data in one go, and let the
// freezerdb return N items (e.g up to 1000 items per go)
// That would require an API change in Ancients though
if h, err := db.Ancient(freezerHashTable, i); err != nil {
if h, err := db.Ancient(ChainFreezer, freezerHashTable, i); err != nil {
log.Crit("Failed to init database from freezer", "err", err)
} else {
hash = common.BytesToHash(h)
Expand Down

0 comments on commit 9b08ce3

Please sign in to comment.