LCOV - code coverage report
Current view: top level - funk - fd_funk_rec.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 9 11 81.8 %
Date: 2025-10-24 04:32:27 Functions: 5 592 0.8 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_funk_fd_funk_rec_h
       2             : #define HEADER_fd_src_funk_fd_funk_rec_h
       3             : 
       4             : /* fd_funk_rec.h provides APIs for managing funk records */
       5             : 
       6             : #include "fd_funk_txn.h" /* Includes fd_funk_base.h */
       7             : 
       8             : /* FD_FUNK_REC_{ALIGN,FOOTPRINT} describe the alignment and footprint of
       9             :    a fd_funk_rec_t.  ALIGN will be a power of 2, footprint will be a
      10             :    multiple of align.  These are provided to facilitate compile time
      11             :    declarations. */
      12             : 
      13             : #define FD_FUNK_REC_ALIGN     (32UL)
      14             : 
      15             : /* FD_FUNK_REC_IDX_NULL gives the map record idx value used to represent
      16             :    NULL.  This value also set a limit on how large rec_max can be. */
      17             : 
      18     2869059 : #define FD_FUNK_REC_IDX_NULL (UINT_MAX)
      19             : 
      20             : /* A fd_funk_rec_t describes a funk record. */
      21             : 
      22             : struct __attribute__((aligned(FD_FUNK_REC_ALIGN))) fd_funk_rec {
      23             : 
      24             :   /* These fields are managed by the funk's rec_map */
      25             : 
      26             :   fd_funk_xid_key_pair_t pair;     /* Transaction id and record key pair */
      27             :   uint                   map_next; /* Internal use by map */
      28             : 
      29             :   /* These fields are managed by the user */
      30             : 
      31             :   uchar user[ 12 ];
      32             : 
      33             :   /* These fields are managed by funk.  TODO: Consider using record
      34             :      index compression here (much more debatable than in txn itself). */
      35             : 
      36             :   uint  next_idx;  /* Record map index of next record in its transaction */
      37             :   uint  prev_idx;  /* Record map index of previous record in its transaction */
      38             : 
      39             :   /* Note: use of uint here requires FD_FUNK_REC_VAL_MAX to be at most
      40             :      (1UL<<28)-1. */
      41             : 
      42             :   ulong val_sz  : 28;  /* Num bytes in record value, in [0,val_max] */
      43             :   ulong val_max : 28;  /* Max byte  in record value, in [0,FD_FUNK_REC_VAL_MAX], 0 if val_gaddr is 0 */
      44             :   ulong tag     :  1;  /* Used for internal validation */
      45             :   ulong val_gaddr; /* Wksp gaddr on record value if any, 0 if val_max is 0
      46             :                       If non-zero, the region [val_gaddr,val_gaddr+val_max) will be a current fd_alloc allocation (such that it is
      47             :                       has tag wksp_tag) and the owner of the region will be the record. The allocator is
      48             :                       fd_funk_alloc(). IMPORTANT! HAS NO GUARANTEED ALIGNMENT! */
      49             : 
      50             : };
      51             : 
      52             : typedef struct fd_funk_rec fd_funk_rec_t;
      53             : 
      54             : FD_STATIC_ASSERT( sizeof(fd_funk_rec_t) == 3U*FD_FUNK_REC_ALIGN, record size is wrong );
      55             : 
      56             : /* fd_funk_rec_map allows for indexing records by their (xid,key) pair.
      57             :    It is used to store all records of the last published transaction and
      58             :    the records being updated for a transaction that is in-preparation.
      59             :    Published records are stored under the pair (root,key).  (This is
      60             :    done so that publishing a transaction doesn't require updating all
      61             :    transaction id of all the records that were not updated by the
      62             :    publish.) */
      63             : 
      64             : #define POOL_NAME       fd_funk_rec_pool
      65             : #define POOL_ELE_T      fd_funk_rec_t
      66             : #define POOL_IDX_T      uint
      67             : #define POOL_NEXT       map_next
      68             : #define POOL_IMPL_STYLE 1
      69             : #define POOL_LAZY       1
      70             : #include "../util/tmpl/fd_pool_para.c"
      71             : 
      72             : #define MAP_NAME              fd_funk_rec_map
      73          51 : #define MAP_ELE_T             fd_funk_rec_t
      74             : #define MAP_KEY_T             fd_funk_xid_key_pair_t
      75             : #define MAP_KEY               pair
      76         177 : #define MAP_KEY_EQ(k0,k1)     fd_funk_xid_key_pair_eq((k0),(k1))
      77        5145 : #define MAP_KEY_HASH(k0,seed) fd_funk_xid_key_pair_hash((k0),(seed))
      78             : #define MAP_IDX_T             uint
      79          51 : #define MAP_NEXT              map_next
      80             : #define MAP_MAGIC             (0xf173da2ce77ecdb0UL) /* Firedancer rec db version 0 */
      81     4150176 : #define FD_FUNK_REC_MAP_CNT_WIDTH 43
      82     4149774 : #define MAP_CNT_WIDTH         FD_FUNK_REC_MAP_CNT_WIDTH
      83             : #define MAP_IMPL_STYLE        1
      84             : #define MAP_PEDANTIC          1
      85             : #include "../util/tmpl/fd_map_chain_para.c"
      86             : 
      87             : typedef fd_funk_rec_map_query_t fd_funk_rec_query_t;
      88             : 
      89             : /* fd_funk_rec_prepare_t represents a new record that has been
      90             :    prepared but not inserted into the map yet. See documentation for
      91             :    fd_funk_rec_prepare. */
      92             : 
      93             : struct _fd_funk_rec_prepare {
      94             :   fd_funk_rec_t * rec;
      95             :   uint *          rec_head_idx;
      96             :   uint *          rec_tail_idx;
      97             : };
      98             : 
      99             : typedef struct _fd_funk_rec_prepare fd_funk_rec_prepare_t;
     100             : 
     101             : FD_PROTOTYPES_BEGIN
     102             : 
     103             : /* fd_funk_rec_idx_is_null returns 1 if idx is FD_FUNK_REC_IDX_NULL and
     104             :    0 otherwise. */
     105             : 
     106      574833 : FD_FN_CONST static inline int fd_funk_rec_idx_is_null( uint idx ) { return idx==FD_FUNK_REC_IDX_NULL; }
     107             : 
     108             : /* Accessors */
     109             : 
     110             : /* fd_funk_rec_query_try queries the in-preparation transaction pointed to
     111             :    by txn for the record whose key matches the key pointed to by key.
     112             :    If txn is NULL, the query will be done for the funk's last published
     113             :    transaction.  Returns a pointer to current record on success and NULL
     114             :    on failure.  Reasons for failure include txn is neither NULL nor a
     115             :    pointer to a in-preparation transaction, key is NULL or not a record
     116             :    in the given transaction.
     117             : 
     118             :    The returned pointer is in the caller's address space if the
     119             :    return value is non-NULL.
     120             : 
     121             :    Assumes funk is a current local join (NULL returns NULL), txn is NULL
     122             :    or points to an in-preparation transaction in the caller's address
     123             :    space, key points to a record key in the caller's address space (NULL
     124             :    returns NULL), and no concurrent operations on funk, txn or key.
     125             :    funk retains no interest in key.  The funk retains ownership of any
     126             :    returned record.
     127             : 
     128             :    The query argument remembers the query for later validity testing.
     129             : 
     130             :    This is reasonably fast O(1).
     131             : 
     132             :    Important safety tip!  This function can encounter records
     133             :    that have the ERASE flag set (i.e. are tombstones of erased
     134             :    records). fd_funk_rec_query_try will still return the record in this
     135             :    case, and the application should check for the flag. */
     136             : 
     137             : fd_funk_rec_t *
     138             : fd_funk_rec_query_try( fd_funk_t *               funk,
     139             :                        fd_funk_txn_xid_t const * xid,
     140             :                        fd_funk_rec_key_t const * key,
     141             :                        fd_funk_rec_query_t *     query );
     142             : 
     143             : /* fd_funk_rec_query_try_global is the same as fd_funk_rec_query_try but
     144             :    will query txn's ancestors for key from youngest to oldest if key is
     145             :    not part of txn.  As such, the txn of the returned record may not
     146             :    match txn but will be the txn of most recent ancestor with the key
     147             :    otherwise.   If xid_out!=NULLL, *xid_out is set to the XID in which
     148             :    the record was created.
     149             : 
     150             :    This is reasonably fast O(in_prep_ancestor_cnt).
     151             : 
     152             :    Important safety tip!  This function can encounter records
     153             :    that have the ERASE flag set (i.e. are tombstones of erased
     154             :    records). fd_funk_rec_query_try_global will return a NULL in this case
     155             :    but still set *txn_out to the relevant transaction. This behavior
     156             :    differs from fd_funk_rec_query_try. */
     157             : fd_funk_rec_t const *
     158             : fd_funk_rec_query_try_global( fd_funk_t const *         funk,
     159             :                               fd_funk_txn_xid_t const * xid,
     160             :                               fd_funk_rec_key_t const * key,
     161             :                               fd_funk_txn_xid_t *       xid_out,
     162             :                               fd_funk_rec_query_t *     query );
     163             : 
     164             : /* fd_funk_rec_{pair,xid,key} returns a pointer in the local address
     165             :    space of the {(transaction id,record key) pair,transaction id,record
     166             :    key} of a live record.  Assumes rec points to a live record in the
     167             :    caller's address space.  The lifetime of the returned pointer is the
     168             :    same as rec.  The value at the pointer will be constant for its
     169             :    lifetime. */
     170             : 
     171           0 : FD_FN_CONST static inline fd_funk_xid_key_pair_t const * fd_funk_rec_pair( fd_funk_rec_t const * rec ) { return &rec->pair;    }
     172           6 : FD_FN_CONST static inline fd_funk_txn_xid_t const *      fd_funk_rec_xid ( fd_funk_rec_t const * rec ) { return rec->pair.xid; }
     173           0 : FD_FN_CONST static inline fd_funk_rec_key_t const *      fd_funk_rec_key ( fd_funk_rec_t const * rec ) { return rec->pair.key; }
     174             : 
     175             : /* fd_funk_rec_prepare creates an unpublished funk record entry.  This
     176             :    is the first step to adding a funk record to a transaction.  Record
     177             :    entry acquisition may fail if the record object pool is exhausted
     178             :    (FD_FUNK_ERR_REC) or the transaction is not writable
     179             :    (FD_FUNK_ERR_FROZEN).  The returned record entry (located in funk
     180             :    shared memory) is then either be cancelled or published by the
     181             :    caller.  This record is invisible to funk query or record-iteration
     182             :    operations until published.  Concurrent record preparation is fine. */
     183             : 
     184             : fd_funk_rec_t *
     185             : fd_funk_rec_prepare( fd_funk_t *               funk,
     186             :                      fd_funk_txn_xid_t const * xid,
     187             :                      fd_funk_rec_key_t const * key,
     188             :                      fd_funk_rec_prepare_t *   prepare,
     189             :                      int *                     opt_err );
     190             : 
     191             : /* fd_funk_rec_publish makes a prepared record globally visible.  First,
     192             :    registers a record with the txn's record list, then inserts it into
     193             :    the record map.  Concurrent record publishing is fine, even to the
     194             :    same transaction.  Crashes the application with FD_LOG_CRIT if the
     195             :    caller attempts to publish the same (txn,xid) key twice. */
     196             : 
     197             : void
     198             : fd_funk_rec_publish( fd_funk_t *             funk,
     199             :                      fd_funk_rec_prepare_t * prepare );
     200             : 
     201             : /* Misc */
     202             : 
     203             : /* fd_funk_rec_verify verifies the record map.  Returns FD_FUNK_SUCCESS
     204             :    if the record map appears intact and FD_FUNK_ERR_INVAL if not (logs
     205             :    details).  Meant to be called as part of fd_funk_verify.  As such, it
     206             :    assumes funk is non-NULL, fd_funk_{wksp,txn_map,rec_map} have been
     207             :    verified to work and the txn_map has been verified. */
     208             : 
     209             : int
     210             : fd_funk_rec_verify( fd_funk_t * funk );
     211             : 
     212             : FD_PROTOTYPES_END
     213             : 
     214             : #endif /* HEADER_fd_src_funk_fd_funk_rec_h */

Generated by: LCOV version 1.14