-
Notifications
You must be signed in to change notification settings - Fork 289
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
Feat schema batch write v2 #3964
base: master
Are you sure you want to change the base?
Changes from all commits
edfa215
18a1407
7f92c35
ed71e12
1105bb3
0940095
87b51c1
50c6bc9
dea50c5
b78ae76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,6 +148,7 @@ impl AccountManager { | |
None => Account::create_readonly(address, public_key, self.store.clone())?, | ||
}; | ||
|
||
// todo: merge following single writes to one schema-batch-write: add_address + set_default | ||
self.store.add_address(*account.address())?; | ||
|
||
// if it's the first address, set it default. | ||
|
@@ -195,7 +196,8 @@ impl AccountManager { | |
"Can not find account_info by address:{}, clear it from address list.", | ||
account | ||
); | ||
self.store.remove_address(account)?; | ||
// todo: merge single writes to one batch-write | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider implementing batch writes for address removal. The |
||
self.store.remove_address_from_all(account)?; | ||
} | ||
} | ||
Ok(res) | ||
|
@@ -254,6 +256,7 @@ impl AccountManager { | |
} | ||
} | ||
|
||
// todo: merge single writes to one batch-write | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implement batch writes for setting default account. The - // todo: merge single writes to one batch-write
+ self.store.set_default_account_batch(&address)?;
|
||
pub fn set_default_account(&self, address: AccountAddress) -> AccountResult<AccountInfo> { | ||
let mut account_info = self | ||
.account_info(address)? | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
use anyhow::Result; | ||
use bcs_ext::BCSCodec; | ||
use serde::{Deserialize, Serialize}; | ||
use starcoin_schemadb::{ | ||
define_schema, | ||
schema::{KeyCodec, ValueCodec}, | ||
ColumnFamilyName, | ||
}; | ||
use starcoin_types::account_address::AccountAddress; | ||
use starcoin_types::account_config::token_code::TokenCode; | ||
|
||
pub const ACCEPTED_TOKEN_PREFIX_NAME: ColumnFamilyName = "accepted_token"; | ||
|
||
define_schema!( | ||
AcceptedToken, | ||
AccountAddress, | ||
AcceptedTokens, | ||
ACCEPTED_TOKEN_PREFIX_NAME | ||
); | ||
|
||
impl KeyCodec<AcceptedToken> for AccountAddress { | ||
fn encode_key(&self) -> Result<Vec<u8>> { | ||
Ok(self.to_vec()) | ||
} | ||
|
||
fn decode_key(data: &[u8]) -> Result<Self> { | ||
AccountAddress::try_from(data).map_err(Into::into) | ||
} | ||
} | ||
|
||
#[derive(Default, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] | ||
pub struct AcceptedTokens(pub Vec<TokenCode>); | ||
|
||
impl ValueCodec<AcceptedToken> for AcceptedTokens { | ||
fn encode_value(&self) -> Result<Vec<u8>> { | ||
self.0.encode() | ||
} | ||
|
||
fn decode_value(data: &[u8]) -> Result<Self> { | ||
<Vec<TokenCode>>::decode(data).map(AcceptedTokens) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,50 @@ | ||||||||||||||||||||||||||
use anyhow::Result; | ||||||||||||||||||||||||||
use bcs_ext::BCSCodec; | ||||||||||||||||||||||||||
use serde::{Deserialize, Serialize}; | ||||||||||||||||||||||||||
use starcoin_schemadb::{ | ||||||||||||||||||||||||||
define_schema, | ||||||||||||||||||||||||||
schema::{KeyCodec, ValueCodec}, | ||||||||||||||||||||||||||
ColumnFamilyName, | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
use starcoin_types::account_address::AccountAddress; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
pub const GLOBAL_PREFIX_NAME: ColumnFamilyName = "global"; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
define_schema!( | ||||||||||||||||||||||||||
GlobalSetting, | ||||||||||||||||||||||||||
GlobalSettingKey, | ||||||||||||||||||||||||||
GlobalValue, | ||||||||||||||||||||||||||
GLOBAL_PREFIX_NAME | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] | ||||||||||||||||||||||||||
pub enum GlobalSettingKey { | ||||||||||||||||||||||||||
DefaultAddress, | ||||||||||||||||||||||||||
/// FIXME: once db support iter, remove this. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Track the FIXME for future improvements. The FIXME comment suggests that the Would you like me to open a GitHub issue to track this FIXME? |
||||||||||||||||||||||||||
AllAddresses, | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
Comment on lines
+20
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider removing or refactoring the FIXME comment. The FIXME comment on line 23 suggests future improvements when database iteration support is available. It's important to track this in the project's issue tracker for future reference. - /// FIXME: once db support iter, remove this.
+ // TODO: Remove AllAddresses once DB supports iteration. Tracked in issue #123 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] | ||||||||||||||||||||||||||
pub struct GlobalValue { | ||||||||||||||||||||||||||
pub(crate) addresses: Vec<AccountAddress>, | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
impl KeyCodec<GlobalSetting> for GlobalSettingKey { | ||||||||||||||||||||||||||
fn encode_key(&self) -> Result<Vec<u8>> { | ||||||||||||||||||||||||||
self.encode() | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
fn decode_key(data: &[u8]) -> Result<Self> { | ||||||||||||||||||||||||||
GlobalSettingKey::decode(data) | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
impl ValueCodec<GlobalSetting> for GlobalValue { | ||||||||||||||||||||||||||
fn encode_value(&self) -> Result<Vec<u8>> { | ||||||||||||||||||||||||||
self.addresses.encode() | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
fn decode_value(data: &[u8]) -> Result<Self> { | ||||||||||||||||||||||||||
<Vec<AccountAddress>>::decode(data).map(|addresses| GlobalValue { addresses }) | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use anyhow::Result; | ||
use starcoin_schemadb::schema::Schema; | ||
use starcoin_storage::cache_storage::GCacheStorage; | ||
use std::sync::Arc; | ||
|
||
mod accepted_token; | ||
mod global_setting; | ||
mod private_key; | ||
mod public_key; | ||
mod setting; | ||
|
||
pub(crate) use accepted_token::*; | ||
pub(crate) use global_setting::*; | ||
pub(crate) use private_key::*; | ||
pub(crate) use public_key::*; | ||
pub(crate) use setting::*; | ||
use starcoin_schemadb::{db::DBStorage as DB, SchemaBatch}; | ||
|
||
#[derive(Clone)] | ||
pub(super) struct AccountStore<S: Schema> { | ||
cache: Arc<GCacheStorage<S::Key, S::Value>>, | ||
db: Option<Arc<DB>>, | ||
} | ||
|
||
impl<S: Schema> AccountStore<S> { | ||
// create an memory-based store | ||
pub fn new() -> Self { | ||
Self { | ||
cache: Arc::new(GCacheStorage::<S::Key, S::Value>::new(None)), | ||
db: None, | ||
} | ||
} | ||
pub fn new_with_db(db: &Arc<DB>) -> Self { | ||
Self { | ||
cache: Arc::new(GCacheStorage::<S::Key, S::Value>::new(None)), | ||
db: Some(Arc::clone(db)), | ||
} | ||
} | ||
|
||
pub fn get(&self, key: &S::Key) -> Result<Option<S::Value>> { | ||
self.cache | ||
.get_inner(key) | ||
.map(|val| Ok(Some(val))) | ||
.unwrap_or_else(|| { | ||
self.db | ||
.as_ref() | ||
.map_or_else(|| Ok(None), |db| db.get::<S>(key)) | ||
}) | ||
} | ||
|
||
pub fn put(&self, key: S::Key, value: S::Value) -> Result<()> { | ||
self.db | ||
.as_ref() | ||
.map_or_else(|| Ok(()), |db| db.put::<S>(&key, &value)) | ||
.map(|_| { | ||
self.cache.put_inner(key, value); | ||
}) | ||
} | ||
|
||
pub fn remove(&self, key: &S::Key) -> Result<()> { | ||
self.db | ||
.as_ref() | ||
.map_or_else(|| Ok(()), |db| db.remove::<S>(key)) | ||
.map(|_| { | ||
self.cache.remove_inner(key); | ||
}) | ||
} | ||
|
||
pub fn put_batch(&self, key: S::Key, value: S::Value, batch: &SchemaBatch) -> Result<()> { | ||
batch.put::<S>(&key, &value)?; | ||
self.put(key, value) | ||
} | ||
|
||
pub fn remove_batch(&self, key: &S::Key, batch: &SchemaBatch) -> Result<()> { | ||
batch.delete::<S>(key)?; | ||
self.remove(key) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
use anyhow::Result; | ||
use starcoin_schemadb::{ | ||
define_schema, | ||
schema::{KeyCodec, ValueCodec}, | ||
ColumnFamilyName, | ||
}; | ||
use starcoin_types::account_address::AccountAddress; | ||
|
||
pub const ENCRYPTED_PRIVATE_KEY_PREFIX_NAME: ColumnFamilyName = "encrypted_private_key"; | ||
|
||
define_schema!( | ||
PrivateKey, | ||
AccountAddress, | ||
EncryptedPrivateKey, | ||
ENCRYPTED_PRIVATE_KEY_PREFIX_NAME | ||
); | ||
|
||
impl KeyCodec<PrivateKey> for AccountAddress { | ||
fn encode_key(&self) -> Result<Vec<u8>> { | ||
Ok(self.to_vec()) | ||
} | ||
|
||
fn decode_key(data: &[u8]) -> Result<Self> { | ||
AccountAddress::try_from(data).map_err(Into::into) | ||
} | ||
} | ||
|
||
#[derive(Default, Debug, Clone, PartialEq, Eq)] | ||
pub struct EncryptedPrivateKey(pub Vec<u8>); | ||
impl From<Vec<u8>> for EncryptedPrivateKey { | ||
fn from(s: Vec<u8>) -> Self { | ||
Self(s) | ||
} | ||
} | ||
|
||
impl ValueCodec<PrivateKey> for EncryptedPrivateKey { | ||
fn encode_value(&self) -> Result<Vec<u8>> { | ||
Ok(self.0.clone()) | ||
} | ||
|
||
fn decode_value(data: &[u8]) -> Result<Self> { | ||
Ok(EncryptedPrivateKey(data.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.
Implement batch writes for performance optimization.
The
TODO
comment indicates the need to merge single writes into one schema-batch-write. This would significantly improve performance by reducing the number of I/O operations.