LCOV - code coverage report
Current view: top level - funk - fd_funk_val.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 32 58 55.2 %
Date: 2025-07-01 05:00:49 Functions: 2 2 100.0 %

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

Generated by: LCOV version 1.14