-
Notifications
You must be signed in to change notification settings - Fork 556
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 list_root_keys
to the AdminKeyValueStore
#3142
base: main
Are you sure you want to change the base?
Conversation
@@ -92,11 +92,19 @@ async fn get_config_internal( | |||
} | |||
} | |||
|
|||
/// The DynamoDb forbids the iteration over the partition keys. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// The DynamoDb forbids the iteration over the partition keys. | |
/// DynamoDB forbids the iteration over the partition keys. | |
/// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, thanks.
/// The DynamoDb forbids the iteration over the partition keys. | ||
/// Therefore we use a special partition_key named [1] for storing | ||
/// the root keys. For normal root_keys, we simply put a 0 in front | ||
/// therefore no intersection is possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this comment be on PARTITION_KEY_ROOT_KEY
?
Currently it's associated with PARTITION_ATTRIBUTE
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, corrected.
let mut vec = vec![0]; | ||
vec.extend(root_key); | ||
vec | ||
let mut start_key = vec![0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is meant to be the same as EMPTY_ROOT_KEY
, is it?
let mut start_key = vec![0]; | |
let mut start_key = EMPTY_ROOT_KEY.to_vec(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
@@ -308,7 +314,7 @@ impl TransactionBuilder { | |||
value: Vec<u8>, | |||
store: &DynamoDbStoreInternal, | |||
) -> Result<(), DynamoDbStoreInternalError> { | |||
let transact = store.build_put_transact(&self.root_key, key, value)?; | |||
let transact = store.build_put_transact(&self.start_key, key, value)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(transact
is an uncommon abbreviation for transaction
. I'd either use the full word or txn
maybe?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I used transaction
in the DynamoDb code.
linera-client/src/client_options.rs
Outdated
@@ -964,6 +964,14 @@ pub enum DatabaseToolCommand { | |||
#[arg(long = "storage")] | |||
storage_config: String, | |||
}, | |||
|
|||
/// List the rot keys of the database |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// List the rot keys of the database | |
/// List the root keys of the database |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you.
linera-client/src/storage.rs
Outdated
match self { | ||
StoreConfig::Memory(_, _) => Err(ViewError::StoreError { | ||
backend: "memory".to_string(), | ||
error: "list_all is not supported for the memory storage".to_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error: "list_all is not supported for the memory storage".to_string(), | |
error: "list_all_root_keys is not supported for the memory storage".to_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
} | ||
|
||
message ReplyInsertRootKey { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(We could use google.protobuf.Empty
instead of all those empty types. Not sure if that's preferable, but we do it in rpc.proto
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, that is great.
linera-views/tests/admin_tests.rs
Outdated
root_key_admin_test::<DynamoDbStore>().await; | ||
} | ||
|
||
#[cfg(with_scylladb)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be more readable to use test_case
for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thank you.
|
||
/// Obtains the list of existing namespaces. | ||
async fn list_all(config: &Self::Config) -> Result<Vec<String>, Self::Error>; | ||
|
||
/// Lists the root keys of the namespace. | ||
/// It is possible that some root_keys have no keys. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean "some namespaces have no root keys"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I really mean that.
What happens is that for each key, there is at least one root key.
But for some root key, there is no corresponding key.
- For ScyllaDb, we will have that the insertion is done via
(root_ley, key)
which lead to the fact that for each key we have a matching root_key. - For others the root key has to be stored as a key. That creation is done just at
fn connect
orfn clone_with_root_key
. So, the creation itself creates root keys. But the key is not yet written.
What this designs allow is to access to all the keys and so to to transfer files from one storage to another.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I think I need some more explanations (or better: code comments, or pointers where to find them) before I can review this. I'm confused how the keys are structured and represented in the different databases. E.g. I thought the first byte was there to distinguish between actual key-value pairs, and markers for the existence of namespaces; in what way does that relate to root keys at all, and why is it changing now?
let set_root_keys = root_keys.iter().cloned().collect::<HashSet<_>>(); | ||
for read_root_key in &read_root_keys { | ||
assert!(set_root_keys.contains(read_root_key)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only asserts that read_root_keys
are a subset of set_root_keys
. Shouldn't we assert that they are equal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No.
For a database like ScyllaDb, the root keys would be inserted only if there is a corresponding key. This is why there is a size_select
that could be 0.
let mut root_keys = HashSet::new(); | ||
while let Some(row) = rows.next().await { | ||
let (root_key,) = row?; | ||
let root_key = root_key[1..].to_vec(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we drop the first byte? Is this KeyTag::Key
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In ScyllaDb, a key has to hava non-zero length. Therefore, we have a function get_big_root_key
that adds a 0 at the first entry.
} | ||
let mut full_key1 = self.start_key.to_vec(); | ||
full_key1.extend(&key_prefix); | ||
let full_key2 = get_upper_bound_option(&full_key1).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Why can't this be None
? Is this because the edge case is gone, because the first byte is never 255
?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly.
Added, documentation.
get_root_keys
to the AdminKeyValueStore
list_root_keys
to the AdminKeyValueStore
Implement the feature to the linera-storage-service.
Make the "list_root_keys" available from the CLI.
094fd65
to
3e78982
Compare
Motivation
We need to have the feature of accessing to the list of root keys in order to have mutation function and accessing to the list of chain ids of a storage.
Fixes #3085
Proposal
The implementation causes some problems:
[255, ..., 255]
disappears.get_root_keys
will not be the same on different storage. If storage has been created withfn create
but no key is inserted then in ScyllaDb / DynamoDb it will not show the root_key but in RocksDb it will appear.The end result is that the
fn connect
becomes slower for RocksDb, StorageService, IndexedDb but this is I think fine as the issue of performance shows up in other operations.Test Plan
One test has been added for this feature.
Release Plan
No impact on the TestNet / DevNet. It can follow the normal release plan.
Links
None.