Add ledger-tool for restoring roots to the Roots CF (#17045)

* Add ledger-tool for restoring roots to the Roots CF

* Print successful repair data, and repair in chunks

* Add parameter to limit num slots checked for root repair
This commit is contained in:
Tyera Eulberg 2021-05-06 14:12:01 -06:00 committed by GitHub
parent dc0429f5e6
commit ddfbae260f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 79 additions and 0 deletions

View File

@ -729,6 +729,7 @@ fn main() {
}
const DEFAULT_ROOT_COUNT: &str = "1";
const DEFAULT_MAX_SLOTS_ROOT_REPAIR: &str = "2000";
solana_logger::setup_with_default("solana=info");
let starting_slot_arg = Arg::with_name("starting_slot")
@ -1336,6 +1337,34 @@ fn main() {
.help("Number of roots in the output"),
)
)
.subcommand(
SubCommand::with_name("repair-roots")
.about("Traverses the AncestorIterator backward from a last known root \
to restore missing roots to the Root column")
.arg(
Arg::with_name("start_root")
.long("before")
.value_name("NUM")
.takes_value(true)
.help("First good root after the range to repair")
)
.arg(
Arg::with_name("end_root")
.long("until")
.value_name("NUM")
.takes_value(true)
.help("Last slot to check for root repair")
)
.arg(
Arg::with_name("max_slots")
.long("repair-limit")
.value_name("NUM")
.takes_value(true)
.default_value(DEFAULT_MAX_SLOTS_ROOT_REPAIR)
.required(true)
.help("Override the maximum number of slots to check for root repair")
)
)
.subcommand(
SubCommand::with_name("analyze-storage")
.about("Output statistics in JSON format about \
@ -2798,6 +2827,56 @@ fn main() {
}
});
}
("repair-roots", Some(arg_matches)) => {
let blockstore = open_blockstore(
&ledger_path,
AccessType::TryPrimaryThenSecondary,
wal_recovery_mode,
);
let start_root = if let Some(root) = arg_matches.value_of("start_root") {
Slot::from_str(root).expect("Before root must be a number")
} else {
blockstore.max_root()
};
let max_slots = value_t_or_exit!(arg_matches, "max_slots", u64);
let end_root = if let Some(root) = arg_matches.value_of("end_root") {
Slot::from_str(root).expect("Until root must be a number")
} else {
start_root.saturating_sub(max_slots)
};
assert!(start_root > end_root);
assert!(blockstore.is_root(start_root));
let num_slots = start_root - end_root - 1; // Adjust by one since start_root need not be checked
if arg_matches.is_present("end_root") && num_slots > max_slots {
eprintln!(
"Requested range {} too large, max {}. \
Either adjust `--until` value, or pass a larger `--repair-limit` \
to override the limit",
num_slots, max_slots,
);
exit(1);
}
let ancestor_iterator =
AncestorIterator::new(start_root, &blockstore).take_while(|&slot| slot >= end_root);
let roots_to_fix: Vec<_> = ancestor_iterator
.filter(|slot| !blockstore.is_root(*slot))
.collect();
if !roots_to_fix.is_empty() {
eprintln!("{} slots to be rooted", roots_to_fix.len());
for chunk in roots_to_fix.chunks(100) {
eprintln!("{:?}", chunk);
blockstore.set_roots(&roots_to_fix).unwrap_or_else(|err| {
eprintln!("Unable to set roots {:?}: {}", roots_to_fix, err);
exit(1);
});
}
} else {
println!(
"No missing roots found in range {} to {}",
end_root, start_root
);
}
}
("bounds", Some(arg_matches)) => {
let blockstore = open_blockstore(
&ledger_path,