Line data Source code
1 : #include "fd_fec_repair.h" 2 : 3 : void * 4 0 : fd_fec_repair_new( void * shmem, ulong fec_max, uint shred_tile_cnt, ulong seed ) { 5 0 : ulong total_fecs_pow2 = fd_ulong_pow2_up( fec_max * shred_tile_cnt ); 6 : 7 0 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 8 0 : fd_fec_repair_t * repair = FD_SCRATCH_ALLOC_APPEND( l, fd_fec_repair_align(), sizeof(fd_fec_repair_t) ); 9 0 : void * intra_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_fec_intra_pool_align(), fd_fec_intra_pool_footprint( total_fecs_pow2 ) ); 10 0 : void * intra_map = FD_SCRATCH_ALLOC_APPEND( l, fd_fec_intra_map_align(), fd_fec_intra_map_footprint( total_fecs_pow2 ) ); 11 0 : void * order_pool_lst = FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong), sizeof(fd_fec_order_t*) * shred_tile_cnt ); 12 0 : void * order_dlist_lst = FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong), sizeof(fd_fec_order_dlist_t*) * shred_tile_cnt ); 13 : 14 0 : repair->intra_pool = fd_fec_intra_pool_new( intra_pool, total_fecs_pow2 ); 15 0 : repair->intra_map = fd_fec_intra_map_new ( intra_map, total_fecs_pow2, seed ); 16 0 : repair->order_pool_lst = (fd_fec_order_t **)order_pool_lst; 17 0 : repair->order_dlist_lst = (fd_fec_order_dlist_t **)order_dlist_lst; 18 : 19 0 : for( ulong i = 0UL; i < shred_tile_cnt; i++ ) { 20 0 : void * order_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_fec_order_pool_align(), fd_fec_order_pool_footprint( fec_max ) ); 21 0 : void * order_dlist = FD_SCRATCH_ALLOC_APPEND( l, fd_fec_order_dlist_align(), fd_fec_order_dlist_footprint() ); 22 0 : repair->order_pool_lst[i] = fd_fec_order_pool_new ( order_pool, fec_max ); 23 0 : repair->order_dlist_lst[i] = fd_fec_order_dlist_new( order_dlist ); 24 0 : } 25 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_fec_repair_align() ) == (ulong)shmem + fd_fec_repair_footprint( fec_max, shred_tile_cnt ) ); 26 : 27 0 : repair->fec_max = fec_max; 28 0 : repair->shred_tile_cnt = shred_tile_cnt; 29 : 30 0 : return repair; 31 0 : } 32 : 33 : fd_fec_repair_t * 34 0 : fd_fec_repair_join( void * shfec_repair ) { 35 0 : fd_fec_repair_t * fec_repair = (fd_fec_repair_t *)shfec_repair; 36 : 37 0 : fec_repair->intra_pool = fd_fec_intra_pool_join( fec_repair->intra_pool ); 38 0 : fec_repair->intra_map = fd_fec_intra_map_join( fec_repair->intra_map ); 39 : 40 0 : for( ulong i = 0UL; i < fec_repair->shred_tile_cnt; i++ ) { 41 0 : fec_repair->order_pool_lst[i] = fd_fec_order_pool_join ( fec_repair->order_pool_lst[i] ); 42 0 : fec_repair->order_dlist_lst[i] = fd_fec_order_dlist_join( fec_repair->order_dlist_lst[i] ); 43 0 : } 44 : 45 0 : return fec_repair; 46 0 : } 47 : 48 : void * 49 0 : fd_fec_repair_leave( fd_fec_repair_t const * fec_repair ) { 50 : 51 0 : if( FD_UNLIKELY( !fec_repair ) ) { 52 0 : FD_LOG_WARNING(( "NULL repair" )); 53 0 : return NULL; 54 0 : } 55 : 56 0 : return (void *)fec_repair; 57 0 : } 58 : 59 : void * 60 0 : fd_fec_repair_delete( void * shmem ) { 61 0 : fd_fec_repair_t * fec_repair = (fd_fec_repair_t *)shmem; 62 : 63 0 : if( FD_UNLIKELY( !fec_repair ) ) { 64 0 : FD_LOG_WARNING(( "NULL repair" )); 65 0 : return NULL; 66 0 : } 67 : 68 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)fec_repair, fd_fec_repair_align() ) ) ) { 69 0 : FD_LOG_WARNING(( "misaligned repair" )); 70 0 : return NULL; 71 0 : } 72 : 73 0 : return fec_repair; 74 0 : } 75 : 76 : int 77 : check_blind_fec_completed( fd_fec_repair_t const * fec_repair, 78 : fd_fec_chainer_t * fec_chainer, 79 : ulong slot, 80 0 : uint fec_set_idx ) { 81 0 : ulong fec_key = ( slot << 32 ) | ( fec_set_idx ); 82 0 : fd_fec_intra_t const * fec_intra = fd_fec_intra_map_ele_query_const( fec_repair->intra_map, &fec_key, NULL, fec_repair->intra_pool ); 83 0 : if( !fec_intra ) return 0; /* no fec set */ 84 0 : if( FD_LIKELY( fec_intra->data_cnt != 0 ) ) return 0; /* We have a coding shred for this FEC. Do not force complete. */ 85 0 : if( fec_intra->buffered_idx == UINT_MAX ) return 0; /* no buffered idx */ 86 0 : if( fec_intra->buffered_idx == fec_intra->completes_idx ) return 1; /* This happens when completes is populated by batch_complete flag or by the below */ 87 : 88 0 : ulong next_fec_key = ( slot << 32 ) | ( fec_set_idx + fec_intra->buffered_idx + 1 ); 89 0 : fd_fec_intra_t const * next_fec = fd_fec_intra_map_ele_query_const( fec_repair->intra_map, &next_fec_key, NULL, fec_repair->intra_pool ); 90 0 : if( !next_fec ) { 91 0 : fd_fec_ele_t * next_fec_c = fd_fec_chainer_query( fec_chainer, slot, fec_set_idx + fec_intra->buffered_idx + 1 ); 92 0 : if( !next_fec_c ) { 93 0 : return 0; /* no next fec set */ 94 0 : } 95 0 : } 96 0 : return 1; 97 0 : } 98 : 99 : int 100 : check_set_blind_fec_completed( fd_fec_repair_t * fec_repair, 101 : fd_fec_chainer_t * fec_chainer, 102 : ulong slot, 103 0 : uint fec_set_idx ) { 104 : 105 0 : ulong fec_key = ( slot << 32 ) | ( fec_set_idx ); 106 0 : fd_fec_intra_t * fec_intra = fd_fec_intra_map_ele_query( fec_repair->intra_map, &fec_key, NULL, fec_repair->intra_pool ); 107 : 108 0 : ulong next_fec_key = ( slot << 32 ) | ( fec_set_idx + fec_intra->buffered_idx + 1 ); 109 : 110 : /* speculate - is the next shred after this the next FEC set? */ 111 : 112 0 : if( FD_LIKELY( fec_intra->data_cnt != 0 ) ) return 0; /* We have a coding shred for this FEC. Do not force complete. */ 113 0 : if( fec_intra->buffered_idx == UINT_MAX ) return 0; 114 0 : if( fec_intra->buffered_idx == fec_intra->completes_idx ) return 1; /* This happens when completes is populated by batch_complete flag or by the below */ 115 : 116 0 : fd_fec_intra_t * next_fec = fd_fec_intra_map_ele_query( fec_repair->intra_map, &next_fec_key, NULL, fec_repair->intra_pool ); 117 0 : if( !next_fec ) { 118 0 : fd_fec_ele_t * next_fec_c = fd_fec_chainer_query( fec_chainer, slot, fec_set_idx + fec_intra->buffered_idx + 1 ); 119 0 : if( !next_fec_c ) { 120 0 : return 0; /* no next fec set */ 121 0 : } 122 0 : } 123 : 124 : /* we have discovered the end of a fec_set. Now check if we've actually buffered that much */ 125 : 126 0 : if( fec_intra->completes_idx == UINT_MAX ) { 127 0 : fec_intra->completes_idx = fec_intra->buffered_idx; 128 0 : } 129 : 130 0 : return ( fec_intra->buffered_idx != UINT_MAX && fec_intra->buffered_idx == fec_intra->completes_idx ); 131 0 : }