Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Synchronize access to block header #6143

Merged
merged 9 commits into from
Nov 14, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ default boolean contains(final Hash blockHash) {
*/
Optional<BlockHeader> getBlockHeader(Hash blockHeaderHash);

/**
* Safe version of {@code getBlockHeader} (it should take any locks necessary to ensure any block
* updates that might be taking place have been completed first)
*
* @param blockHeaderHash The hash of the block whose header we want to retrieve.
* @return The block header corresponding to this block hash.
*/
Optional<BlockHeader> getBlockHeaderSafe(Hash blockHeaderHash);

/**
* Returns the block body corresponding to the given block header hash. Associated block is not
* necessarily on the canonical chain.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,16 @@ public Optional<BlockHeader> getBlockHeader(final Hash blockHeaderHash) {
.orElseGet(() -> blockchainStorage.getBlockHeader(blockHeaderHash));
}

@Override
public synchronized Optional<BlockHeader> getBlockHeaderSafe(final Hash blockHeaderHash) {
return blockHeadersCache
.map(
cache ->
Optional.ofNullable(cache.getIfPresent(blockHeaderHash))
.or(() -> blockchainStorage.getBlockHeader(blockHeaderHash)))
.orElseGet(() -> blockchainStorage.getBlockHeader(blockHeaderHash));
}

@Override
public Optional<BlockBody> getBlockBody(final Hash blockHeaderHash) {
return blockBodiesCache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,14 @@ public Optional<Transaction> getTransactionByHash(final Hash hash) {

private Optional<BlockHeader> getChainHeadBlockHeader() {
final MutableBlockchain blockchain = protocolContext.getBlockchain();
return blockchain.getBlockHeader(blockchain.getChainHeadHash());

// Optimistically get the block header for the chain head without taking a lock,
// but revert to the safe implementation if it returns an empty optional. (It's
// possible the chain head has been updated but the block is still being persisted
// to storage/cache under the lock).
return blockchain
.getBlockHeader(blockchain.getChainHeadHash())
.or(() -> blockchain.getBlockHeaderSafe(blockchain.getChainHeadHash()));
}

private boolean isLocalSender(final Address sender) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ public Optional<BlockHeader> getBlockHeader(final Hash blockHeaderHash) {
return Optional.ofNullable(hashToHeader.get(blockHeaderHash));
}

@Override
public synchronized Optional<BlockHeader> getBlockHeaderSafe(final Hash blockHeaderHash) {
return Optional.ofNullable(hashToHeader.get(blockHeaderHash));
}

@Override
public Optional<BlockBody> getBlockBody(final Hash blockHeaderHash) {
// Deterministic, but just not implemented.
Expand Down
Loading