Inline window method implementations
This commit is contained in:
		
							
								
								
									
										389
									
								
								src/window.rs
									
									
									
									
									
								
							
							
						
						
									
										389
									
								
								src/window.rs
									
									
									
									
									
								
							@@ -56,6 +56,7 @@ pub struct WindowIndex {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait WindowUtil {
 | 
					pub trait WindowUtil {
 | 
				
			||||||
 | 
					    /// Finds available slots, clears them, and returns their indices.
 | 
				
			||||||
    fn clear_slots(&mut self, recycler: &BlobRecycler, consumed: u64, received: u64) -> Vec<u64>;
 | 
					    fn clear_slots(&mut self, recycler: &BlobRecycler, consumed: u64, received: u64) -> Vec<u64>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn repair(
 | 
					    fn repair(
 | 
				
			||||||
@@ -85,7 +86,18 @@ pub trait WindowUtil {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl WindowUtil for Window {
 | 
					impl WindowUtil for Window {
 | 
				
			||||||
    fn clear_slots(&mut self, recycler: &BlobRecycler, consumed: u64, received: u64) -> Vec<u64> {
 | 
					    fn clear_slots(&mut self, recycler: &BlobRecycler, consumed: u64, received: u64) -> Vec<u64> {
 | 
				
			||||||
        clear_window_slots(self, recycler, consumed, received)
 | 
					        (consumed..received)
 | 
				
			||||||
 | 
					            .filter_map(|pix| {
 | 
				
			||||||
 | 
					                let i = (pix % WINDOW_SIZE) as usize;
 | 
				
			||||||
 | 
					                if let Some(blob_idx) = self[i].blob_index() {
 | 
				
			||||||
 | 
					                    if blob_idx == pix {
 | 
				
			||||||
 | 
					                        return None;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                self[i].clear_data(recycler);
 | 
				
			||||||
 | 
					                Some(pix)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .collect()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn repair(
 | 
					    fn repair(
 | 
				
			||||||
@@ -97,13 +109,87 @@ impl WindowUtil for Window {
 | 
				
			|||||||
        consumed: u64,
 | 
					        consumed: u64,
 | 
				
			||||||
        received: u64,
 | 
					        received: u64,
 | 
				
			||||||
    ) -> Vec<(SocketAddr, Vec<u8>)> {
 | 
					    ) -> Vec<(SocketAddr, Vec<u8>)> {
 | 
				
			||||||
        repair_window(self, crdt, recycler, id, times, consumed, received)
 | 
					        let num_peers = crdt.read().unwrap().table.len() as u64;
 | 
				
			||||||
 | 
					        let highest_lost = calculate_highest_lost_blob_index(num_peers, consumed, received);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let idxs = self.clear_slots(recycler, consumed, highest_lost);
 | 
				
			||||||
 | 
					        let reqs: Vec<_> = idxs
 | 
				
			||||||
 | 
					            .into_iter()
 | 
				
			||||||
 | 
					            .filter_map(|pix| crdt.read().unwrap().window_index_request(pix).ok())
 | 
				
			||||||
 | 
					            .collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inc_new_counter_info!("streamer-repair_window-repair", reqs.len());
 | 
				
			||||||
 | 
					        if log_enabled!(Level::Trace) {
 | 
				
			||||||
 | 
					            trace!(
 | 
				
			||||||
 | 
					                "{}: repair_window counter times: {} consumed: {} highest_lost: {} missing: {}",
 | 
				
			||||||
 | 
					                id,
 | 
				
			||||||
 | 
					                times,
 | 
				
			||||||
 | 
					                consumed,
 | 
				
			||||||
 | 
					                highest_lost,
 | 
				
			||||||
 | 
					                reqs.len()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (to, _) in &reqs {
 | 
				
			||||||
 | 
					                trace!("{}: repair_window request to {}", id, to);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        reqs
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn print(&self, id: &Pubkey, consumed: u64) -> String {
 | 
					    fn print(&self, id: &Pubkey, consumed: u64) -> String {
 | 
				
			||||||
        print_window(self, id, consumed)
 | 
					        let pointer: Vec<_> = self
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .enumerate()
 | 
				
			||||||
 | 
					            .map(|(i, _v)| {
 | 
				
			||||||
 | 
					                if i == (consumed % WINDOW_SIZE) as usize {
 | 
				
			||||||
 | 
					                    "V"
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    " "
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let buf: Vec<_> = self
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .map(|v| {
 | 
				
			||||||
 | 
					                if v.data.is_none() && v.coding.is_none() {
 | 
				
			||||||
 | 
					                    "O"
 | 
				
			||||||
 | 
					                } else if v.data.is_some() && v.coding.is_some() {
 | 
				
			||||||
 | 
					                    "D"
 | 
				
			||||||
 | 
					                } else if v.data.is_some() {
 | 
				
			||||||
 | 
					                    // coding.is_none()
 | 
				
			||||||
 | 
					                    "d"
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // data.is_none()
 | 
				
			||||||
 | 
					                    "c"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .collect();
 | 
				
			||||||
 | 
					        format!(
 | 
				
			||||||
 | 
					            "\n{}: WINDOW ({}): {}\n{}: WINDOW ({}): {}",
 | 
				
			||||||
 | 
					            id,
 | 
				
			||||||
 | 
					            consumed,
 | 
				
			||||||
 | 
					            pointer.join(""),
 | 
				
			||||||
 | 
					            id,
 | 
				
			||||||
 | 
					            consumed,
 | 
				
			||||||
 | 
					            buf.join("")
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// process a blob: Add blob to the window. If a continuous set of blobs
 | 
				
			||||||
 | 
					    ///      starting from consumed is thereby formed, add that continuous
 | 
				
			||||||
 | 
					    ///      range of blobs to a queue to be sent on to the next stage.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// * `self` - the window we're operating on
 | 
				
			||||||
 | 
					    /// * `id` - this node's id
 | 
				
			||||||
 | 
					    /// * `blob` -  the blob to be processed into the window and rebroadcast
 | 
				
			||||||
 | 
					    /// * `pix` -  the index of the blob, corresponds to
 | 
				
			||||||
 | 
					    ///            the entry height of this blob
 | 
				
			||||||
 | 
					    /// * `consume_queue` - output, blobs to be rebroadcast are placed here
 | 
				
			||||||
 | 
					    /// * `recycler` - where to return the blob once processed, also where
 | 
				
			||||||
 | 
					    ///                  to return old blobs from the window
 | 
				
			||||||
 | 
					    /// * `consumed` - input/output, the entry-height to which this
 | 
				
			||||||
 | 
					    ///                 node has populated and rebroadcast entries
 | 
				
			||||||
    fn process_blob(
 | 
					    fn process_blob(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        id: &Pubkey,
 | 
					        id: &Pubkey,
 | 
				
			||||||
@@ -115,39 +201,89 @@ impl WindowUtil for Window {
 | 
				
			|||||||
        leader_unknown: bool,
 | 
					        leader_unknown: bool,
 | 
				
			||||||
        pending_retransmits: &mut bool,
 | 
					        pending_retransmits: &mut bool,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        process_blob(
 | 
					        let w = (pix % WINDOW_SIZE) as usize;
 | 
				
			||||||
            self,
 | 
					 | 
				
			||||||
            id,
 | 
					 | 
				
			||||||
            blob,
 | 
					 | 
				
			||||||
            pix,
 | 
					 | 
				
			||||||
            consume_queue,
 | 
					 | 
				
			||||||
            recycler,
 | 
					 | 
				
			||||||
            consumed,
 | 
					 | 
				
			||||||
            leader_unknown,
 | 
					 | 
				
			||||||
            pending_retransmits,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Finds available slots, clears them, and returns their indices.
 | 
					        let is_coding = {
 | 
				
			||||||
fn clear_window_slots(
 | 
					            let blob_r = blob
 | 
				
			||||||
    window: &mut Window,
 | 
					                .read()
 | 
				
			||||||
    recycler: &BlobRecycler,
 | 
					                .expect("blob read lock for flogs streamer::window");
 | 
				
			||||||
    consumed: u64,
 | 
					            blob_r.is_coding()
 | 
				
			||||||
    received: u64,
 | 
					        };
 | 
				
			||||||
) -> Vec<u64> {
 | 
					
 | 
				
			||||||
    (consumed..received)
 | 
					        // insert a newly received blob into a window slot, clearing out and recycling any previous
 | 
				
			||||||
        .filter_map(|pix| {
 | 
					        //  blob unless the incoming blob is a duplicate (based on idx)
 | 
				
			||||||
            let i = (pix % WINDOW_SIZE) as usize;
 | 
					        // returns whether the incoming is a duplicate blob
 | 
				
			||||||
            if let Some(blob_idx) = window[i].blob_index() {
 | 
					        fn insert_blob_is_dup(
 | 
				
			||||||
                if blob_idx == pix {
 | 
					            id: &Pubkey,
 | 
				
			||||||
                    return None;
 | 
					            blob: SharedBlob,
 | 
				
			||||||
                }
 | 
					            pix: u64,
 | 
				
			||||||
 | 
					            window_slot: &mut Option<SharedBlob>,
 | 
				
			||||||
 | 
					            recycler: &BlobRecycler,
 | 
				
			||||||
 | 
					            c_or_d: &str,
 | 
				
			||||||
 | 
					        ) -> bool {
 | 
				
			||||||
 | 
					            if let Some(old) = mem::replace(window_slot, Some(blob)) {
 | 
				
			||||||
 | 
					                let is_dup = old.read().unwrap().get_index().unwrap() == pix;
 | 
				
			||||||
 | 
					                recycler.recycle(old, "insert_blob_is_dup");
 | 
				
			||||||
 | 
					                trace!(
 | 
				
			||||||
 | 
					                    "{}: occupied {} window slot {:}, is_dup: {}",
 | 
				
			||||||
 | 
					                    id,
 | 
				
			||||||
 | 
					                    c_or_d,
 | 
				
			||||||
 | 
					                    pix,
 | 
				
			||||||
 | 
					                    is_dup
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                is_dup
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                trace!("{}: empty {} window slot {:}", id, c_or_d, pix);
 | 
				
			||||||
 | 
					                false
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            window[i].clear_data(recycler);
 | 
					        }
 | 
				
			||||||
            Some(pix)
 | 
					
 | 
				
			||||||
        })
 | 
					        // insert the new blob into the window, overwrite and recycle old (or duplicate) entry
 | 
				
			||||||
        .collect()
 | 
					        let is_duplicate = if is_coding {
 | 
				
			||||||
 | 
					            insert_blob_is_dup(id, blob, pix, &mut self[w].coding, recycler, "coding")
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            insert_blob_is_dup(id, blob, pix, &mut self[w].data, recycler, "data")
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if is_duplicate {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self[w].leader_unknown = leader_unknown;
 | 
				
			||||||
 | 
					        *pending_retransmits = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #[cfg(feature = "erasure")]
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if erasure::recover(
 | 
				
			||||||
 | 
					                id,
 | 
				
			||||||
 | 
					                recycler,
 | 
				
			||||||
 | 
					                window,
 | 
				
			||||||
 | 
					                *consumed,
 | 
				
			||||||
 | 
					                (*consumed % WINDOW_SIZE) as usize,
 | 
				
			||||||
 | 
					            ).is_err()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                trace!("{}: erasure::recover failed", id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // push all contiguous blobs into consumed queue, increment consumed
 | 
				
			||||||
 | 
					        loop {
 | 
				
			||||||
 | 
					            let k = (*consumed % WINDOW_SIZE) as usize;
 | 
				
			||||||
 | 
					            trace!("{}: k: {} consumed: {}", id, k, *consumed,);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if let Some(blob) = &self[k].data {
 | 
				
			||||||
 | 
					                if blob.read().unwrap().get_index().unwrap() < *consumed {
 | 
				
			||||||
 | 
					                    // window wrap-around, end of received
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // self[k].data is None, end of received
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            consume_queue.push(self[k].data.clone().expect("clone in fn recv_window"));
 | 
				
			||||||
 | 
					            *consumed += 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn calculate_highest_lost_blob_index(num_peers: u64, consumed: u64, received: u64) -> u64 {
 | 
					fn calculate_highest_lost_blob_index(num_peers: u64, consumed: u64, received: u64) -> u64 {
 | 
				
			||||||
@@ -186,42 +322,6 @@ fn repair_backoff(last: &mut u64, times: &mut usize, consumed: u64) -> bool {
 | 
				
			|||||||
    thread_rng().gen_range(0, *times as u64) == 0
 | 
					    thread_rng().gen_range(0, *times as u64) == 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn repair_window(
 | 
					 | 
				
			||||||
    window: &mut Window,
 | 
					 | 
				
			||||||
    crdt: &Arc<RwLock<Crdt>>,
 | 
					 | 
				
			||||||
    recycler: &BlobRecycler,
 | 
					 | 
				
			||||||
    id: &Pubkey,
 | 
					 | 
				
			||||||
    times: usize,
 | 
					 | 
				
			||||||
    consumed: u64,
 | 
					 | 
				
			||||||
    received: u64,
 | 
					 | 
				
			||||||
) -> Vec<(SocketAddr, Vec<u8>)> {
 | 
					 | 
				
			||||||
    let num_peers = crdt.read().unwrap().table.len() as u64;
 | 
					 | 
				
			||||||
    let highest_lost = calculate_highest_lost_blob_index(num_peers, consumed, received);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let idxs = window.clear_slots(recycler, consumed, highest_lost);
 | 
					 | 
				
			||||||
    let reqs: Vec<_> = idxs
 | 
					 | 
				
			||||||
        .into_iter()
 | 
					 | 
				
			||||||
        .filter_map(|pix| crdt.read().unwrap().window_index_request(pix).ok())
 | 
					 | 
				
			||||||
        .collect();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    inc_new_counter_info!("streamer-repair_window-repair", reqs.len());
 | 
					 | 
				
			||||||
    if log_enabled!(Level::Trace) {
 | 
					 | 
				
			||||||
        trace!(
 | 
					 | 
				
			||||||
            "{}: repair_window counter times: {} consumed: {} highest_lost: {} missing: {}",
 | 
					 | 
				
			||||||
            id,
 | 
					 | 
				
			||||||
            times,
 | 
					 | 
				
			||||||
            consumed,
 | 
					 | 
				
			||||||
            highest_lost,
 | 
					 | 
				
			||||||
            reqs.len()
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (to, _) in &reqs {
 | 
					 | 
				
			||||||
            trace!("{}: repair_window request to {}", id, to);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    reqs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn add_block_to_retransmit_queue(
 | 
					fn add_block_to_retransmit_queue(
 | 
				
			||||||
    b: &SharedBlob,
 | 
					    b: &SharedBlob,
 | 
				
			||||||
    leader_id: Pubkey,
 | 
					    leader_id: Pubkey,
 | 
				
			||||||
@@ -320,115 +420,6 @@ fn retransmit_all_leader_blocks(
 | 
				
			|||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// process a blob: Add blob to the window. If a continuous set of blobs
 | 
					 | 
				
			||||||
///      starting from consumed is thereby formed, add that continuous
 | 
					 | 
				
			||||||
///      range of blobs to a queue to be sent on to the next stage.
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// * `id` - this node's id
 | 
					 | 
				
			||||||
/// * `blob` -  the blob to be processed into the window and rebroadcast
 | 
					 | 
				
			||||||
/// * `pix` -  the index of the blob, corresponds to
 | 
					 | 
				
			||||||
///            the entry height of this blob
 | 
					 | 
				
			||||||
/// * `consume_queue` - output, blobs to be rebroadcast are placed here
 | 
					 | 
				
			||||||
/// * `window` - the window we're operating on
 | 
					 | 
				
			||||||
/// * `recycler` - where to return the blob once processed, also where
 | 
					 | 
				
			||||||
///                  to return old blobs from the window
 | 
					 | 
				
			||||||
/// * `consumed` - input/output, the entry-height to which this
 | 
					 | 
				
			||||||
///                 node has populated and rebroadcast entries
 | 
					 | 
				
			||||||
fn process_blob(
 | 
					 | 
				
			||||||
    window: &mut Window,
 | 
					 | 
				
			||||||
    id: &Pubkey,
 | 
					 | 
				
			||||||
    blob: SharedBlob,
 | 
					 | 
				
			||||||
    pix: u64,
 | 
					 | 
				
			||||||
    consume_queue: &mut SharedBlobs,
 | 
					 | 
				
			||||||
    recycler: &BlobRecycler,
 | 
					 | 
				
			||||||
    consumed: &mut u64,
 | 
					 | 
				
			||||||
    leader_unknown: bool,
 | 
					 | 
				
			||||||
    pending_retransmits: &mut bool,
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    let w = (pix % WINDOW_SIZE) as usize;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let is_coding = {
 | 
					 | 
				
			||||||
        let blob_r = blob
 | 
					 | 
				
			||||||
            .read()
 | 
					 | 
				
			||||||
            .expect("blob read lock for flogs streamer::window");
 | 
					 | 
				
			||||||
        blob_r.is_coding()
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // insert a newly received blob into a window slot, clearing out and recycling any previous
 | 
					 | 
				
			||||||
    //  blob unless the incoming blob is a duplicate (based on idx)
 | 
					 | 
				
			||||||
    // returns whether the incoming is a duplicate blob
 | 
					 | 
				
			||||||
    fn insert_blob_is_dup(
 | 
					 | 
				
			||||||
        id: &Pubkey,
 | 
					 | 
				
			||||||
        blob: SharedBlob,
 | 
					 | 
				
			||||||
        pix: u64,
 | 
					 | 
				
			||||||
        window_slot: &mut Option<SharedBlob>,
 | 
					 | 
				
			||||||
        recycler: &BlobRecycler,
 | 
					 | 
				
			||||||
        c_or_d: &str,
 | 
					 | 
				
			||||||
    ) -> bool {
 | 
					 | 
				
			||||||
        if let Some(old) = mem::replace(window_slot, Some(blob)) {
 | 
					 | 
				
			||||||
            let is_dup = old.read().unwrap().get_index().unwrap() == pix;
 | 
					 | 
				
			||||||
            recycler.recycle(old, "insert_blob_is_dup");
 | 
					 | 
				
			||||||
            trace!(
 | 
					 | 
				
			||||||
                "{}: occupied {} window slot {:}, is_dup: {}",
 | 
					 | 
				
			||||||
                id,
 | 
					 | 
				
			||||||
                c_or_d,
 | 
					 | 
				
			||||||
                pix,
 | 
					 | 
				
			||||||
                is_dup
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            is_dup
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            trace!("{}: empty {} window slot {:}", id, c_or_d, pix);
 | 
					 | 
				
			||||||
            false
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // insert the new blob into the window, overwrite and recycle old (or duplicate) entry
 | 
					 | 
				
			||||||
    let is_duplicate = if is_coding {
 | 
					 | 
				
			||||||
        insert_blob_is_dup(id, blob, pix, &mut window[w].coding, recycler, "coding")
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        insert_blob_is_dup(id, blob, pix, &mut window[w].data, recycler, "data")
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if is_duplicate {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    window[w].leader_unknown = leader_unknown;
 | 
					 | 
				
			||||||
    *pending_retransmits = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(feature = "erasure")]
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if erasure::recover(
 | 
					 | 
				
			||||||
            id,
 | 
					 | 
				
			||||||
            recycler,
 | 
					 | 
				
			||||||
            window,
 | 
					 | 
				
			||||||
            *consumed,
 | 
					 | 
				
			||||||
            (*consumed % WINDOW_SIZE) as usize,
 | 
					 | 
				
			||||||
        ).is_err()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            trace!("{}: erasure::recover failed", id);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // push all contiguous blobs into consumed queue, increment consumed
 | 
					 | 
				
			||||||
    loop {
 | 
					 | 
				
			||||||
        let k = (*consumed % WINDOW_SIZE) as usize;
 | 
					 | 
				
			||||||
        trace!("{}: k: {} consumed: {}", id, k, *consumed,);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if let Some(blob) = &window[k].data {
 | 
					 | 
				
			||||||
            if blob.read().unwrap().get_index().unwrap() < *consumed {
 | 
					 | 
				
			||||||
                // window wrap-around, end of received
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // window[k].data is None, end of received
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        consume_queue.push(window[k].data.clone().expect("clone in fn recv_window"));
 | 
					 | 
				
			||||||
        *consumed += 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn blob_idx_in_window(id: &Pubkey, pix: u64, consumed: u64, received: &mut u64) -> bool {
 | 
					fn blob_idx_in_window(id: &Pubkey, pix: u64, consumed: u64, received: &mut u64) -> bool {
 | 
				
			||||||
    // Prevent receive window from running over
 | 
					    // Prevent receive window from running over
 | 
				
			||||||
    // Got a blob which has already been consumed, skip it
 | 
					    // Got a blob which has already been consumed, skip it
 | 
				
			||||||
@@ -555,46 +546,6 @@ fn recv_window(
 | 
				
			|||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn print_window(window: &Window, id: &Pubkey, consumed: u64) -> String {
 | 
					 | 
				
			||||||
    let pointer: Vec<_> = window
 | 
					 | 
				
			||||||
        .iter()
 | 
					 | 
				
			||||||
        .enumerate()
 | 
					 | 
				
			||||||
        .map(|(i, _v)| {
 | 
					 | 
				
			||||||
            if i == (consumed % WINDOW_SIZE) as usize {
 | 
					 | 
				
			||||||
                "V"
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                " "
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .collect();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let buf: Vec<_> = window
 | 
					 | 
				
			||||||
        .iter()
 | 
					 | 
				
			||||||
        .map(|v| {
 | 
					 | 
				
			||||||
            if v.data.is_none() && v.coding.is_none() {
 | 
					 | 
				
			||||||
                "O"
 | 
					 | 
				
			||||||
            } else if v.data.is_some() && v.coding.is_some() {
 | 
					 | 
				
			||||||
                "D"
 | 
					 | 
				
			||||||
            } else if v.data.is_some() {
 | 
					 | 
				
			||||||
                // coding.is_none()
 | 
					 | 
				
			||||||
                "d"
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                // data.is_none()
 | 
					 | 
				
			||||||
                "c"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .collect();
 | 
					 | 
				
			||||||
    format!(
 | 
					 | 
				
			||||||
        "\n{}: WINDOW ({}): {}\n{}: WINDOW ({}): {}",
 | 
					 | 
				
			||||||
        id,
 | 
					 | 
				
			||||||
        consumed,
 | 
					 | 
				
			||||||
        pointer.join(""),
 | 
					 | 
				
			||||||
        id,
 | 
					 | 
				
			||||||
        consumed,
 | 
					 | 
				
			||||||
        buf.join("")
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn default_window() -> SharedWindow {
 | 
					pub fn default_window() -> SharedWindow {
 | 
				
			||||||
    Arc::new(RwLock::new(vec![
 | 
					    Arc::new(RwLock::new(vec![
 | 
				
			||||||
        WindowSlot::default();
 | 
					        WindowSlot::default();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user