struct BlockIndex {
index_map: MmapMut,
index_size: usize,
}Expand description
A hash map implementation that maps block hashes to u32 indexes. Indexes are stored scattered
across the memory-mapped file and accessed via hash_map_find_pos. We keep track of how many
buckets are occupied in the metadata file (so we can re-hash the map when needed).
Fields§
§index_map: MmapMutThe memory map for the block indexes
index_size: usizeThe maximum size of the index map, in buckets
Implementations§
Source§impl BlockIndex
impl BlockIndex
Sourcefn new(index_map: MmapMut, index_size: usize) -> Self
fn new(index_map: MmapMut, index_size: usize) -> Self
Creates a new block index
This function should only be called by FlatChainStore::new, and it should never be called directly. It creates a new block index, given a mutable memory-mapped buffer for the index map and its maximum size in buckets.
Sourcefn flush(&self) -> Result<(), FlatChainstoreError>
fn flush(&self) -> Result<(), FlatChainstoreError>
Flushes the index map to disk
If we have enough changes that we don’t want to lose, we should flush the index map to disk. This makes sure the indexes are persisted, and we can recover them in case of a crash.
Sourceunsafe fn set_index_for_hash(
&self,
hash: BlockHash,
index: Index,
get_header_by_index: impl Fn(Index) -> Result<HashedDiskHeader, FlatChainstoreError>,
) -> Result<bool, FlatChainstoreError>
unsafe fn set_index_for_hash( &self, hash: BlockHash, index: Index, get_header_by_index: impl Fn(Index) -> Result<HashedDiskHeader, FlatChainstoreError>, ) -> Result<bool, FlatChainstoreError>
Updates our index to map a block hash to an index
After accepting a new block, this should be updated to record its position in the chain. Returns true if the position was empty, and false if it was occupied (meaning we are rewriting an existing entry).
Sourceunsafe fn get_index_for_hash(
&self,
hash: BlockHash,
get_header_by_index: impl Fn(Index) -> Result<HashedDiskHeader, FlatChainstoreError>,
) -> Result<Option<(Index, DiskBlockHeader)>, FlatChainstoreError>
unsafe fn get_index_for_hash( &self, hash: BlockHash, get_header_by_index: impl Fn(Index) -> Result<HashedDiskHeader, FlatChainstoreError>, ) -> Result<Option<(Index, DiskBlockHeader)>, FlatChainstoreError>
Returns the block index for a given block hash and its fetched header, if present
Sourceunsafe fn hash_map_find_pos(
&self,
block_hash: BlockHash,
get_header_by_index: impl Fn(Index) -> Result<HashedDiskHeader, FlatChainstoreError>,
) -> Result<IndexBucket, FlatChainstoreError>
unsafe fn hash_map_find_pos( &self, block_hash: BlockHash, get_header_by_index: impl Fn(Index) -> Result<HashedDiskHeader, FlatChainstoreError>, ) -> Result<IndexBucket, FlatChainstoreError>
Returns the position inside the hash map where a given hash should be
This function computes the short hash for the block hash and looks up the position inside the index map. If the found index fetches the header we are looking for, return this bucket. Otherwise, we continue incrementing the short hash until we either find the record or a vacant position. If you’re adding a new entry, call this function (it will return a vacant position) and write the height there.
Sourcefn index_hash_fn(block_hash: BlockHash) -> u32
fn index_hash_fn(block_hash: BlockHash) -> u32
The (short) hash function we use to compute where in the map a given index should be
In our normal operation, we sometime need to retrieve a header based on a block hash, rather than height. Block hashes are 256 bits long, so we can’t really use them to index here. Truncating the sha256 is one option, but this short hash function will give us better randomization over the data, and it’s super easy to compute anyway.
This hash function is based on the Jenkins hash function with non-zero seed.