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

Fix blob storage #3502

Merged
merged 9 commits into from
Mar 8, 2025
Merged

Fix blob storage #3502

merged 9 commits into from
Mar 8, 2025

Conversation

ma2bd
Copy link
Contributor

@ma2bd ma2bd commented Mar 8, 2025

Motivation

Proposal

On top of #3501, we simply deactivate the features that require exclusive access to an object in storage.

  • Journaling is not authorized.
  • LRU cache should never insert None but instead forget about the deleted key. (Not that we delete blobs but who knows in the future.)

We may want to rename connect and clone_with_root_keys later in another PR.

Test Plan

Release Plan

In principle, this chould be backported to the latest testnet branch.

Copy link
Contributor

@afck afck 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!

The assumption that after clone_with_root_key we have exclusive access is not something that storage guarantees, is it? It's just that in our use case, all cloned stores are for root views, and those are always only accessed by a single worker?

Comment on lines +47 to +48
/// Whether we have exclusive R/W access to the keys under the root key of the store.
has_exclusive_access: bool,
Copy link
Contributor

Choose a reason for hiding this comment

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

The use of the terminology has_exclusive_access is adequate for the terminology.
But the use in the case !use_exclusive_access makes sense only in a system where data is written in keys are only written, never modified, never erased. That needs to be said. But yes, it is better than cache_key_absence or PR #3496.

The problem of this design is that it forces an API. Conceivably, we could do a clone_with_root_key and not have exclusive access to it. Also, we could access to a store and have access to it. Therefore, I think it would make sense to have that in the input parameter to the LruCachingConfig.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to rename clone_with_root_key. In fact the types returned by connect and clone_with_root_key should probably be different.

Comment on lines +247 to +249
if !self.has_exclusive_access {
return Err(JournalConsistencyError::JournalRequiresExclusiveAccess.into());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The action is indeed necessary for the system to work correctly.
However, I would say that this kills the interest of journaling.

The problem is that what is stored as blobs is large data like Wasm compiled code. Given the limits on size for the fastpath this could be a problem. Still, I have not been able to enable the problem.

Right now, I do not see how to address this issue and have journal and non-exclusive access.

@ma2bd ma2bd force-pushed the fix_blob_storage branch from 5e9d76d to 61e44b0 Compare March 8, 2025 14:26
ma2bd and others added 2 commits March 8, 2025 09:27
Co-authored-by: Andreas Fackler <[email protected]>
Signed-off-by: Mathieu Baudet <[email protected]>
Co-authored-by: Andreas Fackler <[email protected]>
Signed-off-by: Mathieu Baudet <[email protected]>
let store = linera_views::dynamo_db::DynamoDbStore::new_test_store()
.await
.unwrap();
let store = store.clone_with_root_key(&[]).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not think that is needed as the run_big_write_read is very much not cached.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's more about unsafe journaling actually

Comment on lines 92 to 105
use linera_views::store::AdminKeyValueStore as _;

for scenario in get_random_test_scenarios() {
let store = linera_views::scylla_db::ScyllaDbStore::new_test_store()
.await
.unwrap();
let store = store.clone_with_root_key(&[]).unwrap();
run_reads(store, scenario).await;
}
}

#[cfg(with_scylladb)]
#[tokio::test]
async fn test_reads_scylla_db_no_journaling() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Running locally those tests, it is impossible to see some differences in the timing. And running both tests takes the same runtime as one single test.

Also, I object to the no_journaling terminology:

  • The journaling is still present in the journaling. If we are in exclusive access then operation fail.
  • The difference is potentially about caching not journaling. And there is still caching, just caching of values, not absence of values.
  • But actually there is no difference. The difference between exclusive access and no exclusive access is about the checking of absence, and that caching of absence is not going to be present.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok fair. let me rename to test_reads_scylla_db_no_root_key

Comment on lines 400 to 407
match &self.lru_read_values {
None => (),
Some(lru_read_values) => {
let mut lru_read_values = lru_read_values.lock().unwrap();
lru_read_values.has_exclusive_access = true;
}
}
}
Copy link
Contributor

@MathieuDutSik MathieuDutSik Mar 8, 2025

Choose a reason for hiding this comment

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

This can be shortened as

if let Some(lru_read_values) = &self.lru_read_values {
   let mut lru_read_values = lru_read_values.lock().unwrap();
   lru_read_values.has_exclusive_access = true;
}

This could also be inlined in the clone_with_root_key.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks

Copy link
Contributor

@MathieuDutSik MathieuDutSik left a comment

Choose a reason for hiding this comment

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

Thanks for addressing the issue.

@ma2bd ma2bd merged commit 7cae5f9 into linera-io:main Mar 8, 2025
25 checks passed
@ma2bd ma2bd deleted the fix_blob_storage branch March 8, 2025 16:55
@ma2bd
Copy link
Contributor Author

ma2bd commented Mar 8, 2025

Looks good to me!

The assumption that after clone_with_root_key we have exclusive access is not something that storage guarantees, is it? It's just that in our use case, all cloned stores are for root views, and those are always only accessed by a single worker?

Yes that's correct

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.

3 participants