LCOV - code coverage report
Current view: top level - funk - fd_funk_part.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 135 160 84.4 %
Date: 2024-11-13 11:58:15 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    30100329 :                      fd_wksp_t * wksp /* Assumes wksp == fd_funk_wksp( funk ) */) {
       6    30100329 :   return (fd_funk_partvec_t *)fd_wksp_laddr_fast( wksp, funk->partvec_gaddr );
       7    30100329 : }
       8             : 
       9             : void
      10    27248220 : fd_funk_part_init( fd_funk_rec_t * rec ) {
      11    27248220 :   rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
      12    27248220 :   rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
      13    27248220 :   rec->part = FD_FUNK_PART_NULL;
      14    27248220 : }
      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     3119028 :                      uint                part) {
      22     3119028 :   if ( FD_UNLIKELY( part >= partvec->num_part ) )
      23           0 :     return FD_FUNK_ERR_INVAL;
      24             : 
      25     3119028 :   fd_funk_parthead_t * head = &partvec->heads[part];
      26             : 
      27     3119028 :   ulong prev_idx = rec->prev_part_idx;
      28     3119028 :   ulong next_idx = rec->next_part_idx;
      29             : 
      30     3119028 :   int prev_null = fd_funk_rec_idx_is_null( prev_idx );
      31     3119028 :   int next_null = fd_funk_rec_idx_is_null( next_idx );
      32             : 
      33     3119028 :   if( prev_null ) head->head_idx                    = next_idx;
      34     1383198 :   else            rec_map[ prev_idx ].next_part_idx = next_idx;
      35             : 
      36     3119028 :   if( next_null ) head->tail_idx                    = prev_idx;
      37     1201635 :   else            rec_map[ next_idx ].prev_part_idx = prev_idx;
      38             : 
      39     3119028 :   rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
      40     3119028 :   rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
      41     3119028 :   rec->part = FD_FUNK_PART_NULL;
      42     3119028 :   return FD_FUNK_SUCCESS;
      43     3119028 : }
      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    18127206 :                   uint                part) {
      51    18127206 :   if ( FD_UNLIKELY( part >= partvec->num_part ) )
      52           0 :     return FD_FUNK_ERR_INVAL;
      53             : 
      54    18127206 :   fd_funk_parthead_t * head = &partvec->heads[part];
      55             : 
      56    18127206 :   ulong rec_idx = (ulong)(rec - rec_map);
      57    18127206 :   ulong old_tail_idx = head->tail_idx;
      58    18127206 :   rec->prev_part_idx = old_tail_idx;
      59    18127206 :   head->tail_idx = rec_idx;
      60             : 
      61    18127206 :   rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
      62             : 
      63    18127206 :   if ( fd_funk_rec_idx_is_null( old_tail_idx ) ) head->head_idx = rec_idx;
      64     8453760 :   else                                           rec_map[old_tail_idx].next_part_idx = rec_idx;
      65             : 
      66    18127206 :   rec->part = part;
      67    18127206 :   return FD_FUNK_SUCCESS;
      68    18127206 : }
      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    10283355 :                          uint                part) {
      75    10283355 :   if (part == rec->part) return FD_FUNK_SUCCESS;
      76     4349430 :   if ((rec->flags & FD_FUNK_REC_FLAG_ERASE)) return FD_FUNK_ERR_INVAL;
      77             : 
      78     4349430 :   int err;
      79     4349430 :   if (rec->part != FD_FUNK_PART_NULL) {
      80     3119028 :     err = fd_funk_part_remove( partvec, rec_map, rec, rec->part );
      81     3119028 :     if ( FD_UNLIKELY( err ) ) return err;
      82     3119028 :   }
      83             : 
      84     4349430 :   if (part != FD_FUNK_PART_NULL) {
      85     2080044 :     err = fd_funk_part_add( partvec, rec_map, rec, part );
      86     2080044 :     if ( FD_UNLIKELY( err ) ) return err;
      87     2080044 :   }
      88             : 
      89     4349430 :   return FD_FUNK_SUCCESS;
      90     4349430 : }
      91             : 
      92             : int
      93             : fd_funk_part_set( fd_funk_t *     funk,
      94             :                   fd_funk_rec_t * rec,
      95     2107938 :                   uint            part) {
      96     2107938 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
      97     2107938 :   return fd_funk_part_set_intern( fd_funk_get_partvec(funk, wksp),
      98     2107938 :                                   fd_funk_rec_map(funk, wksp),
      99     2107938 :                                   rec,
     100     2107938 :                                   part );
     101     2107938 : }
     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 :     return;
     121           0 :   }
     122     1569129 :   partvec->num_part = num_part;
     123     1569129 :   funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
     124             : 
     125    14122161 :   for ( uint i = 0; i < num_part; ++i )
     126    12553032 :     partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
     127             : 
     128     1569129 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
     129    22338834 :        !fd_funk_rec_map_iter_done( rec_map, iter );
     130    20769705 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
     131    20769705 :     fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
     132    20769705 :     fd_funk_part_init( rec );
     133    20769705 :   }
     134             : 
     135     1569129 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
     136    22338834 :        !fd_funk_rec_map_iter_done( rec_map, iter );
     137    20769705 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
     138    20769705 :     fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
     139    20769705 :     if ( !(rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
     140    20060841 :       uint part = (*cb)(rec, num_part, cb_arg);
     141    20060841 :       if (part != FD_FUNK_PART_NULL) {
     142    16047162 :         int err = fd_funk_part_add( partvec, rec_map, rec, part );
     143    16047162 :         if ( FD_UNLIKELY( err ) ) FD_LOG_WARNING(( "error during repartition: %d", err ));
     144    16047162 :       }
     145    20060841 :     }
     146    20769705 :   }
     147     1569129 : }
     148             : 
     149             : void
     150         306 : fd_funk_set_num_partitions( fd_funk_t * funk, uint num_part ) {
     151         306 :   fd_wksp_t * wksp            = fd_funk_wksp( funk );
     152         306 :   fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
     153         306 :   fd_alloc_t * alloc          = fd_funk_alloc( funk, wksp );
     154             : 
     155             :   /* Already have the desired number of partitions */
     156         306 :   if ( partvec->num_part == num_part ) {
     157           0 :     return;
     158           0 :   }
     159             : 
     160             :   /* Rebuild the header vector */
     161         306 :   fd_alloc_free( alloc, partvec );
     162             : 
     163         306 :   ulong tmp_max;
     164         306 :   partvec = (fd_funk_partvec_t *)fd_alloc_malloc_at_least( alloc, fd_funk_partvec_align(), fd_funk_partvec_footprint(num_part), &tmp_max );
     165         306 :   if( FD_UNLIKELY( !partvec ) ) {
     166           0 :     FD_LOG_ERR(( "partvec alloc failed" ));
     167           0 :     return;
     168           0 :   }
     169         306 :   partvec->num_part = num_part;
     170         306 :   funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
     171             : 
     172        2754 :   for ( uint i = 0; i < num_part; ++i ) {
     173        2448 :     partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
     174        2448 :   }
     175         306 : }
     176             : 
     177             : int
     178    22026408 : fd_funk_part_verify( fd_funk_t * funk ) {
     179    22026408 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
     180    22026408 :   fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
     181    22026408 :   fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
     182             : 
     183    22026408 :   ulong cnt = 0;
     184   122740104 :   for ( uint i = 0; i < partvec->num_part; ++i ) {
     185   100713696 :     ulong prev = FD_FUNK_REC_IDX_NULL;
     186   100713696 :     ulong cur = partvec->heads[i].head_idx;
     187   220989045 :     while ( !fd_funk_rec_idx_is_null(cur) ) {
     188   120275349 :       fd_funk_rec_t * rec = rec_map + cur;
     189   120275349 :       if ( fd_funk_rec_map_private_unbox_tag( rec->map_next ) || (rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
     190           0 :         FD_LOG_WARNING(( "partition contains deleted record" ));
     191           0 :         return FD_FUNK_ERR_INVAL;
     192           0 :       }
     193   120275349 :       if ( rec->prev_part_idx != prev ) {
     194           0 :         FD_LOG_WARNING(( "prev_part_idx is wrong" ));
     195           0 :         return FD_FUNK_ERR_INVAL;
     196           0 :       }
     197   120275349 :       if ( rec->part != i ) {
     198           0 :         FD_LOG_WARNING(( "part is wrong" ));
     199           0 :         return FD_FUNK_ERR_INVAL;
     200           0 :       }
     201   120275349 :       prev = cur;
     202   120275349 :       cur = rec->next_part_idx;
     203   120275349 :       ++cnt;
     204   120275349 :     }
     205   100713696 :     if ( partvec->heads[i].tail_idx != prev ) {
     206           0 :       FD_LOG_WARNING(( "tail_idx is wrong" ));
     207           0 :       return FD_FUNK_ERR_INVAL;
     208           0 :     }
     209   100713696 :   }
     210             : 
     211    22026408 :   ulong cnt2 = 0;
     212    22026408 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
     213   606388173 :        !fd_funk_rec_map_iter_done( rec_map, iter );
     214   584361765 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
     215   584361765 :     fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
     216   584361765 :     if (rec->part != FD_FUNK_PART_NULL)
     217   120275349 :       ++cnt2;
     218   584361765 :   }
     219    22026408 :   if ( cnt != cnt2 ) {
     220           0 :     FD_LOG_WARNING(( "part is wrong for some records" ));
     221           0 :     return FD_FUNK_ERR_INVAL;
     222           0 :   }
     223             : 
     224    22026408 :   return FD_FUNK_SUCCESS;
     225    22026408 : }

Generated by: LCOV version 1.14