ledger-tool: stream output of `accounts` subcommand
This commit is contained in:
parent
57798fae9c
commit
53a579bed1
|
@ -11,7 +11,10 @@ use {
|
||||||
itertools::Itertools,
|
itertools::Itertools,
|
||||||
log::*,
|
log::*,
|
||||||
regex::Regex,
|
regex::Regex,
|
||||||
serde::Serialize,
|
serde::{
|
||||||
|
ser::{SerializeSeq, Serializer},
|
||||||
|
Serialize,
|
||||||
|
},
|
||||||
serde_json::json,
|
serde_json::json,
|
||||||
solana_account_decoder::{UiAccount, UiAccountData, UiAccountEncoding},
|
solana_account_decoder::{UiAccount, UiAccountData, UiAccountEncoding},
|
||||||
solana_clap_utils::{
|
solana_clap_utils::{
|
||||||
|
@ -20,6 +23,7 @@ use {
|
||||||
is_parsable, is_pow2, is_pubkey, is_pubkey_or_keypair, is_slot, is_valid_percentage,
|
is_parsable, is_pow2, is_pubkey, is_pubkey_or_keypair, is_slot, is_valid_percentage,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
solana_cli_output::{CliAccount, CliAccountNewConfig, OutputFormat},
|
||||||
solana_core::{
|
solana_core::{
|
||||||
system_monitor_service::SystemMonitorService, validator::move_and_async_delete_path,
|
system_monitor_service::SystemMonitorService, validator::move_and_async_delete_path,
|
||||||
},
|
},
|
||||||
|
@ -39,6 +43,7 @@ use {
|
||||||
},
|
},
|
||||||
solana_measure::{measure, measure::Measure},
|
solana_measure::{measure, measure::Measure},
|
||||||
solana_runtime::{
|
solana_runtime::{
|
||||||
|
accounts::Accounts,
|
||||||
accounts_background_service::{
|
accounts_background_service::{
|
||||||
AbsRequestHandlers, AbsRequestSender, AccountsBackgroundService,
|
AbsRequestHandlers, AbsRequestSender, AccountsBackgroundService,
|
||||||
PrunedBanksRequestHandler, SnapshotRequestHandler,
|
PrunedBanksRequestHandler, SnapshotRequestHandler,
|
||||||
|
@ -46,7 +51,7 @@ use {
|
||||||
accounts_db::{AccountsDbConfig, FillerAccountsConfig},
|
accounts_db::{AccountsDbConfig, FillerAccountsConfig},
|
||||||
accounts_index::{AccountsIndexConfig, IndexLimitMb, ScanConfig},
|
accounts_index::{AccountsIndexConfig, IndexLimitMb, ScanConfig},
|
||||||
accounts_update_notifier_interface::AccountsUpdateNotifier,
|
accounts_update_notifier_interface::AccountsUpdateNotifier,
|
||||||
bank::{Bank, RewardCalculationEvent},
|
bank::{Bank, RewardCalculationEvent, TotalAccountsStats},
|
||||||
bank_forks::BankForks,
|
bank_forks::BankForks,
|
||||||
cost_model::CostModel,
|
cost_model::CostModel,
|
||||||
cost_tracker::CostTracker,
|
cost_tracker::CostTracker,
|
||||||
|
@ -3377,52 +3382,69 @@ fn main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
let bank = bank_forks.read().unwrap().working_bank();
|
let bank = bank_forks.read().unwrap().working_bank();
|
||||||
let mut measure = Measure::start("getting accounts");
|
let mut serializer = serde_json::Serializer::new(stdout());
|
||||||
let accounts: BTreeMap<_, _> = bank
|
let (summarize, mut json_serializer) =
|
||||||
.get_all_accounts_with_modified_slots()
|
match OutputFormat::from_matches(arg_matches, "output_format", false) {
|
||||||
.unwrap()
|
OutputFormat::Json | OutputFormat::JsonCompact => {
|
||||||
.into_iter()
|
(false, Some(serializer.serialize_seq(None).unwrap()))
|
||||||
.filter(|(pubkey, _account, _slot)| {
|
}
|
||||||
include_sysvars || !solana_sdk::sysvar::is_sysvar_id(pubkey)
|
_ => (true, None),
|
||||||
})
|
|
||||||
.map(|(pubkey, account, slot)| (pubkey, (account, slot)))
|
|
||||||
.collect();
|
|
||||||
measure.stop();
|
|
||||||
info!("{}", measure);
|
|
||||||
|
|
||||||
let mut measure = Measure::start("calculating total accounts stats");
|
|
||||||
let total_accounts_stats = bank.calculate_total_accounts_stats(
|
|
||||||
accounts
|
|
||||||
.iter()
|
|
||||||
.map(|(pubkey, (account, _slot))| (pubkey, account)),
|
|
||||||
);
|
|
||||||
measure.stop();
|
|
||||||
info!("{}", measure);
|
|
||||||
|
|
||||||
let print_account_contents = !arg_matches.is_present("no_account_contents");
|
|
||||||
if print_account_contents {
|
|
||||||
let print_account_data = !arg_matches.is_present("no_account_data");
|
|
||||||
let print_encoding_format = match arg_matches.value_of("encoding") {
|
|
||||||
Some("jsonParsed") => UiAccountEncoding::JsonParsed,
|
|
||||||
Some("base64") => UiAccountEncoding::Base64,
|
|
||||||
Some("base64+zstd") => UiAccountEncoding::Base64Zstd,
|
|
||||||
_ => UiAccountEncoding::Base64,
|
|
||||||
};
|
};
|
||||||
let mut measure = Measure::start("printing account contents");
|
let mut total_accounts_stats = TotalAccountsStats::default();
|
||||||
for (pubkey, (account, slot)) in accounts.into_iter() {
|
let rent_collector = bank.rent_collector();
|
||||||
output_account(
|
let print_account_contents = !arg_matches.is_present("no_account_contents");
|
||||||
&pubkey,
|
let print_account_data = !arg_matches.is_present("no_account_data");
|
||||||
&account,
|
let data_encoding = match arg_matches.value_of("encoding") {
|
||||||
Some(slot),
|
Some("jsonParsed") => UiAccountEncoding::JsonParsed,
|
||||||
print_account_data,
|
Some("base64") => UiAccountEncoding::Base64,
|
||||||
print_encoding_format,
|
Some("base64+zstd") => UiAccountEncoding::Base64Zstd,
|
||||||
);
|
_ => UiAccountEncoding::Base64,
|
||||||
}
|
};
|
||||||
measure.stop();
|
let cli_account_new_config = CliAccountNewConfig {
|
||||||
info!("{}", measure);
|
data_encoding,
|
||||||
}
|
..CliAccountNewConfig::default()
|
||||||
|
};
|
||||||
|
let scan_func = |some_account_tuple: Option<(&Pubkey, AccountSharedData, Slot)>| {
|
||||||
|
if let Some((pubkey, account, slot)) = some_account_tuple
|
||||||
|
.filter(|(_, account, _)| Accounts::is_loadable(account.lamports()))
|
||||||
|
{
|
||||||
|
if !include_sysvars && solana_sdk::sysvar::is_sysvar_id(pubkey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
println!("{:#?}", total_accounts_stats);
|
total_accounts_stats.accumulate_account(pubkey, &account, rent_collector);
|
||||||
|
|
||||||
|
if print_account_contents {
|
||||||
|
if let Some(json_serializer) = json_serializer.as_mut() {
|
||||||
|
let cli_account = CliAccount::new_with_config(
|
||||||
|
pubkey,
|
||||||
|
&account,
|
||||||
|
&cli_account_new_config,
|
||||||
|
);
|
||||||
|
json_serializer.serialize_element(&cli_account).unwrap();
|
||||||
|
} else {
|
||||||
|
output_account(
|
||||||
|
pubkey,
|
||||||
|
&account,
|
||||||
|
Some(slot),
|
||||||
|
print_account_data,
|
||||||
|
data_encoding,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut measure = Measure::start("scanning accounts");
|
||||||
|
bank.scan_all_accounts_with_modified_slots(scan_func)
|
||||||
|
.unwrap();
|
||||||
|
measure.stop();
|
||||||
|
info!("{}", measure);
|
||||||
|
if let Some(json_serializer) = json_serializer {
|
||||||
|
json_serializer.end().unwrap();
|
||||||
|
}
|
||||||
|
if summarize {
|
||||||
|
println!("\n{:#?}", total_accounts_stats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
("capitalization", Some(arg_matches)) => {
|
("capitalization", Some(arg_matches)) => {
|
||||||
let halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok();
|
let halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok();
|
||||||
|
|
|
@ -935,7 +935,7 @@ impl Accounts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_loadable(lamports: u64) -> bool {
|
pub fn is_loadable(lamports: u64) -> bool {
|
||||||
// Don't ever load zero lamport accounts into runtime because
|
// Don't ever load zero lamport accounts into runtime because
|
||||||
// the existence of zero-lamport accounts are never deterministic!!
|
// the existence of zero-lamport accounts are never deterministic!!
|
||||||
lamports > 0
|
lamports > 0
|
||||||
|
@ -1113,6 +1113,19 @@ impl Accounts {
|
||||||
.map(|_| collector)
|
.map(|_| collector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scan_all<F>(
|
||||||
|
&self,
|
||||||
|
ancestors: &Ancestors,
|
||||||
|
bank_id: BankId,
|
||||||
|
scan_func: F,
|
||||||
|
) -> ScanResult<()>
|
||||||
|
where
|
||||||
|
F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
|
||||||
|
{
|
||||||
|
self.accounts_db
|
||||||
|
.scan_accounts(ancestors, bank_id, scan_func, &ScanConfig::default())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hold_range_in_memory<R>(
|
pub fn hold_range_in_memory<R>(
|
||||||
&self,
|
&self,
|
||||||
range: &R,
|
range: &R,
|
||||||
|
|
|
@ -6589,6 +6589,15 @@ impl Bank {
|
||||||
self.rc.accounts.load_all(&self.ancestors, self.bank_id)
|
self.rc.accounts.load_all(&self.ancestors, self.bank_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scan_all_accounts_with_modified_slots<F>(&self, scan_func: F) -> ScanResult<()>
|
||||||
|
where
|
||||||
|
F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
|
||||||
|
{
|
||||||
|
self.rc
|
||||||
|
.accounts
|
||||||
|
.scan_all(&self.ancestors, self.bank_id, scan_func)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_program_accounts_modified_since_parent(
|
pub fn get_program_accounts_modified_since_parent(
|
||||||
&self,
|
&self,
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
|
|
Loading…
Reference in New Issue