LCOV - code coverage report
Current view: top level - flamenco/accdb - fd_accdb_ref.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 19 72 26.4 %
Date: 2025-10-27 04:40:00 Functions: 6 1808 0.3 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_accdb_fd_accdb_ref_h
       2             : #define HEADER_fd_src_flamenco_accdb_fd_accdb_ref_h
       3             : 
       4             : /* fd_accdb_ref.h provides account database handle classes.
       5             : 
       6             :    - accdb_ref is an opaque handle to an account database cache entry.
       7             :    - accdb_ro (extends accdb_ref) represents a read-only handle.
       8             :    - accdb_rw (extends accdb_ro) represents a read-write handle.
       9             : 
      10             :    - accdb_guardr is a read-only account lock guard
      11             :    - accdb_guardw is an exclusive account lock guard
      12             :    - accdb_spec is an account speculative read guard
      13             : 
      14             :    These APIs sit between the database layer (abstracts away backing
      15             :    stores and DB specifics) and the runtime layer (offer no runtime
      16             :    protections). */
      17             : 
      18             : #include "../fd_flamenco_base.h"
      19             : #include "../../funk/fd_funk_rec.h"
      20             : #include "../../funk/fd_funk_val.h"
      21             : 
      22             : /* fd_accdb_ref_t is an opaque account database handle. */
      23             : 
      24             : struct fd_accdb_ref {
      25             :   ulong rec_laddr;
      26             :   ulong meta_laddr;
      27             : };
      28             : typedef struct fd_accdb_ref fd_accdb_ref_t;
      29             : 
      30             : /* fd_accdb_ro_t is a readonly account database handle. */
      31             : 
      32             : union fd_accdb_ro {
      33             :   fd_accdb_ref_t ref[1];
      34             :   struct {
      35             :     fd_funk_rec_t const *     rec;
      36             :     fd_account_meta_t const * meta;
      37             :   };
      38             : };
      39             : typedef union fd_accdb_ro fd_accdb_ro_t;
      40             : 
      41             : FD_PROTOTYPES_BEGIN
      42             : 
      43             : static inline void const *
      44           3 : fd_accdb_ref_data_const( fd_accdb_ro_t const * ro ) {
      45           3 :   return (void *)( ro->meta+1 );
      46           3 : }
      47             : 
      48             : static inline ulong
      49         468 : fd_accdb_ref_data_sz( fd_accdb_ro_t const * ro ) {
      50         468 :   return ro->meta->dlen;
      51         468 : }
      52             : 
      53             : static inline ulong
      54           3 : fd_accdb_ref_lamports( fd_accdb_ro_t const * ro ) {
      55           3 :   return ro->meta->lamports;
      56           3 : }
      57             : 
      58             : static inline void const *
      59           3 : fd_accdb_ref_owner( fd_accdb_ro_t const * ro ) {
      60           3 :   return ro->meta->owner;
      61           3 : }
      62             : 
      63             : static inline uint
      64           3 : fd_accdb_ref_exec_bit( fd_accdb_ro_t const * ro ) {
      65           3 :   return !!ro->meta->executable;
      66           3 : }
      67             : 
      68             : static inline ulong
      69           0 : fd_accdb_ref_slot( fd_accdb_ro_t const * ro ) {
      70           0 :   return ro->meta->slot;
      71           0 : }
      72             : 
      73             : // void
      74             : // fd_accdb_ref_lthash( fd_accdb_ro_t const * ro,
      75             : //                      void *                lthash );
      76             : 
      77             : FD_PROTOTYPES_END
      78             : 
      79             : /* fd_accdb_rw_t is a writable database handle.  Typically, writable
      80             :    handles are only available for invisible/in-prepartion records.
      81             :    In rare cases (e.g. when booting up), components may directly write
      82             :    to globally visible writable records. */
      83             : 
      84             : union fd_accdb_rw {
      85             :   fd_accdb_ref_t ref[1];
      86             :   fd_accdb_ro_t  ro [1];
      87             :   struct {
      88             :     fd_funk_rec_t *     rec;
      89             :     fd_account_meta_t * meta;
      90             :     uint                published : 1;
      91             :   };
      92             : };
      93             : typedef union fd_accdb_rw fd_accdb_rw_t;
      94             : 
      95             : FD_PROTOTYPES_BEGIN
      96             : 
      97             : // void
      98             : // fd_accdb_ref_clear( fd_accdb_rw_t * rw );
      99             : 
     100             : static inline ulong
     101           0 : fd_accdb_ref_data_max( fd_accdb_rw_t * rw ) {
     102           0 :   ulong data_max;
     103           0 :   if( FD_UNLIKELY( __builtin_usubl_overflow( rw->rec->val_max, sizeof(fd_account_meta_t), &data_max ) ) ) {
     104           0 :     FD_LOG_CRIT(( "invalid rec->val_max %lu for account at rec %p", (ulong)rw->rec->val_max, (void *)rw->rec ));
     105           0 :   }
     106           0 :   return data_max;
     107           0 : }
     108             : 
     109             : static inline void *
     110           0 : fd_accdb_ref_data( fd_accdb_rw_t * rw ) {
     111           0 :   return (void *)( rw->meta+1 );
     112           0 : }
     113             : 
     114             : static inline void
     115             : fd_accdb_ref_data_set( fd_accdb_rw_t * rw,
     116             :                        void const *    data,
     117           0 :                        ulong           data_sz ) {
     118           0 :   ulong data_max = fd_accdb_ref_data_max( rw );
     119           0 :   if( FD_UNLIKELY( data_sz>data_max ) ) {
     120           0 :     FD_LOG_CRIT(( "attempted to write %lu bytes into a rec %p with only %lu bytes of data space",
     121           0 :                   data_sz, (void *)rw->rec, data_max ));
     122           0 :   }
     123           0 :   fd_memcpy( fd_accdb_ref_data( rw ), data, data_sz );
     124           0 :   rw->meta->dlen  = (uint)data_sz;
     125           0 :   rw->rec->val_sz = (uint)( sizeof(fd_account_meta_t)+data_sz ) & (FD_FUNK_REC_VAL_MAX-1);
     126           0 : }
     127             : 
     128             : FD_FN_UNUSED static void
     129             : fd_accdb_ref_data_sz_set( fd_accdb_rw_t * rw,
     130           0 :                           ulong           data_sz ) {
     131           0 :   ulong prev_sz = rw->meta->dlen;
     132           0 :   if( data_sz>prev_sz ) {
     133           0 :     /* Increasing size, zero out tail */
     134           0 :     ulong data_max = fd_accdb_ref_data_max( rw );
     135           0 :     if( FD_UNLIKELY( data_sz>data_max ) ) {
     136           0 :       FD_LOG_CRIT(( "attempted to write %lu bytes into a rec %p with only %lu bytes of data space",
     137           0 :                     data_sz, (void *)rw->rec, data_max ));
     138           0 :     }
     139           0 :     void * tail = (uchar *)fd_accdb_ref_data( rw ) + prev_sz;
     140           0 :     fd_memset( tail, 0, data_sz-prev_sz );
     141           0 :   }
     142           0 :   rw->meta->dlen  = (uint)data_sz;
     143           0 :   rw->rec->val_sz = (uint)( sizeof(fd_account_meta_t)+data_sz ) & (FD_FUNK_REC_VAL_MAX-1);
     144           0 : }
     145             : 
     146             : static inline void
     147             : fd_accdb_ref_lamports_set( fd_accdb_rw_t * rw,
     148           0 :                            ulong           lamports ) {
     149           0 :   rw->meta->lamports = lamports;
     150           0 : }
     151             : 
     152             : static inline void
     153             : fd_accdb_ref_owner_set( fd_accdb_rw_t * rw,
     154           0 :                         void const *    owner ) {
     155           0 :   memcpy( rw->meta->owner, owner, 32UL );
     156           0 : }
     157             : 
     158             : static inline void
     159             : fd_accdb_ref_exec_bit_set( fd_accdb_rw_t * rw,
     160           0 :                            uint            exec_bit ) {
     161           0 :   rw->meta->executable = !!exec_bit;
     162           0 : }
     163             : 
     164             : static inline void
     165             : fd_accdb_ref_slot_set( fd_accdb_rw_t * rw,
     166           0 :                        ulong           slot ) {
     167           0 :   rw->meta->slot = slot;
     168           0 : }
     169             : 
     170             : FD_PROTOTYPES_END
     171             : 
     172             : /* fd_accdb_guardr_t tracks a rwlock being held as read-only.
     173             :    Destroying this guard object detaches the caller's thread from the
     174             :    rwlock. */
     175             : 
     176             : struct fd_accbd_guardr {
     177             :   fd_rwlock_t * rwlock;
     178             : };
     179             : 
     180             : typedef struct fd_accdb_guardr fd_accdb_guardr_t;
     181             : 
     182             : /* fd_accdb_guardw_t tracks an rwlock being held exclusively.
     183             :    Destroying this guard object detaches the caller's thread from the
     184             :    lock. */
     185             : 
     186             : struct fd_accdb_guardw {
     187             :   fd_rwlock_t * rwlock;
     188             : };
     189             : 
     190             : typedef struct fd_accdb_guardw fd_accdb_guardw_t;
     191             : 
     192             : /* fd_accdb_spec_t tracks a speculative access to a shared resource.
     193             :    Destroying this guard object marks the end of a speculative access. */
     194             : 
     195             : struct fd_accdb_spec {
     196             :   fd_funk_rec_key_t * keyp;       /* shared key */
     197             :   fd_funk_rec_key_t   key;        /* expected key */
     198             : };
     199             : 
     200             : typedef struct fd_accdb_spec fd_accdb_spec_t;
     201             : 
     202             : /* fd_accdb_spec_test returns 1 if the shared resources has not been
     203             :    invalidated up until now.  Returns 0 if the speculative access may
     204             :    have possibly seen a conflict (e.g. a torn read, a use-after-free,
     205             :    etc). */
     206             : 
     207             : static inline int
     208           3 : fd_accdb_spec_test( fd_accdb_spec_t const * spec ) {
     209           3 :   fd_funk_rec_key_t key_found = FD_VOLATILE_CONST( *spec->keyp );
     210           3 :   return !!fd_funk_rec_key_eq( &key_found, &spec->key );
     211           3 : }
     212             : 
     213             : /* fd_accdb_spec_drop marks the end of a speculative access. */
     214             : 
     215             : static inline void
     216           0 : fd_accdb_spec_drop( fd_accdb_spec_t * spec ) {
     217             :   /* Speculative accesses do not need central synchronization, so no
     218             :      need to inform the holder of the resource of this drop. */
     219           0 :   (void)spec;
     220           0 : }
     221             : 
     222             : #endif /* HEADER_fd_src_flamenco_accdb_fd_accdb_ref_h */

Generated by: LCOV version 1.14