LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_progcache_user.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1 15 6.7 %
Date: 2025-10-27 04:40:00 Functions: 0 448 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_progcache_fd_progcache_user_h
       2             : #define HEADER_fd_src_flamenco_progcache_fd_progcache_user_h
       3             : 
       4             : /* fd_progcache_user.h provides an API for managing a cache of loaded
       5             :    Solana on-chain program.
       6             : 
       7             :    ### Background
       8             : 
       9             :    Solana on-chain programs are rarely updated but frequently executed.
      10             :    Before a program can be executed, it must be loaded and verified,
      11             :    which is costly.
      12             : 
      13             :    ### Fork management
      14             : 
      15             :    The program cache is fork-aware (using funk transactions).  Txn-level
      16             :    operations take an exclusive lock over the cache (record ops are
      17             :    stalled indefinitely until the txn completes).
      18             : 
      19             :    ### Cache entry
      20             : 
      21             :    Each Solana program can have a number of program cache entries
      22             :    (typically only zero or one, in rare cases where the program content
      23             :    differs across forks multiple).
      24             : 
      25             :    A cache entry consists of a funk_rec object (from a preallocated
      26             :    object pool), and a variable-sized fd_progcache_entry struct
      27             :    (from an fd_alloc heap).
      28             : 
      29             :    ### Cache fill policy
      30             : 
      31             :    fd_progcache is lazily filled on reads, and eagerly invalidated
      32             :    if underlying programs are written to.
      33             : 
      34             :    ### Cache evict policy
      35             : 
      36             :    Cache eviction (i.e. force removal of potentially useful records)
      37             :    happens on fill.  Specifically, cache eviction is triggered when a
      38             :    cache fill fails to allocate from the wksp (fd_alloc) heap.
      39             : 
      40             :    fd_progcache further has a concept of "generations" (gen).  Each
      41             :    cache fill operation specifies a 'gen' number.  Only entries with a
      42             :    lower 'gen' number may get evicted.
      43             : 
      44             :    ### Garbage collect policy
      45             : 
      46             :    fd_progcache cleans up unused entries eagerly when:
      47             : 
      48             :    1. a database fork is cancelled (e.g. slot is rooted and competing
      49             :       history dies, or consensus layer prunes a fork)
      50             :    2. a cache entry is orphaned (updated or invalidated by an epoch
      51             :       boundary) */
      52             : 
      53             : #include "fd_progcache_rec.h"
      54             : #include "fd_prog_load.h"
      55             : #include "../../funk/fd_funk.h"
      56             : #include "../runtime/fd_runtime_const.h"
      57             : 
      58         240 : #define FD_PROGCACHE_DEPTH_MAX (128UL)
      59             : 
      60             : struct fd_progcache_metrics {
      61             :   ulong fork_switch_cnt;
      62             :   ulong miss_cnt;
      63             :   ulong hit_cnt;
      64             :   ulong hit_tot_sz;
      65             :   ulong fill_cnt;
      66             :   ulong fill_tot_sz;
      67             :   ulong fill_fail_cnt;
      68             :   ulong dup_insert_cnt;
      69             :   ulong invalidate_cnt;
      70             : };
      71             : 
      72             : typedef struct fd_progcache_metrics fd_progcache_metrics_t;
      73             : 
      74             : /* fd_progcache_t is a thread-local client to a program cache funk
      75             :    instance.  This struct is quite large and therefore not local/stack
      76             :    declaration-friendly. */
      77             : 
      78             : struct fd_progcache {
      79             :   fd_funk_t funk[1];
      80             : 
      81             :   /* Current fork cache */
      82             :   fd_funk_txn_xid_t fork[ FD_PROGCACHE_DEPTH_MAX ];
      83             :   ulong             fork_depth;
      84             : 
      85             :   fd_progcache_metrics_t * metrics;
      86             : 
      87             :   uchar * scratch;
      88             :   ulong   scratch_sz;
      89             : };
      90             : 
      91             : typedef struct fd_progcache fd_progcache_t;
      92             : 
      93             : FD_PROTOTYPES_BEGIN
      94             : 
      95             : extern FD_TL fd_progcache_metrics_t fd_progcache_metrics_default;
      96             : 
      97             : /* Constructor */
      98             : 
      99             : static inline ulong
     100           0 : fd_progcache_align( void ) {
     101           0 :   return alignof(fd_progcache_t);
     102           0 : }
     103             : 
     104             : static inline ulong
     105           0 : fd_progcache_footprint( void ) {
     106           0 :   return sizeof(fd_progcache_t);
     107           0 : }
     108             : 
     109             : static inline fd_progcache_t *
     110           0 : fd_progcache_new( void * ljoin ) {
     111           0 :   return ljoin;
     112           0 : }
     113             : 
     114             : static inline void *
     115           0 : fd_progcache_delete( void * ljoin ) {
     116           0 :   return ljoin;
     117           0 : }
     118             : 
     119             : /* fd_progcache_join joins the caller to a program cache funk instance.
     120             :    scratch points to a FD_PROGCACHE_SCRATCH_ALIGN aligned scratch buffer
     121             :    and scratch_sz is the size of the largest program/ELF binary that is
     122             :    going to be loaded (typically max account data sz). */
     123             : 
     124             : fd_progcache_t *
     125             : fd_progcache_join( fd_progcache_t * ljoin,
     126             :                    void *           shfunk,
     127             :                    uchar *          scratch,
     128             :                    ulong            scratch_sz );
     129             : 
     130           0 : #define FD_PROGCACHE_SCRATCH_ALIGN     (64UL)
     131           0 : #define FD_PROGCACHE_SCRATCH_FOOTPRINT FD_RUNTIME_ACC_SZ_MAX
     132             : 
     133             : /* fd_progcache_leave detaches the caller from a program cache. */
     134             : 
     135             : void *
     136             : fd_progcache_leave( fd_progcache_t * cache,
     137             :                     void **          opt_shfunk );
     138             : 
     139             : /* Record-level operations ********************************************/
     140             : 
     141             : /* fd_progcache_peek queries the program cache for an existing cache
     142             :    entry.  Does not fill the cache.  Returns a pointer to the entry on
     143             :    cache hit (invalidated by the next non-const API call).  Returns NULL
     144             :    on cache miss. */
     145             : 
     146             : fd_progcache_rec_t const *
     147             : fd_progcache_peek( fd_progcache_t *          cache,
     148             :                    fd_funk_txn_xid_t const * xid,
     149             :                    void const *              prog_addr,
     150             :                    ulong                     epoch_slot0 );
     151             : 
     152             : /* fd_progcache_pull loads a program from cache, filling the cache if
     153             :    necessary.  The load operation can have a number of outcomes:
     154             :    - Returns a pointer to an existing cache entry (cache hit, state
     155             :      either "Loaded" or "FailedVerification")
     156             :    - Returns a pointer to a newly created cache entry (cache fill,
     157             :      state either "Loaded" or "FailedVerification")
     158             :    - Returns NULL if the requested program account is not deployed (i.e.
     159             :      account is missing, the program is under visibility delay, or user
     160             :      has not finished uploading the program)
     161             :    In other words, this method guarantees to return a cache entry if a
     162             :    deployed program was found in the account database, and the program
     163             :    either loaded successfully, or failed ELF/bytecode verification.
     164             :    Or it returns  */
     165             : 
     166             : fd_progcache_rec_t const *
     167             : fd_progcache_pull( fd_progcache_t *           cache,
     168             :                    fd_funk_t *                accdb,
     169             :                    fd_funk_txn_xid_t const *  xid,
     170             :                    void const *               prog_addr,
     171             :                    fd_prog_load_env_t const * env );
     172             : 
     173             : /* fd_progcache_invalidate marks the program at the given address as
     174             :    invalidated (typically due to a change of program content).  This
     175             :    creates a non-executable cache entry at the given xid.
     176             : 
     177             :    After a program has been invalidated at xid, it is forbidden to pull
     178             :    the same entry at the same xid.  (Invalidations should happen after
     179             :    replaying transactions). */
     180             : 
     181             : fd_progcache_rec_t const *
     182             : fd_progcache_invalidate( fd_progcache_t *          cache,
     183             :                          fd_funk_txn_xid_t const * xid,
     184             :                          void const *              prog_addr,
     185             :                          ulong                     slot );
     186             : 
     187             : FD_PROTOTYPES_END
     188             : 
     189             : #endif /* HEADER_fd_src_flamenco_fd_progcache_h */

Generated by: LCOV version 1.14