pub fn generate_coding(
    id: &Pubkey,
    window: &mut [WindowSlot],
    receive_index: u64,
    num_blobs: usize,
    transmit_index_coding: &mut u64,
) -> Result<()> {
    // beginning of the coding blobs of the block that receive_index points into
    let coding_index_start =
        receive_index - (receive_index % NUM_DATA as u64) + (NUM_DATA - NUM_CODING) as u64;

    let start_idx = receive_index as usize % window.len();
    let mut block_start = start_idx - (start_idx % NUM_DATA);

    loop {
        let block_end = block_start + NUM_DATA;
        if block_end > (start_idx + num_blobs) {
            break;
        }
        info!(
            "generate_coding {} start: {} end: {} start_idx: {} num_blobs: {}",
            id, block_start, block_end, start_idx, num_blobs
        );

        let mut max_data_size = 0;

        // find max_data_size, maybe bail if not all the data is here
        for i in block_start..block_end {
            let n = i % window.len();
            trace!("{} window[{}] = {:?}", id, n, window[n].data);

            if let Some(b) = &window[n].data {
                max_data_size = cmp::max(b.read().unwrap().meta.size, max_data_size);
            } else {
                trace!("{} data block is null @ {}", id, n);
                return Ok(());
            }
        }

        // round up to the nearest jerasure alignment
        max_data_size = align!(max_data_size, JERASURE_ALIGN);

        trace!("{} max_data_size: {}", id, max_data_size);

        let mut data_blobs = Vec::with_capacity(NUM_DATA);
        for i in block_start..block_end {
            let n = i % window.len();

            if let Some(b) = &window[n].data {
                // make sure extra bytes in each blob are zero-d out for generation of
                //  coding blobs
                let mut b_wl = b.write().unwrap();
                for i in b_wl.meta.size..max_data_size {
                    b_wl.data[i] = 0;
                }
                data_blobs.push(b);
            }
        }

        // getting ready to do erasure coding, means that we're potentially
        // going back in time, tell our caller we've inserted coding blocks
        // starting at coding_index_start
        *transmit_index_coding = cmp::min(*transmit_index_coding, coding_index_start);

        let mut coding_blobs = Vec::with_capacity(NUM_CODING);
        let coding_start = block_end - NUM_CODING;
        for i in coding_start..block_end {
            let n = i % window.len();
            assert!(window[n].coding.is_none());

            window[n].coding = Some(SharedBlob::default());

            let coding = window[n].coding.clone().unwrap();
            let mut coding_wl = coding.write().unwrap();
            for i in 0..max_data_size {
                coding_wl.data[i] = 0;
            }
            // copy index and id from the data blob
            if let Some(data) = &window[n].data {
                let data_rl = data.read().unwrap();

                let index = data_rl.index().unwrap();
                let slot = data_rl.slot().unwrap();
                let id = data_rl.id().unwrap();

                trace!(
                    "{} copying index {} id {:?} from data to coding",
                    id,
                    index,
                    id
                );
                coding_wl.set_index(index).unwrap();
                coding_wl.set_slot(slot).unwrap();
                coding_wl.set_id(&id).unwrap();
            }
            coding_wl.set_size(max_data_size);
            if coding_wl.set_coding().is_err() {
                return Err(ErasureError::EncodeError);
            }

            coding_blobs.push(coding.clone());
        }

        let data_locks: Vec<_> = data_blobs.iter().map(|b| b.read().unwrap()).collect();

        let data_ptrs: Vec<_> = data_locks
            .iter()
            .enumerate()
            .map(|(i, l)| {
                trace!("{} i: {} data: {}", id, i, l.data[0]);
                &l.data[..max_data_size]
            }).collect();

        let mut coding_locks: Vec<_> = coding_blobs.iter().map(|b| b.write().unwrap()).collect();

        let mut coding_ptrs: Vec<_> = coding_locks
            .iter_mut()
            .enumerate()
            .map(|(i, l)| {
                trace!("{} i: {} coding: {}", id, i, l.data[0],);
                &mut l.data_mut()[..max_data_size]
            }).collect();

        generate_coding_blocks(coding_ptrs.as_mut_slice(), &data_ptrs)?;
        debug!(
            "{} start_idx: {} data: {}:{} coding: {}:{}",
            id, start_idx, block_start, block_end, coding_start, block_end
        );
        block_start = block_end;
    }
    Ok(())
}
// Generate coding blocks in window starting from start_idx,
//   for num_blobs..  For each block place the coding blobs
//   at the end of the block like so:
//
//  block-size part of a Window, with each element a WindowSlot..
//  |<======================= NUM_DATA ==============================>|
//                                              |<==== NUM_CODING ===>|
//  +---+ +---+ +---+ +---+ +---+         +---+ +---+ +---+ +---+ +---+
//  | D | | D | | D | | D | | D |         | D | | D | | D | | D | | D |
//  +---+ +---+ +---+ +---+ +---+  . . .  +---+ +---+ +---+ +---+ +---+
//  |   | |   | |   | |   | |   |         |   | | C | | C | | C | | C |
//  +---+ +---+ +---+ +---+ +---+         +---+ +---+ +---+ +---+ +---+
//
//  blob structure for coding, recover
//
//   + ------- meta is set and used by transport, meta.size is actual length
//   |           of data in the byte array blob.data
//   |
//   |          + -- data is stuff shipped over the wire, and has an included
//   |          |        header
//   V          V
//  +----------+------------------------------------------------------------+
//  | meta     |  data                                                      |
//  |+---+--   |+---+---+---+---+------------------------------------------+|
//  || s | .   || i |   | f | s |                                          ||
//  || i | .   || n | i | l | i |                                          ||
//  || z | .   || d | d | a | z |     blob.data(), or blob.data_mut()      ||
//  || e |     || e |   | g | e |                                          ||
//  |+---+--   || x |   | s |   |                                          ||
//  |          |+---+---+---+---+------------------------------------------+|
//  +----------+------------------------------------------------------------+
//             |                |<=== coding blob part for "coding" =======>|
//             |                                                            |
//             |<============== data blob part for "coding"  ==============>|
//
//
//
Generate coding blocks in window starting from start_idx,
for num_blobs..  For each block place the coding blobs
at the end of the block like so.



blob structure for coding, recover


Generate coding blocks in window starting from start_idx for num_blobs .. For each block place the coding blobs at the end of the block like so . blob structure for coding recover
pub fn generate_coding(
    id: &Pubkey,
    window: &mut [WindowSlot],
    receive_index: u64,
    num_blobs: usize,
    transmit_index_coding: &mut u64,
) -> Result<()> {
    // beginning of the coding blobs of the block that receive_index points into
    let coding_index_start =
        receive_index - (receive_index % NUM_DATA as u64) + (NUM_DATA - NUM_CODING) as u64;
    let start_idx = receive_index as usize % window.len();
    let mut block_start = start_idx - (start_idx % NUM_DATA);
    loop {
        let block_end = block_start + NUM_DATA;
        if block_end > (start_idx + num_blobs) {
            break;
        }
        info!(
            "generate_coding {} start: {} end: {} start_idx: {} num_blobs: {}",
            id, block_start, block_end, start_idx, num_blobs
        );
        let mut max_data_size = 0;
        // find max_data_size, maybe bail if not all the data is here
        for i in block_start..block_end {
            let n = i % window.len();
            trace!("{} window[{}] = {:?}", id, n, window[n].data);
            if let Some(b) = &window[n].data {
                max_data_size = cmp::max(b.read().unwrap().meta.size, max_data_size);
            } else {
                trace!("{} data block is null @ {}", id, n);
                return Ok(());
            }
        }
        // round up to the nearest jerasure alignment
        max_data_size = align!(max_data_size, JERASURE_ALIGN);
        trace!("{} max_data_size: {}", id, max_data_size);
        let mut data_blobs = Vec::with_capacity(NUM_DATA);
        for i in block_start..block_end {
            let n = i % window.len();
            if let Some(b) = &window[n].data {
                // make sure extra bytes in each blob are zero-d out for generation of
                //  coding blobs
                let mut b_wl = b.write().unwrap();
                for i in b_wl.meta.size..max_data_size {
                    b_wl.data[i] = 0;
                }
                data_blobs.push(b);
            }
        }
        // getting ready to do erasure coding, means that we're potentially
        // going back in time, tell our caller we've inserted coding blocks
        // starting at coding_index_start
        *transmit_index_coding = cmp::min(*transmit_index_coding, coding_index_start);
        let mut coding_blobs = Vec::with_capacity(NUM_CODING);
        let coding_start = block_end - NUM_CODING;
        for i in coding_start..block_end {
            let n = i % window.len();
            assert!(window[n].coding.is_none());
            window[n].coding = Some(SharedBlob::default());
            let coding = window[n].coding.clone().unwrap();
            let mut coding_wl = coding.write().unwrap();
            for i in 0..max_data_size {
                coding_wl.data[i] = 0;
            }
            // copy index and id from the data blob
            if let Some(data) = &window[n].data {
                let data_rl = data.read().unwrap();
                let index = data_rl.index().unwrap();
                let slot = data_rl.slot().unwrap();
                let id = data_rl.id().unwrap();
                trace!(
                    "{} copying index {} id {:?} from data to coding",
                    id,
                    index,
                    id
                );
                coding_wl.set_index(index).unwrap();
                coding_wl.set_slot(slot).unwrap();
                coding_wl.set_id(&id).unwrap();
            }
            coding_wl.set_size(max_data_size);
            if coding_wl.set_coding().is_err() {
                return Err(ErasureError::EncodeError);
            }
            coding_blobs.push(coding.clone());
        }
        let data_locks: Vec<_> = data_blobs.iter().map(|b| b.read().unwrap()).collect();
        let data_ptrs: Vec<_> = data_locks
            .iter()
            .enumerate()
            .map(|(i, l)| {
                trace!("{} i: {} data: {}", id, i, l.data[0]);
                &l.data[..max_data_size]
            }).collect();
        let mut coding_locks: Vec<_> = coding_blobs.iter().map(|b| b.write().unwrap()).collect();
        let mut coding_ptrs: Vec<_> = coding_locks
            .iter_mut()
            .enumerate()
            .map(|(i, l)| {
                trace!("{} i: {} coding: {}", id, i, l.data[0],);
                &mut l.data_mut()[..max_data_size]
            }).collect();
        generate_coding_blocks(coding_ptrs.as_mut_slice(), &data_ptrs)?;
        debug!(
            "{} start_idx: {} data: {}:{} coding: {}:{}",
            id, start_idx, block_start, block_end, coding_start, block_end
        );
        block_start = block_end;
    }
    Ok(())
}
pub fn generate_coding ( id : & Pubkey , window : & mut [ WindowSlot ] , receive_index : u64 , num_blobs : usize , transmit_index_coding : & mut u64 , ) -> Result < ( ) > { // beginning of the coding blobs of the block that receive_index points into let coding_index_start = receive_index - ( receive_index % NUM_DATA as u64 ) + ( NUM_DATA - NUM_CODING ) as u64 ; let start_idx = receive_index as usize % window . len ( ) ; let mut block_start = start_idx - ( start_idx % NUM_DATA ) ; loop { let block_end = block_start + NUM_DATA ; if block_end > ( start_idx + num_blobs ) { break ; } info ! ( " " id block_start block_end start_idx num_blobs ) ; let mut max_data_size = 0 ; // find max_data_size, maybe bail if not all the data is here for i in block_start .. block_end { let n = i % window . len ( ) ; trace ! ( " " id n window [ n ] data ) ; if let Some ( b ) = & window [ n ] . data { max_data_size = cmp :: max ( b . read ( ) . unwrap ( ) . meta . size , max_data_size ) ; } else { trace ! ( " " id n ) ; return Ok ( ( ) ) ; } } // round up to the nearest jerasure alignment max_data_size = align ! ( max_data_size JERASURE_ALIGN ) ; trace ! ( " " id max_data_size ) ; let mut data_blobs = Vec :: with_capacity ( NUM_DATA ) ; for i in block_start .. block_end { let n = i % window . len ( ) ; if let Some ( b ) = & window [ n ] . data { // make sure extra bytes in each blob are zero-d out for generation of //  coding blobs let mut b_wl = b . write ( ) . unwrap ( ) ; for i in b_wl . meta . size .. max_data_size { b_wl . data [ i ] = 0 ; } data_blobs . push ( b ) ; } } // getting ready to do erasure coding, means that we're potentially // going back in time, tell our caller we've inserted coding blocks // starting at coding_index_start * transmit_index_coding = cmp :: min ( * transmit_index_coding , coding_index_start ) ; let mut coding_blobs = Vec :: with_capacity ( NUM_CODING ) ; let coding_start = block_end - NUM_CODING ; for i in coding_start .. block_end { let n = i % window . len ( ) ; assert ! ( window [ n ] coding is_none ( ) ) ; window [ n ] . coding = Some ( SharedBlob :: default ( ) ) ; let coding = window [ n ] . coding . clone ( ) . unwrap ( ) ; let mut coding_wl = coding . write ( ) . unwrap ( ) ; for i in 0 .. max_data_size { coding_wl . data [ i ] = 0 ; } // copy index and id from the data blob if let Some ( data ) = & window [ n ] . data { let data_rl = data . read ( ) . unwrap ( ) ; let index = data_rl . index ( ) . unwrap ( ) ; let slot = data_rl . slot ( ) . unwrap ( ) ; let id = data_rl . id ( ) . unwrap ( ) ; trace ! ( " " id index id ) ; coding_wl . set_index ( index ) . unwrap ( ) ; coding_wl . set_slot ( slot ) . unwrap ( ) ; coding_wl . set_id ( & id ) . unwrap ( ) ; } coding_wl . set_size ( max_data_size ) ; if coding_wl . set_coding ( ) . is_err ( ) { return Err ( ErasureError :: EncodeError ) ; } coding_blobs . push ( coding . clone ( ) ) ; } let data_locks : Vec < _ > = data_blobs . iter ( ) . map ( | b | b . read ( ) . unwrap ( ) ) . collect ( ) ; let data_ptrs : Vec < _ > = data_locks . iter ( ) . enumerate ( ) . map ( | ( i , l ) | { trace ! ( " " id i l data [ 0 ] ) ; & l . data [ .. max_data_size ] } ) . collect ( ) ; let mut coding_locks : Vec < _ > = coding_blobs . iter ( ) . map ( | b | b . write ( ) . unwrap ( ) ) . collect ( ) ; let mut coding_ptrs : Vec < _ > = coding_locks . iter_mut ( ) . enumerate ( ) . map ( | ( i , l ) | { trace ! ( " " id i l data [ 0 ] ) ; & mut l . data_mut ( ) [ .. max_data_size ] } ) . collect ( ) ; generate_coding_blocks ( coding_ptrs . as_mut_slice ( ) , & data_ptrs ) ? ; debug ! ( " " id start_idx block_start block_end coding_start block_end ) ; block_start = block_end ; } Ok ( ( ) ) }
Generate coding blocks in window starting from start_idx,
for num_blobs..  For each block place the coding blobs
at the end of the block like so:
Generate coding blocks in window starting from start_idx for num_blobs .. For each block place the coding blobs at the end of the block like so :
id
&Pubkey
window
&mut [WindowSlot]
receive_index
u64
num_blobs
usize
transmit_index_coding
&mut u64
id
&Pubkey
window
&mut [WindowSlot]
receive_index
u64
num_blobs
usize
transmit_index_coding
&mut u64