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

Implement FlatStorageState #7663

Merged
merged 9 commits into from
Sep 26, 2022
Merged

Implement FlatStorageState #7663

merged 9 commits into from
Sep 26, 2022

Conversation

mzhangmzz
Copy link
Contributor

@mzhangmzz mzhangmzz commented Sep 22, 2022

This PR implements FlatStorageState, the struct that manages deltas in flat storage. After this PR, the main implementation of flat storage is mostly ready. The next step is to add more tests.

@mzhangmzz mzhangmzz marked this pull request as ready for review September 22, 2022 20:57
@mzhangmzz mzhangmzz requested a review from a team as a code owner September 22, 2022 20:57
@mzhangmzz mzhangmzz requested review from matklad, Longarithm, jakmeier and akhi3030 and removed request for matklad September 22, 2022 20:57
Copy link
Contributor

@jakmeier jakmeier left a comment

Choose a reason for hiding this comment

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

Looks good to me! Your choice if you want to wait for Aleksandr to be back and have a look as well or if you want to merge before that. :)

shard_id,
store.head().unwrap().height,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason this changed from ? to .unwrap()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah good call, changed back.

Comment on lines 4726 to 4728
// Right now, we don't implement flat storage for catchup, so we only store
// the delta if we are not catching up
if !is_catching_up {
if let Some(chain_flat_storage) =
self.runtime_adapter.get_flat_storage_state_for_shard(shard_id)
{
let delta = FlatStateDelta::from_state_changes(
&apply_result.trie_changes.state_changes(),
);
let store_update = chain_flat_storage.add_delta(&block_hash, delta)?;
self.chain_store_update.merge(store_update);
}
}
self.save_flat_state_changes(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the comment about catchup still relevant here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I'll move it to inside save_flat_state_changes.

core/store/src/flat_state.rs Outdated Show resolved Hide resolved
core/store/src/flat_state.rs Outdated Show resolved Hide resolved
let mut chain = MockChain::linear_chain(10);
let store = create_test_store();
let mut store_update = store.store_update();
store_helper::set_flat_head(&mut store_update, 0, &chain.get_block_hash(0));
Copy link
Member

Choose a reason for hiding this comment

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

Can we check in set_flat_head that flat state head is not set previously, or add a comment that it must be called only once? Though I am not sure how it will work with catchup logic.

Adding comment here because set_flat_head is unchanged in the PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I understand what you are referring to. set_flat_head can be called many times, it is called every time when flat_head is updated. Are you worried that the function set_flat_head can be arbitrarily called in the code, not through update_flat_head?

Copy link
Member

Choose a reason for hiding this comment

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

Are you worried that the function set_flat_head can be arbitrarily called in the code, not through update_flat_head?

Yeah, that's right. I'm thinking about making set_flat_head private, or explicitly saying that it must be called only inside update_flat_head or on initialization.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I made it private and added another function set_flat_storage_state_for_genesis

@near-bulldozer near-bulldozer bot merged commit 55a3b4d into master Sep 26, 2022
@near-bulldozer near-bulldozer bot deleted the flat_storage_state branch September 26, 2022 22:27
// TODO (#7327): implement garbage collection of old deltas.
// TODO (#7327): cache deltas to speed up multiple DB reads.
/// Get deltas between blocks `target_block_hash`(inclusive) to flat head(inclusive),
/// in backwards chain order. Returns an error if there is no path between these two them.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be helpful to say what "backwards chain order" means, it's not clear what "chain order" exactly refers to.

@@ -392,38 +413,41 @@ struct FlatStorageStateInner {
/// State deltas for all blocks supported by this flat storage.
/// All these deltas here are stored on disk too.
#[allow(unused)]
deltas: HashMap<CryptoHash, FlatStateDelta>,
deltas: HashMap<CryptoHash, Arc<FlatStateDelta>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we combine blocks and deltas into a single hash map, so we don't need to look up twice?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point

pub fn merge(&mut self, other: Self) {
self.0.extend(other.0)
pub fn merge(&mut self, other: &Self) {
self.0.extend(other.0.iter().map(|(k, v)| (k.clone(), v.clone())))
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: other.0.iter().cloned() should work?

@@ -81,7 +100,7 @@ mod imp {
/// could charge users for the value length before loading the value.
// TODO (#7327): support different roots (or block hashes).
// TODO (#7327): consider inlining small values, so we could use only one db access.
pub fn get_ref(&self, key: &[u8]) -> Result<Option<ValueRef>, StorageError> {
pub fn get_ref(&self, key: &[u8]) -> Result<Option<ValueRef>, crate::StorageError> {
// Take deltas ordered from `self.block_hash` to flat state head.
// In other words, order of deltas is the opposite of the order of blocks in chain.
let deltas = self.flat_storage_state.get_deltas_between_blocks(&self.block_hash)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Will we move this to the (maybe lazy) initialization of FlatState? I don't imagine computing this for every single key would be very efficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but flat_head could change during the lifetime of FlatState, so we can't remove the need for calling get_deltas_between_blocks all together. One optimization we could do is to store the value of flat_head and the deltas path last time when get_deltas_between_blocks is called and only recompute it if flat_head is changed. I'll create a JIRA issue to track this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, thanks. As a general feedback here I find the names a bit overloaded. Maybe some documentation text on how each of these structures are different / related could be helpful. For example, it's almost impossible to tell what the difference is between FlatStorageState and FlatState by just looking at the names (it's still fuzzy to me even after reading the code).

nikurt pushed a commit that referenced this pull request Sep 27, 2022
This PR implements FlatStorageState, the struct that manages deltas in flat storage. After this PR, the main implementation of flat storage is mostly ready. The next step is to add more tests.
nikurt pushed a commit that referenced this pull request Nov 9, 2022
This PR implements FlatStorageState, the struct that manages deltas in flat storage. After this PR, the main implementation of flat storage is mostly ready. The next step is to add more tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants