@@ -49,6 +49,9 @@ use std::sync::Arc;
4949use std:: path:: { Path , PathBuf } ;
5050use std:: io;
5151use std:: collections:: { HashMap , HashSet } ;
52+ use parking_lot:: { Mutex , RwLock } ;
53+ use linked_hash_map:: LinkedHashMap ;
54+ use log:: { trace, debug, warn} ;
5255
5356use sc_client_api:: {
5457 UsageInfo , MemoryInfo , IoInfo , MemorySize ,
@@ -63,7 +66,6 @@ use codec::{Decode, Encode};
6366use hash_db:: Prefix ;
6467use sp_trie:: { MemoryDB , PrefixedMemoryDB , prefixed_key} ;
6568use sp_database:: Transaction ;
66- use parking_lot:: RwLock ;
6769use sp_core:: ChangesTrieConfiguration ;
6870use sp_core:: offchain:: storage:: { OffchainOverlayedChange , OffchainOverlayedChanges } ;
6971use sp_core:: storage:: { well_known_keys, ChildInfo } ;
@@ -83,7 +85,6 @@ use sc_state_db::StateDb;
8385use sp_blockchain:: { CachedHeaderMetadata , HeaderMetadata , HeaderMetadataCache } ;
8486use crate :: storage_cache:: { CachingState , SyncingCachingState , SharedCache , new_shared_cache} ;
8587use crate :: stats:: StateUsageStats ;
86- use log:: { trace, debug, warn} ;
8788
8889// Re-export the Database trait so that one can pass an implementation of it.
8990pub use sp_database:: Database ;
@@ -93,6 +94,7 @@ pub use sc_state_db::PruningMode;
9394pub use bench:: BenchmarkingState ;
9495
9596const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR : u32 = 32768 ;
97+ const CACHE_HEADERS : usize = 8 ;
9698
9799/// Default value for storage cache child ratio.
98100const DEFAULT_CHILD_RATIO : ( usize , usize ) = ( 1 , 10 ) ;
@@ -352,12 +354,24 @@ impl<'a> sc_state_db::MetaDb for StateMetaDb<'a> {
352354 }
353355}
354356
357+ fn cache_header < Hash : std:: cmp:: Eq + std:: hash:: Hash , Header > (
358+ cache : & mut LinkedHashMap < Hash , Option < Header > > ,
359+ hash : Hash ,
360+ header : Option < Header > ,
361+ ) {
362+ cache. insert ( hash, header) ;
363+ while cache. len ( ) > CACHE_HEADERS {
364+ cache. pop_front ( ) ;
365+ }
366+ }
367+
355368/// Block database
356369pub struct BlockchainDb < Block : BlockT > {
357370 db : Arc < dyn Database < DbHash > > ,
358371 meta : Arc < RwLock < Meta < NumberFor < Block > , Block :: Hash > > > ,
359372 leaves : RwLock < LeafSet < Block :: Hash , NumberFor < Block > > > ,
360373 header_metadata_cache : Arc < HeaderMetadataCache < Block > > ,
374+ header_cache : Mutex < LinkedHashMap < Block :: Hash , Option < Block :: Header > > > ,
361375}
362376
363377impl < Block : BlockT > BlockchainDb < Block > {
@@ -369,6 +383,7 @@ impl<Block: BlockT> BlockchainDb<Block> {
369383 leaves : RwLock :: new ( leaves) ,
370384 meta : Arc :: new ( RwLock :: new ( meta) ) ,
371385 header_metadata_cache : Arc :: new ( HeaderMetadataCache :: default ( ) ) ,
386+ header_cache : Default :: default ( ) ,
372387 } )
373388 }
374389
@@ -407,7 +422,20 @@ impl<Block: BlockT> BlockchainDb<Block> {
407422
408423impl < Block : BlockT > sc_client_api:: blockchain:: HeaderBackend < Block > for BlockchainDb < Block > {
409424 fn header ( & self , id : BlockId < Block > ) -> ClientResult < Option < Block :: Header > > {
410- utils:: read_header ( & * self . db , columns:: KEY_LOOKUP , columns:: HEADER , id)
425+ match & id {
426+ BlockId :: Hash ( h) => {
427+ let mut cache = self . header_cache . lock ( ) ;
428+ if let Some ( result) = cache. get_refresh ( h) {
429+ return Ok ( result. clone ( ) ) ;
430+ }
431+ let header = utils:: read_header ( & * self . db , columns:: KEY_LOOKUP , columns:: HEADER , id) ?;
432+ cache_header ( & mut cache, h. clone ( ) , header. clone ( ) ) ;
433+ Ok ( header)
434+ }
435+ BlockId :: Number ( _) => {
436+ utils:: read_header ( & * self . db , columns:: KEY_LOOKUP , columns:: HEADER , id)
437+ }
438+ }
411439 }
412440
413441 fn info ( & self ) -> sc_client_api:: blockchain:: Info < Block > {
@@ -424,12 +452,7 @@ impl<Block: BlockT> sc_client_api::blockchain::HeaderBackend<Block> for Blockcha
424452
425453 fn status ( & self , id : BlockId < Block > ) -> ClientResult < sc_client_api:: blockchain:: BlockStatus > {
426454 let exists = match id {
427- BlockId :: Hash ( _) => read_db (
428- & * self . db ,
429- columns:: KEY_LOOKUP ,
430- columns:: HEADER ,
431- id
432- ) ?. is_some ( ) ,
455+ BlockId :: Hash ( _) => self . header ( id) ?. is_some ( ) ,
433456 BlockId :: Number ( n) => n <= self . meta . read ( ) . best_number ,
434457 } ;
435458 match exists {
@@ -1117,12 +1140,6 @@ impl<Block: BlockT> Backend<Block> {
11171140 hash,
11181141 ) ?;
11191142
1120- let header_metadata = CachedHeaderMetadata :: from ( & pending_block. header ) ;
1121- self . blockchain . insert_header_metadata (
1122- header_metadata. hash ,
1123- header_metadata,
1124- ) ;
1125-
11261143 transaction. set_from_vec ( columns:: HEADER , & lookup_key, pending_block. header . encode ( ) ) ;
11271144 if let Some ( body) = & pending_block. body {
11281145 transaction. set_from_vec ( columns:: BODY , & lookup_key, body. encode ( ) ) ;
@@ -1271,7 +1288,7 @@ impl<Block: BlockT> Backend<Block> {
12711288
12721289 meta_updates. push ( ( hash, number, pending_block. leaf_state . is_best ( ) , finalized) ) ;
12731290
1274- Some ( ( number, hash, enacted, retracted, displaced_leaf, is_best, cache) )
1291+ Some ( ( pending_block . header , number, hash, enacted, retracted, displaced_leaf, is_best, cache) )
12751292 } else {
12761293 None
12771294 } ;
@@ -1297,7 +1314,11 @@ impl<Block: BlockT> Backend<Block> {
12971314
12981315 self . storage . db . commit ( transaction) ?;
12991316
1317+ // Apply all in-memory state shanges.
1318+ // Code beyond this point can't fail.
1319+
13001320 if let Some ( (
1321+ header,
13011322 number,
13021323 hash,
13031324 enacted,
@@ -1306,6 +1327,12 @@ impl<Block: BlockT> Backend<Block> {
13061327 is_best,
13071328 mut cache,
13081329 ) ) = imported {
1330+ let header_metadata = CachedHeaderMetadata :: from ( & header) ;
1331+ self . blockchain . insert_header_metadata (
1332+ header_metadata. hash ,
1333+ header_metadata,
1334+ ) ;
1335+ cache_header ( & mut self . blockchain . header_cache . lock ( ) , hash, Some ( header) ) ;
13091336 cache. sync_cache (
13101337 & enacted,
13111338 & retracted,
0 commit comments