LCOV - code coverage report
Current view: top level - funk - fd_funk_part.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 135 159 84.9 %
Date: 2025-01-08 12:08:44 Functions: 9 9 100.0 %

          Line data    Source code
       1             : #include "fd_funk.h"
       2             : 
       3             : fd_funk_partvec_t *
       4             : fd_funk_get_partvec( fd_funk_t * funk,
       5    31839855 :                      fd_wksp_t * wksp /* Assumes wksp == fd_funk_wksp( funk ) */) {
       6    31839855 :   return (fd_funk_partvec_t *)fd_wksp_laddr_fast( wksp, funk->partvec_gaddr );
       7    31839855 : }
       8             : 
       9             : void
      10    36999750 : fd_funk_part_init( fd_funk_rec_t * rec ) {
      11    36999750 :   rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
      12    36999750 :   rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
      13    36999750 :   rec->part = FD_FUNK_PART_NULL;
      14    36999750 : }
      15             : 
      16             : /* Private function */
      17             : static int
      18             : fd_funk_part_remove( fd_funk_partvec_t * partvec,
      19             :                      fd_funk_rec_t *     rec_map,
      20             :                      fd_funk_rec_t *     rec,
      21     2643486 :                      uint                part) {
      22     2643486 :   if ( FD_UNLIKELY( part >= partvec->num_part ) )
      23           0 :     return FD_FUNK_ERR_INVAL;
      24             : 
      25     2643486 :   fd_funk_parthead_t * head = &partvec->heads[part];
      26             : 
      27     2643486 :   ulong prev_idx = rec->prev_part_idx;
      28     2643486 :   ulong next_idx = rec->next_part_idx;
      29             : 
      30     2643486 :   int prev_null = fd_funk_rec_idx_is_null( prev_idx );
      31     2643486 :   int next_null = fd_funk_rec_idx_is_null( next_idx );
      32             : 
      33     2643486 :   if( prev_null ) head->head_idx                    = next_idx;
      34     1193763 :   else            rec_map[ prev_idx ].next_part_idx = next_idx;
      35             : 
      36     2643486 :   if( next_null ) head->tail_idx                    = prev_idx;
      37      977226 :   else            rec_map[ next_idx ].prev_part_idx = prev_idx;
      38             : 
      39     2643486 :   rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
      40     2643486 :   rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
      41     2643486 :   rec->part = FD_FUNK_PART_NULL;
      42     2643486 :   return FD_FUNK_SUCCESS;
      43     2643486 : }
      44             : 
      45             : /* Private function */
      46             : static int
      47             : fd_funk_part_add( fd_funk_partvec_t * partvec,
      48             :                   fd_funk_rec_t *     rec_map,
      49             :                   fd_funk_rec_t *     rec,
      50    17648316 :                   uint                part) {
      51    17648316 :   if ( FD_UNLIKELY( part >= partvec->num_part ) )
      52           0 :     return FD_FUNK_ERR_INVAL;
      53             : 
      54    17648316 :   fd_funk_parthead_t * head = &partvec->heads[part];
      55             : 
      56    17648316 :   ulong rec_idx = (ulong)(rec - rec_map);
      57    17648316 :   ulong old_tail_idx = head->tail_idx;
      58    17648316 :   rec->prev_part_idx = old_tail_idx;
      59    17648316 :   head->tail_idx = rec_idx;
      60             : 
      61    17648316 :   rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
      62             : 
      63    17648316 :   if ( fd_funk_rec_idx_is_null( old_tail_idx ) ) head->head_idx = rec_idx;
      64     8109405 :   else                                           rec_map[old_tail_idx].next_part_idx = rec_idx;
      65             : 
      66    17648316 :   rec->part = part;
      67    17648316 :   return FD_FUNK_SUCCESS;
      68    17648316 : }
      69             : 
      70             : int
      71             : fd_funk_part_set_intern( fd_funk_partvec_t * partvec,
      72             :                          fd_funk_rec_t *     rec_map,
      73             :                          fd_funk_rec_t *     rec,
      74    12092778 :                          uint                part) {
      75    12092778 :   if (part == rec->part) return FD_FUNK_SUCCESS;
      76     3689325 :   if ((rec->flags & FD_FUNK_REC_FLAG_ERASE)) return FD_FUNK_ERR_INVAL;
      77             : 
      78     3689325 :   int err;
      79     3689325 :   if (rec->part != FD_FUNK_PART_NULL) {
      80     2643486 :     err = fd_funk_part_remove( partvec, rec_map, rec, rec->part );
      81     2643486 :     if ( FD_UNLIKELY( err ) ) return err;
      82     2643486 :   }
      83             : 
      84     3689325 :   if (part != FD_FUNK_PART_NULL) {
      85     1601154 :     err = fd_funk_part_add( partvec, rec_map, rec, part );
      86     1601154 :     if ( FD_UNLIKELY( err ) ) return err;
      87     1601154 :   }
      88             : 
      89     3689325 :   return FD_FUNK_SUCCESS;
      90     3689325 : }
      91             : 
      92             : int
      93             : fd_funk_part_set( fd_funk_t *     funk,
      94             :                   fd_funk_rec_t * rec,
      95     2101938 :                   uint            part) {
      96     2101938 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
      97     2101938 :   return fd_funk_part_set_intern( fd_funk_get_partvec(funk, wksp),
      98     2101938 :                                   fd_funk_rec_map(funk, wksp),
      99     2101938 :                                   rec,
     100     2101938 :                                   part );
     101     2101938 : }
     102             : 
     103             : void
     104             : fd_funk_repartition(fd_funk_t *            funk,
     105             :                     uint                   num_part,
     106             :                     fd_funk_repartition_cb cb,
     107     1569129 :                     void *                 cb_arg) {
     108     1569129 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
     109     1569129 :   fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
     110     1569129 :   fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
     111     1569129 :   fd_alloc_t * alloc = fd_funk_alloc( funk, wksp );
     112             : 
     113             :   /* Rebuild the header vector */
     114     1569129 :   fd_alloc_free( alloc, partvec );
     115             : 
     116     1569129 :   ulong tmp_max;
     117     1569129 :   partvec = (fd_funk_partvec_t *)fd_alloc_malloc_at_least( alloc, fd_funk_partvec_align(), fd_funk_partvec_footprint(num_part), &tmp_max );
     118     1569129 :   if( FD_UNLIKELY( !partvec ) ) {
     119           0 :     FD_LOG_ERR(( "partvec alloc failed" ));
     120           0 :   }
     121     1569129 :   partvec->num_part = num_part;
     122     1569129 :   funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
     123             : 
     124    14122161 :   for ( uint i = 0; i < num_part; ++i )
     125    12553032 :     partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
     126             : 
     127     1569129 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
     128    30712500 :        !fd_funk_rec_map_iter_done( rec_map, iter );
     129    29143371 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
     130    29143371 :     fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
     131    29143371 :     fd_funk_part_init( rec );
     132    29143371 :   }
     133             : 
     134     1569129 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
     135    30712500 :        !fd_funk_rec_map_iter_done( rec_map, iter );
     136    29143371 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
     137    29143371 :     fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
     138    29143371 :     if ( !(rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
     139    20060841 :       uint part = (*cb)(rec, num_part, cb_arg);
     140    20060841 :       if (part != FD_FUNK_PART_NULL) {
     141    16047162 :         int err = fd_funk_part_add( partvec, rec_map, rec, part );
     142    16047162 :         if ( FD_UNLIKELY( err ) ) FD_LOG_WARNING(( "error during repartition: %d", err ));
     143    16047162 :       }
     144    20060841 :     }
     145    29143371 :   }
     146     1569129 : }
     147             : 
     148             : void
     149           3 : fd_funk_set_num_partitions( fd_funk_t * funk, uint num_part ) {
     150           3 :   fd_wksp_t * wksp            = fd_funk_wksp( funk );
     151           3 :   fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
     152           3 :   fd_alloc_t * alloc          = fd_funk_alloc( funk, wksp );
     153             : 
     154             :   /* Already have the desired number of partitions */
     155           3 :   if ( partvec->num_part == num_part ) {
     156           0 :     return;
     157           0 :   }
     158             : 
     159             :   /* Rebuild the header vector */
     160           3 :   fd_alloc_free( alloc, partvec );
     161             : 
     162           3 :   ulong tmp_max;
     163           3 :   partvec = (fd_funk_partvec_t *)fd_alloc_malloc_at_least( alloc, fd_funk_partvec_align(), fd_funk_partvec_footprint(num_part), &tmp_max );
     164           3 :   if( FD_UNLIKELY( !partvec ) ) {
     165           0 :     FD_LOG_ERR(( "partvec alloc failed" ));
     166           0 :     return;
     167           0 :   }
     168           3 :   partvec->num_part = num_part;
     169           3 :   funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
     170             : 
     171          27 :   for ( uint i = 0; i < num_part; ++i ) {
     172          24 :     partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
     173          24 :   }
     174           3 : }
     175             : 
     176             : int
     177    22275108 : fd_funk_part_verify( fd_funk_t * funk ) {
     178    22275108 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
     179    22275108 :   fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
     180    22275108 :   fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
     181             : 
     182    22275108 :   ulong cnt = 0;
     183   124978404 :   for ( uint i = 0; i < partvec->num_part; ++i ) {
     184   102703296 :     ulong prev = FD_FUNK_REC_IDX_NULL;
     185   102703296 :     ulong cur = partvec->heads[i].head_idx;
     186   222981366 :     while ( !fd_funk_rec_idx_is_null(cur) ) {
     187   120278070 :       fd_funk_rec_t * rec = rec_map + cur;
     188   120278070 :       if ( fd_funk_rec_map_private_unbox_tag( rec->map_next ) || (rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
     189           0 :         FD_LOG_WARNING(( "partition contains deleted record" ));
     190           0 :         return FD_FUNK_ERR_INVAL;
     191           0 :       }
     192   120278070 :       if ( rec->prev_part_idx != prev ) {
     193           0 :         FD_LOG_WARNING(( "prev_part_idx is wrong" ));
     194           0 :         return FD_FUNK_ERR_INVAL;
     195           0 :       }
     196   120278070 :       if ( rec->part != i ) {
     197           0 :         FD_LOG_WARNING(( "part is wrong" ));
     198           0 :         return FD_FUNK_ERR_INVAL;
     199           0 :       }
     200   120278070 :       prev = cur;
     201   120278070 :       cur = rec->next_part_idx;
     202   120278070 :       ++cnt;
     203   120278070 :     }
     204   102703296 :     if ( partvec->heads[i].tail_idx != prev ) {
     205           0 :       FD_LOG_WARNING(( "tail_idx is wrong" ));
     206           0 :       return FD_FUNK_ERR_INVAL;
     207           0 :     }
     208   102703296 :   }
     209             : 
     210    22275108 :   ulong cnt2 = 0;
     211    22275108 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
     212   903401892 :        !fd_funk_rec_map_iter_done( rec_map, iter );
     213   881126784 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
     214   881126784 :     fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
     215   881126784 :     if (rec->part != FD_FUNK_PART_NULL)
     216   120278070 :       ++cnt2;
     217   881126784 :   }
     218    22275108 :   if ( cnt != cnt2 ) {
     219           0 :     FD_LOG_WARNING(( "part is wrong for some records" ));
     220           0 :     return FD_FUNK_ERR_INVAL;
     221           0 :   }
     222             : 
     223    22275108 :   return FD_FUNK_SUCCESS;
     224    22275108 : }

Generated by: LCOV version 1.14