pub fn recover(id: &Pubkey, window: &mut [WindowSlot], start_idx: u64, start: usize) -> Result<()> {
    let block_start = start - (start % NUM_DATA);
    let block_start_idx = start_idx - (start_idx % NUM_DATA as u64);

    debug!("start: {} block_start: {}", start, block_start);

    let coding_start = block_start + NUM_DATA - NUM_CODING;
    let block_end = block_start + NUM_DATA;
    trace!(
        "recover {}: block_start_idx: {} block_start: {} coding_start: {} block_end: {}",
        id,
        block_start_idx,
        block_start,
        coding_start,
        block_end
    );

    let (data_missing, coding_missing) = find_missing(id, block_start_idx, block_start, window);

    // if we're not missing data, or if we have too much missin but have enough coding
    if data_missing == 0 {
        // nothing to do...
        return Ok(());
    }

    if (data_missing + coding_missing) > NUM_CODING {
        trace!(
            "recover {}: start: {} skipping recovery data: {} coding: {}",
            id,
            block_start,
            data_missing,
            coding_missing
        );
        // nothing to do...
        return Err(ErasureError::NotEnoughBlocksToDecode);
    }

    trace!(
        "recover {}: recovering: data: {} coding: {}",
        id,
        data_missing,
        coding_missing
    );
    let mut blobs: Vec<SharedBlob> = Vec::with_capacity(NUM_DATA + NUM_CODING);
    let mut locks = Vec::with_capacity(NUM_DATA + NUM_CODING);
    let mut erasures: Vec<i32> = Vec::with_capacity(NUM_CODING);
    let mut meta = None;
    let mut size = None;

    // add the data blobs we have into recovery blob vector
    for i in block_start..block_end {
        let j = i % window.len();

        if let Some(b) = window[j].data.clone() {
            if meta.is_none() {
                meta = Some(b.read().unwrap().meta.clone());
                trace!("recover {} meta at {} {:?}", id, j, meta);
            }
            blobs.push(b);
        } else {
            let n = SharedBlob::default();
            window[j].data = Some(n.clone());
            // mark the missing memory
            blobs.push(n);
            erasures.push((i - block_start) as i32);
        }
    }
    for i in coding_start..block_end {
        let j = i % window.len();
        if let Some(b) = window[j].coding.clone() {
            if size.is_none() {
                size = Some(b.read().unwrap().meta.size - BLOB_HEADER_SIZE);
                trace!(
                    "{} recover size {} from {}",
                    id,
                    size.unwrap(),
                    i as u64 + block_start_idx
                );
            }
            blobs.push(b);
        } else {
            let n = SharedBlob::default();
            window[j].coding = Some(n.clone());
            //mark the missing memory
            blobs.push(n);
            erasures.push(((i - coding_start) + NUM_DATA) as i32);
        }
    }

    // now that we have size (from coding), zero out data blob tails
    let size = size.unwrap();
    for i in block_start..block_end {
        let j = i % window.len();

        if let Some(b) = &window[j].data {
            let mut b_wl = b.write().unwrap();
            for i in b_wl.meta.size..size {
                b_wl.data[i] = 0;
            }
        }
    }

    // marks end of erasures
    erasures.push(-1);
    trace!("erasures[]: {} {:?} data_size: {}", id, erasures, size,);
    //lock everything for write
    for b in &blobs {
        locks.push(b.write().unwrap());
    }

    {
        let mut coding_ptrs: Vec<&mut [u8]> = Vec::with_capacity(NUM_CODING);
        let mut data_ptrs: Vec<&mut [u8]> = Vec::with_capacity(NUM_DATA);
        for (i, l) in locks.iter_mut().enumerate() {
            if i < NUM_DATA {
                trace!("{} pushing data: {}", id, i);
                data_ptrs.push(&mut l.data[..size]);
            } else {
                trace!("{} pushing coding: {}", id, i);
                coding_ptrs.push(&mut l.data_mut()[..size]);
            }
        }
        trace!(
            "{} coding_ptrs.len: {} data_ptrs.len {}",
            id,
            coding_ptrs.len(),
            data_ptrs.len()
        );
        decode_blocks(
            data_ptrs.as_mut_slice(),
            coding_ptrs.as_mut_slice(),
            &erasures,
        )?;
    }

    let meta = meta.unwrap();
    let mut corrupt = false;
    // repopulate header data size from recovered blob contents
    for i in &erasures[..erasures.len() - 1] {
        let n = *i as usize;
        let mut idx = n as u64 + block_start_idx;

        let mut data_size;
        if n < NUM_DATA {
            data_size = locks[n].data_size().unwrap() as usize;
            data_size -= BLOB_HEADER_SIZE;
            if data_size > BLOB_DATA_SIZE {
                error!("{} corrupt data blob[{}] data_size: {}", id, idx, data_size);
                corrupt = true;
            }
        } else {
            data_size = size;
            idx -= NUM_CODING as u64;
            locks[n].set_index(idx).unwrap();

            if data_size - BLOB_HEADER_SIZE > BLOB_DATA_SIZE {
                error!(
                    "{} corrupt coding blob[{}] data_size: {}",
                    id, idx, data_size
                );
                corrupt = true;
            }
        }

        locks[n].meta = meta.clone();
        locks[n].set_size(data_size);
        trace!(
            "{} erasures[{}] ({}) size: {} data[0]: {}",
            id,
            *i,
            idx,
            data_size,
            locks[n].data()[0]
        );
    }
    assert!(!corrupt, " {} ", id);

    Ok(())
}
// Recover a missing block into window
//   missing blocks should be None or old...
//   If not enough coding or data blocks are present to restore
//    any of the blocks, the block is skipped.
//   Side effect: old blobs in a block are None'd
Recover a missing block into window
missing blocks should be None or old
If not enough coding or data blocks are present to restore
any of the blocks, the block is skipped.
Side effect: old blobs in a block are None'd
Recover a missing block into window missing blocks should be None or old If not enough coding or data blocks are present to restore any of the blocks the block is skipped . Side effect : old blobs in a block are None ' d
pub fn recover(id: &Pubkey, window: &mut [WindowSlot], start_idx: u64, start: usize) -> Result<()> {
    let block_start = start - (start % NUM_DATA);
    let block_start_idx = start_idx - (start_idx % NUM_DATA as u64);
    debug!("start: {} block_start: {}", start, block_start);
    let coding_start = block_start + NUM_DATA - NUM_CODING;
    let block_end = block_start + NUM_DATA;
    trace!(
        "recover {}: block_start_idx: {} block_start: {} coding_start: {} block_end: {}",
        id,
        block_start_idx,
        block_start,
        coding_start,
        block_end
    );
    let (data_missing, coding_missing) = find_missing(id, block_start_idx, block_start, window);
    // if we're not missing data, or if we have too much missin but have enough coding
    if data_missing == 0 {
        // nothing to do...
        return Ok(());
    }
    if (data_missing + coding_missing) > NUM_CODING {
        trace!(
            "recover {}: start: {} skipping recovery data: {} coding: {}",
            id,
            block_start,
            data_missing,
            coding_missing
        );
        // nothing to do...
        return Err(ErasureError::NotEnoughBlocksToDecode);
    }
    trace!(
        "recover {}: recovering: data: {} coding: {}",
        id,
        data_missing,
        coding_missing
    );
    let mut blobs: Vec<SharedBlob> = Vec::with_capacity(NUM_DATA + NUM_CODING);
    let mut locks = Vec::with_capacity(NUM_DATA + NUM_CODING);
    let mut erasures: Vec<i32> = Vec::with_capacity(NUM_CODING);
    let mut meta = None;
    let mut size = None;
    // add the data blobs we have into recovery blob vector
    for i in block_start..block_end {
        let j = i % window.len();
        if let Some(b) = window[j].data.clone() {
            if meta.is_none() {
                meta = Some(b.read().unwrap().meta.clone());
                trace!("recover {} meta at {} {:?}", id, j, meta);
            }
            blobs.push(b);
        } else {
            let n = SharedBlob::default();
            window[j].data = Some(n.clone());
            // mark the missing memory
            blobs.push(n);
            erasures.push((i - block_start) as i32);
        }
    }
    for i in coding_start..block_end {
        let j = i % window.len();
        if let Some(b) = window[j].coding.clone() {
            if size.is_none() {
                size = Some(b.read().unwrap().meta.size - BLOB_HEADER_SIZE);
                trace!(
                    "{} recover size {} from {}",
                    id,
                    size.unwrap(),
                    i as u64 + block_start_idx
                );
            }
            blobs.push(b);
        } else {
            let n = SharedBlob::default();
            window[j].coding = Some(n.clone());
            //mark the missing memory
            blobs.push(n);
            erasures.push(((i - coding_start) + NUM_DATA) as i32);
        }
    }
    // now that we have size (from coding), zero out data blob tails
    let size = size.unwrap();
    for i in block_start..block_end {
        let j = i % window.len();
        if let Some(b) = &window[j].data {
            let mut b_wl = b.write().unwrap();
            for i in b_wl.meta.size..size {
                b_wl.data[i] = 0;
            }
        }
    }
    // marks end of erasures
    erasures.push(-1);
    trace!("erasures[]: {} {:?} data_size: {}", id, erasures, size,);
    //lock everything for write
    for b in &blobs {
        locks.push(b.write().unwrap());
    }
    {
        let mut coding_ptrs: Vec<&mut [u8]> = Vec::with_capacity(NUM_CODING);
        let mut data_ptrs: Vec<&mut [u8]> = Vec::with_capacity(NUM_DATA);
        for (i, l) in locks.iter_mut().enumerate() {
            if i < NUM_DATA {
                trace!("{} pushing data: {}", id, i);
                data_ptrs.push(&mut l.data[..size]);
            } else {
                trace!("{} pushing coding: {}", id, i);
                coding_ptrs.push(&mut l.data_mut()[..size]);
            }
        }
        trace!(
            "{} coding_ptrs.len: {} data_ptrs.len {}",
            id,
            coding_ptrs.len(),
            data_ptrs.len()
        );
        decode_blocks(
            data_ptrs.as_mut_slice(),
            coding_ptrs.as_mut_slice(),
            &erasures,
        )?;
    }
    let meta = meta.unwrap();
    let mut corrupt = false;
    // repopulate header data size from recovered blob contents
    for i in &erasures[..erasures.len() - 1] {
        let n = *i as usize;
        let mut idx = n as u64 + block_start_idx;
        let mut data_size;
        if n < NUM_DATA {
            data_size = locks[n].data_size().unwrap() as usize;
            data_size -= BLOB_HEADER_SIZE;
            if data_size > BLOB_DATA_SIZE {
                error!("{} corrupt data blob[{}] data_size: {}", id, idx, data_size);
                corrupt = true;
            }
        } else {
            data_size = size;
            idx -= NUM_CODING as u64;
            locks[n].set_index(idx).unwrap();
            if data_size - BLOB_HEADER_SIZE > BLOB_DATA_SIZE {
                error!(
                    "{} corrupt coding blob[{}] data_size: {}",
                    id, idx, data_size
                );
                corrupt = true;
            }
        }
        locks[n].meta = meta.clone();
        locks[n].set_size(data_size);
        trace!(
            "{} erasures[{}] ({}) size: {} data[0]: {}",
            id,
            *i,
            idx,
            data_size,
            locks[n].data()[0]
        );
    }
    assert!(!corrupt, " {} ", id);
    Ok(())
}
pub fn recover ( id : & Pubkey , window : & mut [ WindowSlot ] , start_idx : u64 , start : usize ) -> Result < ( ) > { let block_start = start - ( start % NUM_DATA ) ; let block_start_idx = start_idx - ( start_idx % NUM_DATA as u64 ) ; debug ! ( " " start block_start ) ; let coding_start = block_start + NUM_DATA - NUM_CODING ; let block_end = block_start + NUM_DATA ; trace ! ( " " id block_start_idx block_start coding_start block_end ) ; let ( data_missing , coding_missing ) = find_missing ( id , block_start_idx , block_start , window ) ; // if we're not missing data, or if we have too much missin but have enough coding if data_missing == 0 { // nothing to do... return Ok ( ( ) ) ; } if ( data_missing + coding_missing ) > NUM_CODING { trace ! ( " " id block_start data_missing coding_missing ) ; // nothing to do... return Err ( ErasureError :: NotEnoughBlocksToDecode ) ; } trace ! ( " " id data_missing coding_missing ) ; let mut blobs : Vec < SharedBlob > = Vec :: with_capacity ( NUM_DATA + NUM_CODING ) ; let mut locks = Vec :: with_capacity ( NUM_DATA + NUM_CODING ) ; let mut erasures : Vec < i32 > = Vec :: with_capacity ( NUM_CODING ) ; let mut meta = None ; let mut size = None ; // add the data blobs we have into recovery blob vector for i in block_start .. block_end { let j = i % window . len ( ) ; if let Some ( b ) = window [ j ] . data . clone ( ) { if meta . is_none ( ) { meta = Some ( b . read ( ) . unwrap ( ) . meta . clone ( ) ) ; trace ! ( " " id j meta ) ; } blobs . push ( b ) ; } else { let n = SharedBlob :: default ( ) ; window [ j ] . data = Some ( n . clone ( ) ) ; // mark the missing memory blobs . push ( n ) ; erasures . push ( ( i - block_start ) as i32 ) ; } } for i in coding_start .. block_end { let j = i % window . len ( ) ; if let Some ( b ) = window [ j ] . coding . clone ( ) { if size . is_none ( ) { size = Some ( b . read ( ) . unwrap ( ) . meta . size - BLOB_HEADER_SIZE ) ; trace ! ( " " id size unwrap ( ) i as u64 block_start_idx ) ; } blobs . push ( b ) ; } else { let n = SharedBlob :: default ( ) ; window [ j ] . coding = Some ( n . clone ( ) ) ; //mark the missing memory blobs . push ( n ) ; erasures . push ( ( ( i - coding_start ) + NUM_DATA ) as i32 ) ; } } // now that we have size (from coding), zero out data blob tails let size = size . unwrap ( ) ; for i in block_start .. block_end { let j = i % window . len ( ) ; if let Some ( b ) = & window [ j ] . data { let mut b_wl = b . write ( ) . unwrap ( ) ; for i in b_wl . meta . size .. size { b_wl . data [ i ] = 0 ; } } } // marks end of erasures erasures . push ( - 1 ) ; trace ! ( " " id erasures size ) ; //lock everything for write for b in & blobs { locks . push ( b . write ( ) . unwrap ( ) ) ; } { let mut coding_ptrs : Vec < & mut [ u8 ] > = Vec :: with_capacity ( NUM_CODING ) ; let mut data_ptrs : Vec < & mut [ u8 ] > = Vec :: with_capacity ( NUM_DATA ) ; for ( i , l ) in locks . iter_mut ( ) . enumerate ( ) { if i < NUM_DATA { trace ! ( " " id i ) ; data_ptrs . push ( & mut l . data [ .. size ] ) ; } else { trace ! ( " " id i ) ; coding_ptrs . push ( & mut l . data_mut ( ) [ .. size ] ) ; } } trace ! ( " " id coding_ptrs len ( ) data_ptrs len ( ) ) ; decode_blocks ( data_ptrs . as_mut_slice ( ) , coding_ptrs . as_mut_slice ( ) , & erasures , ) ? ; } let meta = meta . unwrap ( ) ; let mut corrupt = false ; // repopulate header data size from recovered blob contents for i in & erasures [ .. erasures . len ( ) - 1 ] { let n = * i as usize ; let mut idx = n as u64 + block_start_idx ; let mut data_size ; if n < NUM_DATA { data_size = locks [ n ] . data_size ( ) . unwrap ( ) as usize ; data_size -= BLOB_HEADER_SIZE ; if data_size > BLOB_DATA_SIZE { error ! ( " " id idx data_size ) ; corrupt = true ; } } else { data_size = size ; idx -= NUM_CODING as u64 ; locks [ n ] . set_index ( idx ) . unwrap ( ) ; if data_size - BLOB_HEADER_SIZE > BLOB_DATA_SIZE { error ! ( " " id idx data_size ) ; corrupt = true ; } } locks [ n ] . meta = meta . clone ( ) ; locks [ n ] . set_size ( data_size ) ; trace ! ( " " id i idx data_size locks [ n ] data ( ) [ 0 ] ) ; } assert ! ( corrupt " " id ) ; Ok ( ( ) ) }
Recover a missing block into window
missing blocks should be None or old...
Recover a missing block into window missing blocks should be None or old ...
id
&Pubkey
window
&mut [WindowSlot]
start_idx
u64
start
usize
id
&Pubkey
window
&mut [WindowSlot]
start_idx
u64
start
usize