LCOV - code coverage report
Current view: top level - funk - fd_funk_val.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 36 53 67.9 %
Date: 2025-10-13 04:42:14 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     1718862 :                       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     1718862 :   ulong val_sz = (ulong)rec->val_sz;
      22     1718862 :   ulong val_max = (ulong)rec->val_max;
      23             : 
      24     1718862 :   if( FD_UNLIKELY( !sz ) ) {
      25             : 
      26             :     /* User asked to truncate to 0.  Flush the any existing value. */
      27             : 
      28      158478 :     fd_funk_val_flush( rec, alloc, wksp );
      29             : 
      30      158478 :     fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS );
      31      158478 :     return NULL;
      32             : 
      33     1560384 :   } 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     1560357 :     ulong   val_gaddr = rec->val_gaddr;
      42     1560357 :     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     1560357 :     ulong   new_val_max;
      47     1560357 :     uchar * new_val = fd_alloc_malloc_at_least( alloc, align, sz, &new_val_max );
      48     1560357 :     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     1560357 :     if( val_sz ) fd_memcpy( new_val, val, val_sz ); /* Copy the existing value */
      54     1560357 :     fd_memset( new_val + val_sz, 0, new_val_max - val_sz ); /* Clear out trailing padding to be on the safe side */
      55             : 
      56     1560357 :     rec->val_gaddr = fd_wksp_gaddr_fast( wksp, new_val );
      57     1560357 :     rec->val_sz    = (uint)( sz & FD_FUNK_REC_VAL_MAX );
      58     1560357 :     rec->val_max   = (uint)( fd_ulong_min( new_val_max, FD_FUNK_REC_VAL_MAX ) & FD_FUNK_REC_VAL_MAX );
      59             : 
      60     1560357 :     if( val ) fd_alloc_free( alloc, val ); /* Free the old value (if any) */
      61             : 
      62     1560357 :     fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS );
      63     1560357 :     return new_val;
      64             : 
      65     1560357 :   } else {
      66             : 
      67             :     /* Just set the new size */
      68             : 
      69          27 :     rec->val_sz = (uint)( sz & FD_FUNK_REC_VAL_MAX );
      70             : 
      71          27 :     fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS );
      72          27 :     return (uchar *)fd_wksp_laddr_fast( wksp, rec->val_gaddr );
      73             : 
      74          27 :   }
      75     1718862 : }
      76             : 
      77             : int
      78          12 : fd_funk_val_verify( fd_funk_t * funk ) {
      79          12 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
      80          12 :   ulong wksp_tag = funk->shmem->wksp_tag;
      81             : 
      82             :   /* At this point, rec_map has been extensively verified */
      83             : 
      84          12 : # define TEST(c) do {                                                                           \
      85           0 :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNK_ERR_INVAL; } \
      86           0 :   } while(0)
      87             : 
      88             :   /* Iterate over all records in use */
      89             : 
      90          12 :   fd_funk_all_iter_t iter[1];
      91          12 :   for( fd_funk_all_iter_new( funk, iter ); !fd_funk_all_iter_done( iter ); fd_funk_all_iter_next( iter ) ) {
      92           0 :     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           0 :     ulong val_sz    = (ulong)rec->val_sz;
      99           0 :     ulong val_max   = (ulong)rec->val_max;
     100           0 :     ulong val_gaddr = rec->val_gaddr;
     101             : 
     102           0 :     TEST( val_sz<=val_max );
     103             : 
     104           0 :     TEST( val_max<=FD_FUNK_REC_VAL_MAX );
     105           0 :     if( !val_gaddr ) TEST( !val_max );
     106           0 :     else {
     107           0 :       TEST( (0UL<val_max) & (val_max<=FD_FUNK_REC_VAL_MAX) );
     108           0 :       TEST( fd_wksp_tag( wksp, val_gaddr )==wksp_tag );
     109           0 :     }
     110           0 :   }
     111             : 
     112          12 : # undef TEST
     113             : 
     114          12 :   return FD_FUNK_SUCCESS;
     115          12 : }

Generated by: LCOV version 1.14