LCOV - code coverage report
Current view: top level - flamenco/accdb - fd_accdb_sync.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 31 43 72.1 %
Date: 2026-01-23 05:02:40 Functions: 58 451 12.9 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_accdb_fd_accdb_sync_h
       2             : #define HEADER_fd_src_flamenco_accdb_fd_accdb_sync_h
       3             : 
       4             : /* fd_accdb_sync.h provides synchronous blocking APIs for the account
       5             :    database.  These are slow and should only be used for management ops. */
       6             : 
       7             : #include "fd_accdb_user.h"
       8             : 
       9             : /* In-place read APIs *************************************************/
      10             : 
      11             : static inline void
      12             : fd_accdb_close_ref( fd_accdb_user_t * accdb,
      13       23745 :                     fd_accdb_ref_t *  ref ) {
      14       23745 :   if( FD_UNLIKELY( ref->accdb_type==FD_ACCDB_TYPE_NONE ) ) return;
      15       13950 :   accdb->base.vt->close_ref_multi( accdb, ref, 1UL );
      16       13950 : }
      17             : 
      18             : static inline fd_accdb_ro_t *
      19             : fd_accdb_open_ro( fd_accdb_user_t *         accdb,
      20             :                   fd_accdb_ro_t *           ro,
      21             :                   fd_funk_txn_xid_t const * txn_id,
      22       16770 :                   void const *              address ) {
      23       16770 :   accdb->base.vt->open_ro_multi( accdb, ro, txn_id, address, 1UL );
      24       16770 :   if( fd_accdb_ref_lamports( ro )==0UL ) {
      25       12810 :     fd_accdb_close_ref( accdb, ro->ref );
      26       12810 :     return NULL;
      27       12810 :   }
      28        3960 :   return ro;
      29       16770 : }
      30             : 
      31             : static inline void
      32             : fd_accdb_close_ro( fd_accdb_user_t * accdb,
      33        4017 :                    fd_accdb_ro_t *   ro ) {
      34        4017 :   fd_accdb_close_ref( accdb, ro->ref );
      35        4017 : }
      36             : 
      37             : /* In-place transactional write APIs **********************************/
      38             : 
      39             : FD_PROTOTYPES_BEGIN
      40             : 
      41             : /* fd_accdb_open_rw starts an account modification op.  txn_xid names a
      42             :    non-rooted non-frozen fork graph node, and address identifies the
      43             :    account.  If the account data buffer is smaller than data_max, it is
      44             :    resized (does not affect the data size, just the buffer capacity).
      45             : 
      46             :    If the CREATE flag is set and the account does not exist, returns a
      47             :    newly created account.  If the CREATE flag is not set, returns NULL
      48             :    if the account does not exist.
      49             : 
      50             :    If the TRUNCATE flag is set, the account data size is set to zero.
      51             :    The account data buffer's capacity will still be data_max, but is
      52             :    left uninitialized.  This is useful for callers that intend to
      53             :    replace the entire account.
      54             : 
      55             :    For the entire lifetime of an rw handle, the (txn_xid,address) pair
      56             :    MUST NOT be accessed by any other ro or rw operation.  Violating this
      57             :    rule causes undefined behavior.  The lifetime of an rw handle starts
      58             :    as soon as open_rw is called.  It ends once all memory writes done
      59             :    after the close_rw call returns are visible to all other DB user
      60             :    threads.
      61             : 
      62             :    It is fine to do multiple open_rw/close_rw interactions with the same
      63             :    (txn_xid,address) pair assuming proper synchronization.  Only the
      64             :    final state for a (txn_xid,address) pair is retained. */
      65             : 
      66             : static inline fd_accdb_rw_t *
      67             : fd_accdb_open_rw( fd_accdb_user_t *         accdb,
      68             :                   fd_accdb_rw_t *           rw,
      69             :                   fd_funk_txn_xid_t const * txn_id,
      70             :                   void const *              address,
      71             :                   ulong                     data_max,
      72        6933 :                   int                       flags ) {
      73        6933 :   accdb->base.vt->open_rw_multi( accdb, rw, txn_id, address, &data_max, flags, 1UL );
      74        6933 :   if( rw->ref->accdb_type==FD_ACCDB_TYPE_NONE ) return NULL;
      75        6918 :   return rw;
      76        6933 : }
      77             : 
      78             : /* fd_accdb_close_rw publishes a previously prepared account write.
      79             :    Note that this function returns before memory writes have propagated
      80             :    to other threads, thus requires external synchronization. */
      81             : 
      82             : static inline void
      83             : fd_accdb_close_rw( fd_accdb_user_t * accdb,
      84        6918 :                    fd_accdb_rw_t *   rw ) { /* destroyed */
      85        6918 :   fd_accdb_close_ref( accdb, rw->ref );
      86        6918 : }
      87             : 
      88             : /* fd_accdb_ref_data_max returns the data capacity of an account. */
      89             : 
      90             : static inline ulong
      91             : fd_accdb_ref_data_max( fd_accdb_user_t * accdb,
      92           0 :                        fd_accdb_rw_t *   rw ) {
      93           0 :   return accdb->base.vt->rw_data_max( accdb, rw );
      94           0 : }
      95             : 
      96             : /* fd_accdb_ref_data_sz_set expands/truncates the data size of an
      97             :    account.  Assumes that the account has sufficient capacity
      98             :    (fd_accdb_ref_data_max).  If an increase of the account size was
      99             :    requested, zero-initializes the tail region, unless FLAG_DONTZERO is
     100             :    set. */
     101             : 
     102             : static inline void
     103             : fd_accdb_ref_data_sz_set( fd_accdb_user_t * accdb,
     104             :                           fd_accdb_rw_t *   rw,
     105             :                           ulong             data_sz,
     106         744 :                           int               flags ) {
     107         744 :   accdb->base.vt->rw_data_sz_set( accdb, rw, data_sz, flags );
     108         744 : }
     109             : 
     110             : /* fd_accdb_ref_data_set replaces the data content of an account.
     111             :    Assumes that the account has sufficient capacity
     112             :    (fd_accdb_ref_data_max). */
     113             : 
     114             : FD_FN_UNUSED static void
     115             : fd_accdb_ref_data_set( fd_accdb_user_t * accdb,
     116             :                        fd_accdb_rw_t *   rw,
     117             :                        void const *      data,
     118         744 :                        ulong             data_sz ) {
     119         744 :   fd_accdb_ref_data_sz_set( accdb, rw, data_sz, FD_ACCDB_FLAG_DONTZERO );
     120         744 :   fd_memcpy( fd_accdb_ref_data( rw ), data, data_sz );
     121         744 :   rw->meta->dlen = (uint)data_sz;
     122         744 : }
     123             : 
     124             : FD_PROTOTYPES_END
     125             : 
     126             : /* Batch APIs **********************************************************
     127             : 
     128             :    These amortize I/O wait time if paired with an asynchronous database
     129             :    I/O engine (e.g. vinyl_io_ur).  Mostly useful for reads of accounts
     130             :    that are not in memory cache. */
     131             : 
     132             : FD_PROTOTYPES_BEGIN
     133             : 
     134             : static inline ulong
     135           0 : fd_accdb_batch_max( fd_accdb_user_t * accdb ) {
     136           0 :   return accdb->base.vt->batch_max( accdb );
     137           0 : }
     138             : 
     139             : /* fd_accdb_open_ro_multi opens a batch of accounts for read.  ro[i]
     140             :    is initialized with an account handle.  xid is the fork ID.
     141             :    address[i] gives the account address to query (conflicts are fine).
     142             :    cnt is the number of accounts to query.
     143             : 
     144             :    If account i does not exist, ro[i] gives an account with zero
     145             :    lamports and no data.  Note that account refs over non-existent
     146             :    accounts must still be closed (fd_accdb_close_ref_multi).
     147             : 
     148             :    On return, the caller owns cnt accdb_ro database handles. */
     149             : 
     150             : static inline void
     151             : fd_accdb_open_ro_multi( fd_accdb_user_t *         accdb,
     152             :                         fd_accdb_ro_t *           ro,
     153             :                         fd_funk_txn_xid_t const * xid,
     154             :                         void const *              address,
     155           0 :                         ulong                     cnt ) {
     156           0 :   accdb->base.vt->open_ro_multi( accdb, ro, xid, address, cnt );
     157           0 : }
     158             : 
     159             : /* fd_accdb_open_rw_multi opens a batch of accounts for read-write.
     160             :    rw[i] is either initialized with an account handle or marked as
     161             :    invalid (see below).  xid is the fork ID.  address[i] gives the
     162             :    account address to query (conflicts are forbidden).  data_min[i]
     163             :    specifies the requested minimum account data byte capacity (grows
     164             :    account buffers if necessary).  cnt is the number of accounts to
     165             :    query.
     166             : 
     167             :    Supported flags:
     168             : 
     169             :      CREATE: if set, and account i does not exist, rw[i] gives a valid
     170             :              handle with zero lamports and zero data length (but with
     171             :              requested buffer capacity).
     172             :              if not set, and account i does not exist, then sets
     173             :              rw[i]->ref->accdb_type=INVAL.
     174             : 
     175             :      TRUNCATE: reset the account's data length to zero (useful as a
     176             :                hit to the database engine to avoid copies)
     177             : 
     178             :      DONTZERO: do not zero unused account data buffer space (useful
     179             :                as a performance hint when the caller plans to
     180             :                overwrite all data bytes anyway)
     181             : 
     182             :    On return, the caller owns cnt accdb_rw database handles (some of
     183             :    which may be invalid). */
     184             : 
     185             : static inline void
     186             : fd_accdb_close_ro_multi( fd_accdb_user_t * accdb,
     187             :                          fd_accdb_ro_t *   ro,
     188           0 :                          ulong             cnt ) {
     189           0 :   accdb->base.vt->close_ref_multi( accdb, fd_type_pun( ro ), cnt );
     190           0 : }
     191             : 
     192             : FD_PROTOTYPES_END
     193             : 
     194             : #endif /* HEADER_fd_src_flamenco_accdb_fd_accdb_sync_h */

Generated by: LCOV version 1.14