cmd/utils, core/rawdb: address some comments

This commit is contained in:
rjl493456442 2019-07-25 18:59:33 +08:00 committed by Péter Szilágyi
parent a536c5d33c
commit 24192a95c0
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D
7 changed files with 40 additions and 37 deletions

View file

@ -1424,7 +1424,10 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
CheckExclusive(ctx, LightLegacyServFlag, LightServeFlag, SyncModeFlag, "light") CheckExclusive(ctx, LightLegacyServFlag, LightServeFlag, SyncModeFlag, "light")
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
CheckExclusive(ctx, GCModeFlag, "archive", TxLookupLimitFlag) CheckExclusive(ctx, GCModeFlag, "archive", TxLookupLimitFlag)
// todo(rjl493456442) make it available for les server
// Ancient tx indices pruning is not available for les server now
// since light client relies on the server for transaction status query.
CheckExclusive(ctx, SyncModeFlag, "light", TxLookupLimitFlag)
var ks *keystore.KeyStore var ks *keystore.KeyStore
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore) ks = keystores[0].(*keystore.KeyStore)

View file

@ -290,7 +290,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
} }
// Take ownership of this particular state // Take ownership of this particular state
go bc.update() go bc.update()
go bc.updateTxIndices() go bc.maintainTxIndex()
return bc, nil return bc, nil
} }
@ -2046,7 +2046,7 @@ func (bc *BlockChain) update() {
} }
} }
// updateTxIndices is responsible for the construction and deletion of the // maintainTxIndex is responsible for the construction and deletion of the
// transaction index. // transaction index.
// //
// User can use flag `txlookuplimit` to specify a "recentness" block, below // User can use flag `txlookuplimit` to specify a "recentness" block, below
@ -2055,22 +2055,12 @@ func (bc *BlockChain) update() {
// //
// The user can adjust the txlookuplimit value for each launch, Geth will // The user can adjust the txlookuplimit value for each launch, Geth will
// automatically construct the missing indices and delete the extra indices. // automatically construct the missing indices and delete the extra indices.
func (bc *BlockChain) updateTxIndices() { func (bc *BlockChain) maintainTxIndex() {
var (
done chan struct{} // Non-nil if background unindexing or reindexing routine is active.
headCh = make(chan ChainHeadEvent)
)
sub := bc.SubscribeChainHeadEvent(headCh)
defer func() {
if sub != nil {
sub.Unsubscribe()
}
}()
// initialiseIndices inits txlookup indices into the database. // initialiseIndices inits txlookup indices into the database.
// If there already exists some indices, this function will find // If there already exists some indices, this function will find
// the oldest block which has been indexed and start indexing from // the oldest block which has been indexed and start indexing from
// this point. // this point.
initialiseIndices := func(head uint64) { initialiseIndices := func(head uint64, done chan struct{}) {
defer func() { done <- struct{}{} }() defer func() { done <- struct{}{} }()
from, to := uint64(0), head from, to := uint64(0), head
@ -2080,7 +2070,7 @@ func (bc *BlockChain) updateTxIndices() {
// Find oldest indexed block via binary search when we don't // Find oldest indexed block via binary search when we don't
// have this flag in database. // have this flag in database.
start := time.Now() start := time.Now()
oldest := rawdb.FindOldestIndexedBlock(bc.db, from, to) oldest := rawdb.FindTxIndexTail(bc.db, from, to)
log.Debug("Find oldest indexed block", "oldest", oldest, "elapsed", common.PrettyDuration(time.Since(start))) log.Debug("Find oldest indexed block", "oldest", oldest, "elapsed", common.PrettyDuration(time.Since(start)))
// Re-construct missing tx indices. // Re-construct missing tx indices.
@ -2091,7 +2081,7 @@ func (bc *BlockChain) updateTxIndices() {
// Drop all useless tx indices below the HEAD-limit. // Drop all useless tx indices below the HEAD-limit.
if from > 0 { if from > 0 {
oldest := rawdb.FindOldestIndexedBlock(bc.db, 0, from) oldest := rawdb.FindTxIndexTail(bc.db, 0, from)
if oldest != nil { if oldest != nil {
rawdb.RemoveTxsLookup(bc.db, *oldest, from) rawdb.RemoveTxsLookup(bc.db, *oldest, from)
} }
@ -2101,7 +2091,7 @@ func (bc *BlockChain) updateTxIndices() {
} }
// indexBlocks reindex or unindex transaction indices depends // indexBlocks reindex or unindex transaction indices depends
// on user's requirement. // on user's requirement.
indexBlocks := func(oldest uint64, head uint64) { indexBlocks := func(oldest uint64, head uint64, done chan struct{}) {
defer func() { done <- struct{}{} }() defer func() { done <- struct{}{} }()
// All indices should be reserved. // All indices should be reserved.
@ -2125,16 +2115,26 @@ func (bc *BlockChain) updateTxIndices() {
rawdb.RemoveTxsLookup(bc.db, oldest, head-bc.txLookupLimit) rawdb.RemoveTxsLookup(bc.db, oldest, head-bc.txLookupLimit)
} }
} }
var (
done chan struct{} // Non-nil if background unindexing or reindexing routine is active.
headCh = make(chan ChainHeadEvent)
)
sub := bc.SubscribeChainHeadEvent(headCh)
defer func() {
if sub != nil {
sub.Unsubscribe()
}
}()
for { for {
select { select {
case head := <-headCh: case head := <-headCh:
if done == nil { if done == nil {
done = make(chan struct{}) done = make(chan struct{})
if number := rawdb.ReadOldestIndexedBlock(bc.db); number == nil { if number := rawdb.ReadTxIndexTail(bc.db); number == nil {
go initialiseIndices(head.Block.NumberU64()) go initialiseIndices(head.Block.NumberU64(), done)
} else { } else {
go indexBlocks(*number, head.Block.NumberU64()) go indexBlocks(*number, head.Block.NumberU64(), done)
} }
} }
case <-done: case <-done:

View file

@ -2155,7 +2155,7 @@ func TestTransactionIndices(t *testing.T) {
blocks2, _ := GenerateChain(gspec.Config, blocks[len(blocks)-1], ethash.NewFaker(), gendb, 10, nil) blocks2, _ := GenerateChain(gspec.Config, blocks[len(blocks)-1], ethash.NewFaker(), gendb, 10, nil)
check := func(oldest *uint64, chain *BlockChain) { check := func(oldest *uint64, chain *BlockChain) {
indexed := rawdb.ReadOldestIndexedBlock(chain.db) indexed := rawdb.ReadTxIndexTail(chain.db)
if oldest == nil && indexed != nil { if oldest == nil && indexed != nil {
t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *indexed) t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *indexed)
} }

View file

@ -171,11 +171,11 @@ func WriteFastTrieProgress(db ethdb.KeyValueWriter, count uint64) {
} }
} }
// ReadOldestIndexedBlock retrieves the number of oldest indexed block // ReadTxIndexTail retrieves the number of oldest indexed block
// whose transaction indices has been indexed. If the corresponding entry // whose transaction indices has been indexed. If the corresponding entry
// is non-existent in database it means the indexing has been finished. // is non-existent in database it means the indexing has been finished.
func ReadOldestIndexedBlock(db ethdb.KeyValueReader) *uint64 { func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 {
data, _ := db.Get(oldestIndexedBlockKey) data, _ := db.Get(txIndexTailKey)
if len(data) != 8 { if len(data) != 8 {
return nil return nil
} }
@ -183,10 +183,10 @@ func ReadOldestIndexedBlock(db ethdb.KeyValueReader) *uint64 {
return &number return &number
} }
// WriteOldestIndexedBlock stores the number of oldest indexed block // WriteTxIndexTail stores the number of oldest indexed block
// into database. // into database.
func WriteOldestIndexedBlock(db ethdb.KeyValueWriter, number uint64) { func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) {
if err := db.Put(oldestIndexedBlockKey, encodeBlockNumber(number)); err != nil { if err := db.Put(txIndexTailKey, encodeBlockNumber(number)); err != nil {
log.Crit("Failed to store the number of oldest indexed block", "err", err) log.Crit("Failed to store the number of oldest indexed block", "err", err)
} }
} }
@ -579,14 +579,14 @@ func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header {
return a return a
} }
// FindOldestIndexedBlock binary searches the oldest block which has been indexed. // FindTxIndexTail binary searches the oldest block which has been indexed.
// We will always ensures that if Bi is indexed, then Bi+1 must has been indexed. // We will always ensures that if Bi is indexed, then Bi+1 must has been indexed.
// //
// If no block has been indexed, then the returned value is to+1. // If no block has been indexed, then the returned value is to+1.
// //
// The block doesn't contain any transaction will be regarded as unindexed. It can // The block doesn't contain any transaction will be regarded as unindexed. It can
// cause the blocks before this block can be reindexed. // cause the blocks before this block will be reindexed.
func FindOldestIndexedBlock(db ethdb.Reader, from uint64, to uint64) *uint64 { func FindTxIndexTail(db ethdb.Reader, from uint64, to uint64) *uint64 {
low, high := from, to+1 low, high := from, to+1
check := func(number uint64) bool { check := func(number uint64) bool {

View file

@ -402,7 +402,7 @@ func TestFindOldestIndexedBlock(t *testing.T) {
WriteTxLookupEntries(db, block) WriteTxLookupEntries(db, block)
} }
} }
res := FindOldestIndexedBlock(db, c.start, c.end) res := FindTxIndexTail(db, c.start, c.end)
if c.expectNil && res != nil { if c.expectNil && res != nil {
t.Fatalf("Case %d failed, oldest block mismatch, want nil, have %d", cid, *res) t.Fatalf("Case %d failed, oldest block mismatch, want nil, have %d", cid, *res)
} }

View file

@ -200,13 +200,13 @@ func IndexTxLookup(db ethdb.Database, from uint64, to uint64) {
writeIndices := func(batch ethdb.Batch, block *types.Block) { writeIndices := func(batch ethdb.Batch, block *types.Block) {
WriteTxLookupEntries(batch, block) WriteTxLookupEntries(batch, block)
if block.NumberU64()%1000000 == 0 { if block.NumberU64()%1000000 == 0 {
WriteOldestIndexedBlock(batch, block.NumberU64()) WriteTxIndexTail(batch, block.NumberU64())
} }
} }
if err := iterateCanonicalChain(db, from, to, "txlookup", hashTxs, writeIndices, true, true); err != nil { if err := iterateCanonicalChain(db, from, to, "txlookup", hashTxs, writeIndices, true, true); err != nil {
log.Crit("Failed to iterate canonical chain", "err", err) log.Crit("Failed to iterate canonical chain", "err", err)
} }
WriteOldestIndexedBlock(db, from) WriteTxIndexTail(db, from)
log.Info("Constructed transaction indices", "from", from, "to", to, "count", to-from) log.Info("Constructed transaction indices", "from", from, "to", to, "count", to-from)
} }
@ -214,7 +214,7 @@ func IndexTxLookup(db ethdb.Database, from uint64, to uint64) {
func RemoveTxsLookup(db ethdb.Database, from uint64, to uint64) { func RemoveTxsLookup(db ethdb.Database, from uint64, to uint64) {
// Write flag first and then unindex the transaction indices. Some indices // Write flag first and then unindex the transaction indices. Some indices
// will be left in the database if crash happens but it's fine. // will be left in the database if crash happens but it's fine.
WriteOldestIndexedBlock(db, to) WriteTxIndexTail(db, to)
if from+1 == to { if from+1 == to {
hash := ReadCanonicalHash(db, from) hash := ReadCanonicalHash(db, from)

View file

@ -41,8 +41,8 @@ var (
// fastTrieProgressKey tracks the number of trie entries imported during fast sync. // fastTrieProgressKey tracks the number of trie entries imported during fast sync.
fastTrieProgressKey = []byte("TrieSync") fastTrieProgressKey = []byte("TrieSync")
// oldestIndexedBlockKey tracks the oldest block whose transaction indices(txlookup) has been indexed. // txIndexTailKey tracks the oldest block whose transaction indices(txlookup) has been indexed.
oldestIndexedBlockKey = []byte("OldestIndexedBlock") txIndexTailKey = []byte("TxIndexTail")
// Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes). // Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes).
headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header