use {
super::{repair_handler::RepairHandler, repair_response},
solana_clock::Slot,
solana_ledger::{blockstore::Blockstore, shred::Nonce},
solana_perf::packet::{BytesPacket, BytesPacketBatch, PacketBatch},
std::{net::SocketAddr, sync::Arc},
};
pub(crate) struct StandardRepairHandler {
blockstore: Arc<Blockstore>,
}
impl StandardRepairHandler {
pub(crate) fn new(blockstore: Arc<Blockstore>) -> Self {
Self { blockstore }
}
}
impl RepairHandler for StandardRepairHandler {
fn blockstore(&self) -> &Blockstore {
&self.blockstore
}
fn repair_response_packet(
&self,
slot: Slot,
shred_index: u64,
dest: &SocketAddr,
nonce: Nonce,
) -> Option<BytesPacket> {
repair_response::repair_response_packet(
self.blockstore.as_ref(),
slot,
shred_index,
dest,
nonce,
)
}
fn run_orphan(
&self,
from_addr: &SocketAddr,
slot: Slot,
max_responses: usize,
nonce: Nonce,
) -> Option<PacketBatch> {
let mut res = BytesPacketBatch::with_capacity(max_responses);
let packets = std::iter::successors(self.blockstore.meta(slot).ok()?, |meta| {
self.blockstore.meta(meta.parent_slot?).ok()?
})
.map_while(|meta| {
repair_response::repair_response_packet(
self.blockstore.as_ref(),
meta.slot,
meta.received.checked_sub(1u64)?,
from_addr,
nonce,
)
});
for packet in packets.take(max_responses) {
res.push(packet);
}
(!res.is_empty()).then(|| PacketBatch::Bytes(res))
}
}