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

blockstore: populate merkle root metas column #34097

Merged

Conversation

AshwinSekar
Copy link
Contributor

@AshwinSekar AshwinSekar commented Nov 15, 2023

Problem

We don't yet write to this column.

Summary of Changes

When inserting the first shred for each fec set, populate the merkle root metas
Note: we must only create the merkle root meta if the shred was successfully inserted, otherwise there will be a desync on first_received_shred_index and what's actually available in blockstore.

Split from #33889
Contributes to #33644

Copy link

codecov bot commented Nov 15, 2023

Codecov Report

Merging #34097 (1b6c66e) into master (6a5b8e8) will increase coverage by 0.0%.
Report is 1 commits behind head on master.
The diff coverage is 99.0%.

Additional details and impacted files
@@           Coverage Diff            @@
##           master   #34097    +/-   ##
========================================
  Coverage    81.9%    81.9%            
========================================
  Files         812      812            
  Lines      219656   219864   +208     
========================================
+ Hits       179989   180238   +249     
+ Misses      39667    39626    -41     

Comment on lines +1024 to +1026
for (erasure_set, merkle_root_meta) in merkle_root_metas {
write_batch.put::<cf::MerkleRootMeta>(erasure_set.key(), &merkle_root_meta)?;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't this overwrite existing merkle-root meta in blockstore?
it seems like at least some entries will be re-written with the same value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, i just c/p the erasure_metas logic, but I think we can be smarter and keep track of which entries are dirty and need to be written.

Comment on lines +1202 to +1208
let erasure_set = shred.erasure_set();

if let HashMapEntry::Vacant(entry) = merkle_root_metas.entry(erasure_set) {
if let Some(meta) = self.merkle_root_meta(erasure_set).unwrap() {
entry.insert(meta);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why merkle-root meta is read from the blockstore.
shouldn't it be obtained from the current shred?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea here is to load the merkle entry we already have in blockstore into the in memory map for comparison in the future pr

Comment on lines +1288 to +1290
merkle_root_metas
.entry(erasure_set)
.or_insert(MerkleRootMeta::from_shred(&shred));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need the code in L1204 then?

I guess follow up commits will compare if the merkle-roots are the same.
but then I guess we could read the blockstore-db here instead of pre-emptively fetching it but then not using it if the shred is not inserted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the idea is:

L1204 - load merkle root meta from blockstore -> in memory map
(future commit) L1196 - compare with the current merkle shred meta for conflict
(here) L1287 - if the in memory map is empty and the insert has succeeded, add the current merkle shred meta to the in memory map
L1024 - commit in memory map to blockstore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then I guess we could read the blockstore-db here instead of pre-emptively fetching it but then not using it if the shred is not inserted.

this is possible, but it would result in 2 blockstore reads, one for the future comparison, and then one to decide whether to insert the newly received merkle root meta.

Comment on lines +291 to +293
pub(crate) fn key(&self) -> (Slot, /*fec_set_index:*/ u32) {
(self.0, self.1)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, this key vs store_key is pretty bad and confusing.
Can you please leave a comment where one should use each?

Maybe we should remove the (_, u64) version, and do the type cast only at the call-sites which use that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah you're right i'll remove/deprecate the old store_key and only use the u32 version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for posterity this is being fixed here: #34268

Copy link
Contributor Author

@AshwinSekar AshwinSekar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will update tomorrow to distinguish dirty entries in merkle_root_metas and deprecate the u32 version of store_key

Comment on lines +1024 to +1026
for (erasure_set, merkle_root_meta) in merkle_root_metas {
write_batch.put::<cf::MerkleRootMeta>(erasure_set.key(), &merkle_root_meta)?;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, i just c/p the erasure_metas logic, but I think we can be smarter and keep track of which entries are dirty and need to be written.

Comment on lines +1202 to +1208
let erasure_set = shred.erasure_set();

if let HashMapEntry::Vacant(entry) = merkle_root_metas.entry(erasure_set) {
if let Some(meta) = self.merkle_root_meta(erasure_set).unwrap() {
entry.insert(meta);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea here is to load the merkle entry we already have in blockstore into the in memory map for comparison in the future pr

Comment on lines +1288 to +1290
merkle_root_metas
.entry(erasure_set)
.or_insert(MerkleRootMeta::from_shred(&shred));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the idea is:

L1204 - load merkle root meta from blockstore -> in memory map
(future commit) L1196 - compare with the current merkle shred meta for conflict
(here) L1287 - if the in memory map is empty and the insert has succeeded, add the current merkle shred meta to the in memory map
L1024 - commit in memory map to blockstore

Comment on lines +291 to +293
pub(crate) fn key(&self) -> (Slot, /*fec_set_index:*/ u32) {
(self.0, self.1)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah you're right i'll remove/deprecate the old store_key and only use the u32 version.

Comment on lines +1288 to +1290
merkle_root_metas
.entry(erasure_set)
.or_insert(MerkleRootMeta::from_shred(&shred));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then I guess we could read the blockstore-db here instead of pre-emptively fetching it but then not using it if the shred is not inserted.

this is possible, but it would result in 2 blockstore reads, one for the future comparison, and then one to decide whether to insert the newly received merkle root meta.

Copy link
Contributor

@behzadnouri behzadnouri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, assuming the leftover issues will be addressed in follow up commits.

@AshwinSekar AshwinSekar merged commit e1165aa into solana-labs:master Nov 29, 2023
32 checks passed
@AshwinSekar AshwinSekar deleted the blockstore-merkle-meta-write branch November 29, 2023 16:39
@AshwinSekar AshwinSekar self-assigned this Nov 29, 2023
@AshwinSekar AshwinSekar requested a review from t-nelson November 30, 2023 23:30
@AshwinSekar AshwinSekar added the v1.17 PRs that should be backported to v1.17 label Dec 7, 2023
Copy link
Contributor

mergify bot commented Dec 7, 2023

Backports to the beta branch are to be avoided unless absolutely necessary for fixing bugs, security issues, and perf regressions. Changes intended for backport should be structured such that a minimum effective diff can be committed separately from any refactoring, plumbing, cleanup, etc that are not strictly necessary to achieve the goal. Any of the latter should go only into master and ride the normal stabilization schedule. Exceptions include CI/metrics changes, CLI improvements and documentation updates on a case by case basis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v1.17 PRs that should be backported to v1.17
Projects
Development

Successfully merging this pull request may close these issues.

2 participants