LCOV - code coverage report
Current view: top level - funk - fd_funk_val.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 47 53 88.7 %
Date: 2025-10-27 04:40:00 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "fd_funk_private.h"
       2             : 
       3             : void *
       4             : fd_funk_val_truncate( fd_funk_rec_t * rec,
       5             :                       fd_alloc_t *    alloc,
       6             :                       fd_wksp_t *     wksp,
       7             :                       ulong           align,
       8             :                       ulong           sz,
       9     1277496 :                       int *           opt_err ) {
      10             : 
      11             :   /* Check input args */
      12             : 
      13             : #ifdef FD_FUNK_HANDHOLDING
      14             :   if( FD_UNLIKELY( (!rec) | (sz>FD_FUNK_REC_VAL_MAX) | (!alloc) | (!wksp) ) ||  /* NULL rec,too big,NULL alloc,NULL wksp */
      15             :       FD_UNLIKELY( !fd_ulong_is_pow2( align ) & (align != 0UL)            ) ) { /* Align is not a power of 2 or == 0 */
      16             :     fd_int_store_if( !!opt_err, opt_err, FD_FUNK_ERR_INVAL );
      17             :     return NULL;
      18             :   }
      19             : #endif
      20             : 
      21     1277496 :   ulong val_sz = (ulong)rec->val_sz;
      22     1277496 :   ulong val_max = (ulong)rec->val_max;
      23             : 
      24     1277496 :   if( FD_UNLIKELY( !sz ) ) {
      25             : 
      26             :     /* User asked to truncate to 0.  Flush the any existing value. */
      27             : 
      28           0 :     fd_funk_val_flush( rec, alloc, wksp );
      29             : 
      30           0 :     fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS );
      31           0 :     return NULL;
      32             : 
      33     1277496 :   } else if( FD_LIKELY( sz > val_max ) ) {
      34             : 
      35             :     /* User requested to increase the value size.  We presume they are
      36             :        asking for a specific size (as opposed to bumping up the size ala
      37             :        append) so we don't build in extra padding to amortize the cost
      38             :        of future truncates.  Note that new_val_sz is at least 1 at this
      39             :        point but val_sz / val_gaddr could be zero / zero. */
      40             : 
      41     1277034 :     ulong   val_gaddr = rec->val_gaddr;
      42     1277034 :     uchar * val       = val_max ? fd_wksp_laddr_fast( wksp, val_gaddr ) : NULL; /* TODO: branchless */
      43             : 
      44             :     /* NOTE: if the align is 0, we use the default alignment for
      45             :        fd_alloc_malloc_at_least */
      46     1277034 :     ulong   new_val_max;
      47     1277034 :     uchar * new_val = fd_alloc_malloc_at_least( alloc, align, sz, &new_val_max );
      48     1277034 :     if( FD_UNLIKELY( !new_val ) ) { /* Allocation failure! */
      49           0 :       fd_int_store_if( !!opt_err, opt_err, FD_FUNK_ERR_MEM );
      50           0 :       return NULL;
      51           0 :     }
      52             : 
      53     1277034 :     if( val_sz ) fd_memcpy( new_val, val, val_sz ); /* Copy the existing value */
      54     1277034 :     fd_memset( new_val + val_sz, 0, new_val_max - val_sz ); /* Clear out trailing padding to be on the safe side */
      55             : 
      56     1277034 :     rec->val_gaddr = fd_wksp_gaddr_fast( wksp, new_val );
      57     1277034 :     rec->val_sz    = (uint)( sz & FD_FUNK_REC_VAL_MAX );
      58     1277034 :     rec->val_max   = (uint)( fd_ulong_min( new_val_max, FD_FUNK_REC_VAL_MAX ) & FD_FUNK_REC_VAL_MAX );
      59             : 
      60     1277034 :     if( val ) fd_alloc_free( alloc, val ); /* Free the old value (if any) */
      61             : 
      62     1277034 :     fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS );
      63     1277034 :     return new_val;
      64             : 
      65     1277034 :   } else {
      66             : 
      67             :     /* Just set the new size */
      68             : 
      69         462 :     rec->val_sz = (uint)( sz & FD_FUNK_REC_VAL_MAX );
      70             : 
      71         462 :     fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS );
      72         462 :     return (uchar *)fd_wksp_laddr_fast( wksp, rec->val_gaddr );
      73             : 
      74         462 :   }
      75     1277496 : }
      76             : 
      77             : int
      78         249 : fd_funk_val_verify( fd_funk_t * funk ) {
      79         249 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
      80         249 :   ulong wksp_tag = funk->shmem->wksp_tag;
      81             : 
      82             :   /* At this point, rec_map has been extensively verified */
      83             : 
      84       53196 : # define TEST(c) do {                                                                           \
      85       53196 :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNK_ERR_INVAL; } \
      86       53196 :   } while(0)
      87             : 
      88             :   /* Iterate over all records in use */
      89             : 
      90         249 :   fd_funk_all_iter_t iter[1];
      91       13548 :   for( fd_funk_all_iter_new( funk, iter ); !fd_funk_all_iter_done( iter ); fd_funk_all_iter_next( iter ) ) {
      92       13299 :     fd_funk_rec_t const * rec = fd_funk_all_iter_ele_const( iter );
      93             : 
      94             :     /* Make sure values look sane */
      95             :     /* TODO: consider doing an alias analysis on allocated values?
      96             :        (tricky to do algo efficient in place) */
      97             : 
      98       13299 :     ulong val_sz    = (ulong)rec->val_sz;
      99       13299 :     ulong val_max   = (ulong)rec->val_max;
     100       13299 :     ulong val_gaddr = rec->val_gaddr;
     101             : 
     102       13299 :     TEST( val_sz<=val_max );
     103             : 
     104       13299 :     TEST( val_max<=FD_FUNK_REC_VAL_MAX );
     105       13299 :     if( !val_gaddr ) TEST( !val_max );
     106       13299 :     else {
     107       13299 :       TEST( (0UL<val_max) & (val_max<=FD_FUNK_REC_VAL_MAX) );
     108       13299 :       TEST( fd_wksp_tag( wksp, val_gaddr )==wksp_tag );
     109       13299 :     }
     110       13299 :   }
     111             : 
     112         249 : # undef TEST
     113             : 
     114         249 :   return FD_FUNK_SUCCESS;
     115         249 : }

Generated by: LCOV version 1.14