Ledger-tool recreate snapshot of starting snapshots
Co-authored-by: Carl Lin <carl@solana.com>
This commit is contained in:
parent
ca35bb3ac8
commit
51d8f36dae
|
@ -820,118 +820,121 @@ fn load_frozen_forks(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let dev_halt_at_slot = opts.dev_halt_at_slot.unwrap_or(std::u64::MAX);
|
let dev_halt_at_slot = opts.dev_halt_at_slot.unwrap_or(std::u64::MAX);
|
||||||
while !pending_slots.is_empty() {
|
if root_bank.slot() != dev_halt_at_slot {
|
||||||
let (meta, bank, last_entry_hash) = pending_slots.pop().unwrap();
|
while !pending_slots.is_empty() {
|
||||||
let slot = bank.slot();
|
let (meta, bank, last_entry_hash) = pending_slots.pop().unwrap();
|
||||||
if last_status_report.elapsed() > Duration::from_secs(2) {
|
let slot = bank.slot();
|
||||||
let secs = last_status_report.elapsed().as_secs() as f32;
|
if last_status_report.elapsed() > Duration::from_secs(2) {
|
||||||
last_status_report = Instant::now();
|
let secs = last_status_report.elapsed().as_secs() as f32;
|
||||||
info!(
|
last_status_report = Instant::now();
|
||||||
"processing ledger: slot={}, last root slot={} slots={} slots/s={:?} txs/s={}",
|
info!(
|
||||||
|
"processing ledger: slot={}, last root slot={} slots={} slots/s={:?} txs/s={}",
|
||||||
|
slot,
|
||||||
|
last_root_slot,
|
||||||
|
slots_elapsed,
|
||||||
|
slots_elapsed as f32 / secs,
|
||||||
|
txs as f32 / secs,
|
||||||
|
);
|
||||||
|
slots_elapsed = 0;
|
||||||
|
txs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let allocated = thread_mem_usage::Allocatedp::default();
|
||||||
|
let initial_allocation = allocated.get();
|
||||||
|
|
||||||
|
let mut progress = ConfirmationProgress::new(last_entry_hash);
|
||||||
|
|
||||||
|
if process_single_slot(
|
||||||
|
blockstore,
|
||||||
|
&bank,
|
||||||
|
opts,
|
||||||
|
recyclers,
|
||||||
|
&mut progress,
|
||||||
|
transaction_status_sender.clone(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
txs += progress.num_txs;
|
||||||
|
|
||||||
|
// Block must be frozen by this point, otherwise `process_single_slot` would
|
||||||
|
// have errored above
|
||||||
|
assert!(bank.is_frozen());
|
||||||
|
all_banks.insert(bank.slot(), bank.clone());
|
||||||
|
|
||||||
|
// If we've reached the last known root in blockstore, start looking
|
||||||
|
// for newer cluster confirmed roots
|
||||||
|
let new_root_bank = {
|
||||||
|
if *root == max_root {
|
||||||
|
supermajority_root_from_vote_accounts(
|
||||||
|
bank.slot(),
|
||||||
|
bank.total_epoch_stake(),
|
||||||
|
bank.vote_accounts(),
|
||||||
|
).and_then(|supermajority_root| {
|
||||||
|
if supermajority_root > *root {
|
||||||
|
// If there's a cluster confirmed root greater than our last
|
||||||
|
// replayed root, then beccause the cluster confirmed root should
|
||||||
|
// be descended from our last root, it must exist in `all_banks`
|
||||||
|
let cluster_root_bank = all_banks.get(&supermajority_root).unwrap();
|
||||||
|
|
||||||
|
// cluster root must be a descendant of our root, otherwise something
|
||||||
|
// is drastically wrong
|
||||||
|
assert!(cluster_root_bank.ancestors.contains_key(root));
|
||||||
|
info!("blockstore processor found new cluster confirmed root: {}, observed in bank: {}", cluster_root_bank.slot(), bank.slot());
|
||||||
|
Some(cluster_root_bank)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if blockstore.is_root(slot) {
|
||||||
|
Some(&bank)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(new_root_bank) = new_root_bank {
|
||||||
|
*root = new_root_bank.slot();
|
||||||
|
last_root_slot = new_root_bank.slot();
|
||||||
|
leader_schedule_cache.set_root(&new_root_bank);
|
||||||
|
new_root_bank.squash();
|
||||||
|
|
||||||
|
if last_free.elapsed() > Duration::from_secs(30) {
|
||||||
|
// This could take few secs; so update last_free later
|
||||||
|
new_root_bank.exhaustively_free_unused_resource();
|
||||||
|
last_free = Instant::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out all non descendants of the new root
|
||||||
|
pending_slots
|
||||||
|
.retain(|(_, pending_bank, _)| pending_bank.ancestors.contains_key(root));
|
||||||
|
initial_forks.retain(|_, fork_tip_bank| fork_tip_bank.ancestors.contains_key(root));
|
||||||
|
all_banks.retain(|_, bank| bank.ancestors.contains_key(root));
|
||||||
|
}
|
||||||
|
|
||||||
|
slots_elapsed += 1;
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
"Bank for {}slot {} is complete. {} bytes allocated",
|
||||||
|
if last_root_slot == slot { "root " } else { "" },
|
||||||
slot,
|
slot,
|
||||||
last_root_slot,
|
allocated.since(initial_allocation)
|
||||||
slots_elapsed,
|
|
||||||
slots_elapsed as f32 / secs,
|
|
||||||
txs as f32 / secs,
|
|
||||||
);
|
);
|
||||||
slots_elapsed = 0;
|
|
||||||
txs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let allocated = thread_mem_usage::Allocatedp::default();
|
process_next_slots(
|
||||||
let initial_allocation = allocated.get();
|
&bank,
|
||||||
|
&meta,
|
||||||
|
blockstore,
|
||||||
|
leader_schedule_cache,
|
||||||
|
&mut pending_slots,
|
||||||
|
&mut initial_forks,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut progress = ConfirmationProgress::new(last_entry_hash);
|
if slot >= dev_halt_at_slot {
|
||||||
|
break;
|
||||||
if process_single_slot(
|
|
||||||
blockstore,
|
|
||||||
&bank,
|
|
||||||
opts,
|
|
||||||
recyclers,
|
|
||||||
&mut progress,
|
|
||||||
transaction_status_sender.clone(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
txs += progress.num_txs;
|
|
||||||
|
|
||||||
// Block must be frozen by this point, otherwise `process_single_slot` would
|
|
||||||
// have errored above
|
|
||||||
assert!(bank.is_frozen());
|
|
||||||
all_banks.insert(bank.slot(), bank.clone());
|
|
||||||
|
|
||||||
// If we've reached the last known root in blockstore, start looking
|
|
||||||
// for newer cluster confirmed roots
|
|
||||||
let new_root_bank = {
|
|
||||||
if *root == max_root {
|
|
||||||
supermajority_root_from_vote_accounts(
|
|
||||||
bank.slot(),
|
|
||||||
bank.total_epoch_stake(),
|
|
||||||
bank.vote_accounts(),
|
|
||||||
).and_then(|supermajority_root| {
|
|
||||||
if supermajority_root > *root {
|
|
||||||
// If there's a cluster confirmed root greater than our last
|
|
||||||
// replayed root, then beccause the cluster confirmed root should
|
|
||||||
// be descended from our last root, it must exist in `all_banks`
|
|
||||||
let cluster_root_bank = all_banks.get(&supermajority_root).unwrap();
|
|
||||||
|
|
||||||
// cluster root must be a descendant of our root, otherwise something
|
|
||||||
// is drastically wrong
|
|
||||||
assert!(cluster_root_bank.ancestors.contains_key(root));
|
|
||||||
info!("blockstore processor found new cluster confirmed root: {}, observed in bank: {}", cluster_root_bank.slot(), bank.slot());
|
|
||||||
Some(cluster_root_bank)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if blockstore.is_root(slot) {
|
|
||||||
Some(&bank)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(new_root_bank) = new_root_bank {
|
|
||||||
*root = new_root_bank.slot();
|
|
||||||
last_root_slot = new_root_bank.slot();
|
|
||||||
leader_schedule_cache.set_root(&new_root_bank);
|
|
||||||
new_root_bank.squash();
|
|
||||||
|
|
||||||
if last_free.elapsed() > Duration::from_secs(30) {
|
|
||||||
// This could take few secs; so update last_free later
|
|
||||||
new_root_bank.exhaustively_free_unused_resource();
|
|
||||||
last_free = Instant::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out all non descendants of the new root
|
|
||||||
pending_slots.retain(|(_, pending_bank, _)| pending_bank.ancestors.contains_key(root));
|
|
||||||
initial_forks.retain(|_, fork_tip_bank| fork_tip_bank.ancestors.contains_key(root));
|
|
||||||
all_banks.retain(|_, bank| bank.ancestors.contains_key(root));
|
|
||||||
}
|
|
||||||
|
|
||||||
slots_elapsed += 1;
|
|
||||||
|
|
||||||
trace!(
|
|
||||||
"Bank for {}slot {} is complete. {} bytes allocated",
|
|
||||||
if last_root_slot == slot { "root " } else { "" },
|
|
||||||
slot,
|
|
||||||
allocated.since(initial_allocation)
|
|
||||||
);
|
|
||||||
|
|
||||||
process_next_slots(
|
|
||||||
&bank,
|
|
||||||
&meta,
|
|
||||||
blockstore,
|
|
||||||
leader_schedule_cache,
|
|
||||||
&mut pending_slots,
|
|
||||||
&mut initial_forks,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if slot >= dev_halt_at_slot {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2607,6 +2610,37 @@ pub mod tests {
|
||||||
assert_eq!(bank.process_transaction(&fail_tx), Ok(()));
|
assert_eq!(bank.process_transaction(&fail_tx), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_halt_at_slot_starting_snapshot_root() {
|
||||||
|
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(123);
|
||||||
|
|
||||||
|
// Create roots at slots 0, 1
|
||||||
|
let forks = tr(0) / tr(1);
|
||||||
|
let ledger_path = get_tmp_ledger_path!();
|
||||||
|
let blockstore = Blockstore::open(&ledger_path).unwrap();
|
||||||
|
blockstore.add_tree(
|
||||||
|
forks,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
genesis_config.ticks_per_slot,
|
||||||
|
genesis_config.hash(),
|
||||||
|
);
|
||||||
|
blockstore.set_roots(&[0, 1]).unwrap();
|
||||||
|
|
||||||
|
// Specify halting at slot 0
|
||||||
|
let opts = ProcessOptions {
|
||||||
|
poh_verify: true,
|
||||||
|
dev_halt_at_slot: Some(0),
|
||||||
|
..ProcessOptions::default()
|
||||||
|
};
|
||||||
|
let (bank_forks, _leader_schedule) =
|
||||||
|
process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap();
|
||||||
|
|
||||||
|
// Should be able to fetch slot 0 because we specified halting at slot 0, even
|
||||||
|
// if there is a greater root at slot 1.
|
||||||
|
assert!(bank_forks.get(0).is_some());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_blockstore_from_root() {
|
fn test_process_blockstore_from_root() {
|
||||||
let GenesisConfigInfo {
|
let GenesisConfigInfo {
|
||||||
|
|
Loading…
Reference in New Issue