diff --git a/core/blockchain.go b/core/blockchain.go index e4a69ff726..042226fe52 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -978,6 +978,8 @@ func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error { func (bc *BlockChain) writeHeadBlock(block *types.Block) { // Add the block to the canonical chain number scheme and mark as the head batch := bc.db.NewBatch() + defer batch.Close() + rawdb.WriteHeadHeaderHash(batch, block.Hash()) rawdb.WriteHeadFastBlockHash(batch, block.Hash()) rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64()) @@ -1437,6 +1439,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // Note all the components of block(td, hash->number map, header, body, receipts) // should be written atomically. BlockBatch is used for containing all components. blockBatch := bc.db.NewBatch() + defer blockBatch.Close() rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd) rawdb.WriteBlock(blockBatch, block) rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts) @@ -2286,6 +2289,8 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Header) error { // Delete useless indexes right now which includes the non-canonical // transaction indexes, canonical chain indexes which above the head. batch := bc.db.NewBatch() + defer batch.Close() + for _, tx := range types.HashDifference(deletedTxs, rebirthTxs) { rawdb.DeleteTxLookupEntry(batch, tx) } diff --git a/core/rawdb/table.go b/core/rawdb/table.go index dfb261f90d..a0c87173cb 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -260,6 +260,11 @@ func (b *tableBatch) Reset() { b.batch.Reset() } +// Close closes the batch and releases all associated resources. +func (b *tableBatch) Close() { + b.batch.Close() +} + // tableReplayer is a wrapper around a batch replayer which truncates // the added prefix. type tableReplayer struct { diff --git a/core/state/statedb.go b/core/state/statedb.go index 6903577d9d..4283cc6113 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1095,6 +1095,8 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er return common.Hash{}, err } + code.Close() + // Write the account trie changes, measuing the amount of wasted time // The onleaf func is called _serially_, so we can reuse the same account // for unmarshalling every time. diff --git a/ctxcdb/batch.go b/ctxcdb/batch.go index 42bd7f0c3e..45653eb866 100644 --- a/ctxcdb/batch.go +++ b/ctxcdb/batch.go @@ -37,6 +37,9 @@ type Batch interface { // Replay replays the batch contents. Replay(w KeyValueWriter) error + + // Close closes the batch and releases all associated resources. + Close() } // Batcher wraps the NewBatch method of a backing data store. diff --git a/ctxcdb/leveldb/leveldb.go b/ctxcdb/leveldb/leveldb.go index f88e590633..3ca7c0d994 100644 --- a/ctxcdb/leveldb/leveldb.go +++ b/ctxcdb/leveldb/leveldb.go @@ -492,6 +492,9 @@ func (b *batch) Replay(w ctxcdb.KeyValueWriter) error { return b.b.Replay(&replayer{writer: w}) } +// Close closes the batch and releases all associated resources. +func (b *batch) Close() {} + // replayer is a small wrapper to implement the correct replay methods. type replayer struct { writer ctxcdb.KeyValueWriter diff --git a/ctxcdb/memorydb/memorydb.go b/ctxcdb/memorydb/memorydb.go index b647bd6f0c..e13ef03cbe 100644 --- a/ctxcdb/memorydb/memorydb.go +++ b/ctxcdb/memorydb/memorydb.go @@ -350,6 +350,9 @@ func (b *batch) Replay(w ctxcdb.KeyValueWriter) error { return nil } +// Close closes the batch and releases all associated resources. +func (b *batch) Close() {} + // iterator can walk over the (potentially partial) keyspace of a memory key // value store. Internally it is a deep copy of the entire iterated state, // sorted by keys. diff --git a/ctxcdb/pebble/pebble.go b/ctxcdb/pebble/pebble.go index 3cb6b75270..7a6d5145ec 100644 --- a/ctxcdb/pebble/pebble.go +++ b/ctxcdb/pebble/pebble.go @@ -719,6 +719,12 @@ func (b *batch) Replay(w ctxcdb.KeyValueWriter) error { } } +// Close closes the batch and releases all associated resources. After it is +// closed, any subsequent operations on this batch are undefined. +func (b *batch) Close() { + b.b.Close() +} + // pebbleIterator is a wrapper of underlying iterator in storage engine. // The purpose of this structure is to implement the missing APIs. // diff --git a/trie/database.go b/trie/database.go index c6b68b0fc5..483f951487 100644 --- a/trie/database.go +++ b/trie/database.go @@ -611,6 +611,7 @@ func (db *Database) Cap(limit common.StorageSize) error { log.Error("Failed to write flush list to disk", "err", err) return err } + batch.Close() // Write successful, clear out the flushed data for db.oldest != oldest { diff --git a/trie/trie_test.go b/trie/trie_test.go index fd45e53e94..3264dcea16 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -776,6 +776,7 @@ func (b *spongeBatch) ValueSize() int { return 100 } func (b *spongeBatch) Write() error { return nil } func (b *spongeBatch) Reset() {} func (b *spongeBatch) Replay(w ctxcdb.KeyValueWriter) error { return nil } +func (b *spongeBatch) Close() {} // TestCommitSequence tests that the trie.Commit operation writes the elements // of the trie in the expected order.