Skip to content

Commit 3f8a4c7

Browse files
committed
Using an LRU when receving chunks
1 parent 41f5e53 commit 3f8a4c7

1 file changed

Lines changed: 23 additions & 12 deletions

File tree

pixie-uefi/src/flash.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use core::{cell::RefCell, mem, net::SocketAddrV4};
77
use futures::future::{select, Either};
88
use log::info;
99
use lz4_flex::decompress;
10-
use pixie_shared::{Image, TcpRequest, UdpRequest, BODY_LEN, CHUNKS_PORT, HEADER_LEN};
10+
use pixie_shared::{ChunkHash, Image, TcpRequest, UdpRequest, BODY_LEN, CHUNKS_PORT, HEADER_LEN};
1111
use uefi::proto::console::text::Color;
1212

1313
struct PartialChunk {
@@ -57,21 +57,24 @@ struct Stats {
5757
requested: usize,
5858
}
5959

60-
async fn handle_packet(
60+
fn handle_packet(
6161
buf: &[u8],
62-
chunks_info: &mut BTreeMap<[u8; 32], (usize, usize, Vec<usize>)>,
63-
received: &mut BTreeMap<[u8; 32], PartialChunk>,
62+
chunks_info: &mut BTreeMap<ChunkHash, (usize, usize, Vec<usize>)>,
63+
received: &mut BTreeMap<ChunkHash, PartialChunk>,
64+
last_seen: &mut Vec<ChunkHash>,
6465
) -> Result<Option<(Vec<usize>, Vec<u8>)>> {
65-
let hash: &[u8; 32] = buf[..32].try_into().unwrap();
66+
let hash: ChunkHash = buf[..32].try_into().unwrap();
6667
let index = u16::from_le_bytes(buf[32..34].try_into().unwrap()) as usize;
67-
let csize = match chunks_info.get(hash) {
68+
let csize = match chunks_info.get(&hash) {
6869
Some(&(_, csize, _)) => csize,
6970
_ => return Ok(None),
7071
};
7172

7273
let pchunk = received
73-
.entry(*hash)
74+
.entry(hash)
7475
.or_insert_with(|| PartialChunk::new(csize));
76+
last_seen.retain(|x| x != &hash);
77+
last_seen.push(hash);
7578

7679
let rot_index = (index as u16).wrapping_add(32) as usize;
7780
match &mut pchunk.missing_first[rot_index] {
@@ -101,8 +104,9 @@ async fn handle_packet(
101104
}
102105
}
103106

104-
let (size, _, pos) = chunks_info.remove(hash).unwrap();
105-
let mut pchunk = received.remove(hash).unwrap();
107+
let (size, _, pos) = chunks_info.remove(&hash).unwrap();
108+
let mut pchunk = received.remove(&hash).unwrap();
109+
last_seen.retain(|x| x != &hash);
106110

107111
let mut xor = [[0; BODY_LEN]; 32];
108112
for packet in 0..pchunk.missing_first.len() {
@@ -126,6 +130,7 @@ async fn handle_packet(
126130

127131
let data = decompress(&pchunk.data[32 * BODY_LEN..], size)
128132
.map_err(|e| Error::Generic(e.to_string()))?;
133+
assert_eq!(data.len(), size);
129134

130135
Ok(Some((pos, data)))
131136
}
@@ -226,6 +231,7 @@ pub async fn flash(os: UefiOS, server_addr: SocketAddrV4) -> Result<()> {
226231

227232
let task1 = async {
228233
let mut tx = tx;
234+
let mut last_seen = Vec::new();
229235
while !chunks_info.is_empty() {
230236
let recv = Box::pin(socket.recv(&mut buf));
231237
let sleep = Box::pin(os.sleep_us(100_000));
@@ -234,13 +240,18 @@ pub async fn flash(os: UefiOS, server_addr: SocketAddrV4) -> Result<()> {
234240
stats.borrow_mut().pack_recv += 1;
235241
assert!(buf.len() >= 34);
236242

237-
let chunk = handle_packet(buf, &mut chunks_info, &mut received).await?;
243+
let chunk =
244+
handle_packet(buf, &mut chunks_info, &mut received, &mut last_seen)?;
238245
if let Some((pos, data)) = chunk {
239246
tx.send((pos, data)).await;
240247
}
241248

242-
if received.len() > 128 {
243-
received.pop_last();
249+
assert_eq!(last_seen.len(), received.len());
250+
if last_seen.len() > 128 {
251+
let hash = last_seen.remove(0);
252+
received
253+
.remove(&hash)
254+
.expect("last_seen should contain only received chunks");
244255
}
245256
}
246257
Either::Right(((), _sleep)) => {

0 commit comments

Comments
 (0)