LCOV - code coverage report
Current view: top level - funk - fd_funk_val.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 30 36 83.3 %
Date: 2026-05-27 08:23:31 Functions: 12 238 5.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_funk_fd_funk_val_h
       2             : #define HEADER_fd_src_funk_fd_funk_val_h
       3             : 
       4             : /* This provides APIs for managing funk record values.  It is generally
       5             :    not meant to be included directly.  Use fd_funk.h instead. */
       6             : 
       7             : #include "fd_funk_rec.h" /* Includes fd_funk_txn.h, fd_funk_base.h */
       8             : 
       9             : /* FD_FUNK_REC_VAL_MAX is the maximum size of a record value. */
      10             : 
      11     7305801 : #define FD_FUNK_REC_VAL_MAX ((1UL<<28)-1UL)
      12             : #define FD_FUNK_VAL_ALIGN   (8UL)
      13             : 
      14    53352372 : #define FD_FUNK_VAL_SHRINK_FREE_THRESHOLD (512UL<<10) /* 512 KiB */
      15             : 
      16             : FD_PROTOTYPES_BEGIN
      17             : 
      18             : /* Accessors */
      19             : 
      20             : /* fd_funk_val_{sz,max} returns the current size of the value associated
      21             :    with a record and the amount of wksp allocated currently for a value.
      22             :    Assumes funk is a current local join.  These value might change on
      23             :    subsequent calls if the record is resized.
      24             :    0<=sz<=max<=FD_FUNK_REC_VAL_MAX. */
      25             : 
      26             : FD_FN_PURE static inline ulong                /* Current size of the record's value in bytes */
      27           0 : fd_funk_val_sz( fd_funk_rec_t const * rec ) { /* Assumes pointer in caller's address space to a live funk record */
      28           0 :   return (ulong)rec->val_sz; /* Covers the marked ERASE case too */
      29           0 : }
      30             : 
      31             : FD_FN_PURE static inline ulong                 /* Current size of the record's value allocation in bytes */
      32           0 : fd_funk_val_max( fd_funk_rec_t const * rec ) { /* Assumes pointer in caller's address space to a live funk record */
      33           0 :   return (ulong)rec->val_max; /* Covers the marked ERASE case too */
      34           0 : }
      35             : 
      36             : /* fd_funk_val returns a pointer in the caller's address space to the
      37             :    current value associated with a record.  fd_funk_rec_val_const is a
      38             :    const-correct version.  There are sz bytes at the returned pointer.
      39             :    IMPORTANT SAFETY TIP!  There are _no_ alignment guarantees on the
      40             :    returned value.  Returns NULL if the record has a zero sz (which also
      41             :    covers the case where rec has been marked ERASE).  max 0 implies val
      42             :    NULL and vice versa.  Assumes no concurrent operations on rec. */
      43             : 
      44             : FD_FN_PURE static inline void *             /* Lifetime is the lesser of rec or the value size is modified */
      45             : fd_funk_val( fd_funk_rec_t const * rec,     /* Assumes pointer in caller's address space to a live funk record */
      46     3601971 :              fd_wksp_t const *     wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */
      47     3601971 :   ulong val_gaddr = rec->val_gaddr;
      48     3601971 :   if( !val_gaddr ) return NULL; /* Covers the marked ERASE case too */ /* TODO: consider branchless */
      49     3601971 :   return fd_wksp_laddr_fast( wksp, val_gaddr );
      50     3601971 : }
      51             : 
      52             : FD_FN_PURE static inline void const *             /* Lifetime is the lesser of rec or the value size is modified */
      53             : fd_funk_val_const( fd_funk_rec_t const * rec,     /* Assumes pointer in caller's address space to a live funk record */
      54          48 :                    fd_wksp_t const *     wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */
      55          48 :   ulong val_gaddr = rec->val_gaddr;
      56          48 :   if( !val_gaddr ) return NULL; /* Covers the marked ERASE case too */ /* TODO: consider branchless */
      57          48 :   return fd_wksp_laddr_fast( wksp, val_gaddr );
      58          48 : }
      59             : 
      60             : FD_FN_CONST static inline int
      61             : fd_funk_val_shrink_compacts( ulong sz,
      62    54641670 :                              ulong val_max ) {
      63    54641670 :   return (sz<val_max) &&
      64    54641670 :          ( ( (5UL*sz)<(4UL*val_max) ) |
      65    28180401 :            ( (val_max-sz)>FD_FUNK_VAL_SHRINK_FREE_THRESHOLD ) );
      66    54641670 : }
      67             : 
      68             : /* fd_funk_val_truncate resizes a record to be new_val_sz bytes in
      69             :    size.  Invalidates val_gaddr.
      70             : 
      71             :    If the requested size is larger than the current allocation, this
      72             :    reallocates the record.  If the requested size is smaller than the
      73             :    current allocation, reallocates if fd_funk_val_shrink_compacts()==1.
      74             : 
      75             :    Returns a pointer to the value memory on success and NULL on
      76             :    failure.  If opt_err is non-NULL, on return, *opt_err will hold
      77             :    FD_FUNK_SUCCESS if successful or a FD_FUNK_ERR_* code on
      78             :    failure.  Reasons for failure include FD_FUNK_ERR_INVAL (NULL
      79             :    rec, too large new_val_sz, rec is marked ERASE) and
      80             :    FD_FUNK_ERR_MEM (allocation failure, need a larger wksp).  On
      81             :    failure, the current value is unchanged.
      82             : 
      83             :    Assumes no concurrent operations on rec. */
      84             : 
      85             : void *                                            /* Returns record value on success, NULL on failure */
      86             : fd_funk_val_truncate( fd_funk_rec_t * rec,        /* Assumed in caller's address space to a live funk record (NULL returns NULL) */
      87             :                       fd_alloc_t *    alloc,      /* ==fd_funk_alloc( funk, wksp ) */
      88             :                       fd_wksp_t *     wksp,       /* ==fd_funk_wksp( funk ) where funk is current local join */
      89             :                       ulong           align,      /* Must be a power of 2. 0 uses the fd_funk_alloc_malloc default alignment. */
      90             :                       ulong           sz,         /* Should be in [0,FD_FUNK_REC_VAL_MAX] (returns NULL otherwise) */
      91             :                       int *           opt_err );  /* If non-NULL, *opt_err returns operation error code */
      92             : 
      93             : /* Misc */
      94             : 
      95             : /* fd_funk_val_init sets a record with uninitialized value metadata to
      96             :    the NULL value.  Meant for internal use. */
      97             : 
      98             : static inline fd_funk_rec_t *                /* Returns rec */
      99     2648448 : fd_funk_val_init( fd_funk_rec_t * rec ) { /* Assumed record in caller's address space with uninitialized value metadata */
     100     2648448 :   rec->val_sz      = 0U;
     101     2648448 :   rec->val_max     = 0U;
     102     2648448 :   rec->val_gaddr   = 0UL;
     103     2648448 :   return rec;
     104     2648448 : }
     105             : 
     106             : /* fd_funk_val_flush sets a record to the NULL value, discarding the
     107             :    current value if any.  Meant for internal use. */
     108             : 
     109             : static inline fd_funk_rec_t *               /* Returns rec */
     110             : fd_funk_val_flush( fd_funk_rec_t * rec,     /* Assumed live funk record in caller's address space */
     111             :                    fd_alloc_t *    alloc,   /* ==fd_funk_alloc( funk, wksp ) */
     112     1371480 :                    fd_wksp_t *     wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */
     113     1371480 :   ulong val_gaddr = rec->val_gaddr;
     114     1371480 :   fd_funk_val_init( rec );
     115     1371480 :   FD_COMPILER_MFENCE(); /* Make sure we don't double free on crash recovery */
     116     1371480 :   if( val_gaddr ) fd_alloc_free( alloc, fd_wksp_laddr_fast( wksp, val_gaddr ) );
     117     1371480 :   return rec;
     118     1371480 : }
     119             : 
     120             : /* fd_funk_val_verify verifies the record values.  Returns
     121             :    FD_FUNK_SUCCESS if the values appear intact and FD_FUNK_ERR_INVAL if
     122             :    not (logs details).  Meant to be called as part of fd_funk_verify.
     123             :    As such, it assumes funk is non-NULL, fd_funk_{wksp,rec_map,wksp_tag}
     124             :    have been verified to work and the rec_map has been verified. */
     125             : 
     126             : int
     127             : fd_funk_val_verify( fd_funk_t * funk );
     128             : 
     129             : FD_PROTOTYPES_END
     130             : 
     131             : /* TODO: Retune fd_alloc and fd_wksp for Solana record size optimized
     132             :    size classes and transition point to fd_wksp backing. */
     133             : 
     134             : #endif /* HEADER_fd_src_funk_fd_funk_val_h */

Generated by: LCOV version 1.14