LCOV - code coverage report
Current view: top level - discof/backup - fd_txncache_writer.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 64 67 95.5 %
Date: 2026-08-14 04:54:57 Functions: 4 5 80.0 %

          Line data    Source code
       1             : #include "fd_txncache_writer.h"
       2             : #include "../../flamenco/runtime/fd_txncache_private.h"
       3             : #include "../../util/fd_util.h"
       4             : 
       5             : /* Mirror of blockcache_t and fd_txncache_private from fd_txncache.c.
       6             :    Needed to access the page index array and txnpages. */
       7             : 
       8             : struct fd_txncache_writer_blockcache {
       9             :   fd_txncache_blockcache_shmem_t * shmem;
      10             :   uint *           heads;
      11             :   ushort *         pages;
      12             :   descends_set_t * descends;
      13             : };
      14             : 
      15             : typedef struct fd_txncache_writer_blockcache fd_txncache_writer_blockcache_t;
      16             : 
      17             : struct fd_txncache_writer_tc {
      18             :   fd_txncache_shmem_t *                 shmem;
      19             :   fd_txncache_blockcache_shmem_t *      blockcache_shmem_pool;
      20             :   fd_txncache_writer_blockcache_t *     blockcache_pool;
      21             :   blockhash_map_t *                     blockhash_map;
      22             :   ushort *                              txnpages_free;
      23             :   fd_txncache_txnpage_t *               txnpages;
      24             : };
      25             : 
      26             : typedef struct fd_txncache_writer_tc fd_txncache_writer_tc_t;
      27             : 
      28          12 : #define STATE_HEADER    1
      29          48 : #define STATE_BLOCKHASH 2
      30          36 : #define STATE_TXNS      3
      31          12 : #define STATE_DONE      4
      32           6 : #define STATE_INIT STATE_HEADER
      33             : 
      34             : static int
      35             : txncache_txn_on_snapshot_root( fd_txncache_writer_tc_t const * tc,
      36             :                                ulong                           snapshot_root_idx,
      37          90 :                                fd_txncache_single_txn_t const * txn ) {
      38          90 :   if( FD_UNLIKELY( snapshot_root_idx>=tc->shmem->active_slots_max ) ) return 0;
      39          90 :   if( FD_UNLIKELY( txn->fork_id.val>=tc->shmem->active_slots_max ) ) return 0;
      40             : 
      41          90 :   fd_txncache_blockcache_shmem_t const * txn_fork = &tc->blockcache_shmem_pool[ txn->fork_id.val ];
      42          90 :   if( FD_UNLIKELY( txn_fork->frozen<0 || txn_fork->generation!=txn->generation ) ) return 0;
      43             : 
      44          90 :   return txn->fork_id.val==snapshot_root_idx ||
      45          90 :          descends_set_test( tc->blockcache_pool[ snapshot_root_idx ].descends, txn->fork_id.val );
      46          90 : }
      47             : 
      48             : static ulong
      49             : txncache_count_txns( fd_txncache_writer_tc_t const * tc,
      50             :                      ulong                           snapshot_root_idx,
      51          24 :                      ulong                           bc_idx ) {
      52          24 :   fd_txncache_blockcache_shmem_t const * bc_shmem = &tc->blockcache_shmem_pool[ bc_idx ];
      53          24 :   fd_txncache_writer_blockcache_t const * bc      = &tc->blockcache_pool[ bc_idx ];
      54          24 :   ulong cnt = 0UL;
      55          48 :   for( ushort p=0; p<bc_shmem->pages_cnt; p++ ) {
      56          24 :     fd_txncache_txnpage_t const * page = &tc->txnpages[ bc->pages[ p ] ];
      57          24 :     ulong txns_in_page = FD_TXNCACHE_TXNS_PER_PAGE - (ulong)page->free;
      58          72 :     for( ulong t=0UL; t<txns_in_page; t++ ) {
      59          48 :       fd_txncache_single_txn_t const * txn = page->txns[ t ];
      60          48 :       if( FD_LIKELY( txncache_txn_on_snapshot_root( tc, snapshot_root_idx, txn ) ) ) cnt++;
      61          48 :     }
      62          24 :   }
      63          24 :   return cnt;
      64          24 : }
      65             : 
      66             : fd_txncache_writer_t *
      67             : fd_txncache_writer_init( fd_txncache_writer_t * writer,
      68             :                          fd_txncache_t *        tc,
      69           6 :                          ulong                  slot ) {
      70           6 :   fd_txncache_writer_tc_t const * ltc = (fd_txncache_writer_tc_t const *)tc;
      71           6 :   writer->state      = STATE_INIT;
      72           6 :   writer->tc         = tc;
      73           6 :   writer->slot       = slot;
      74           6 :   writer->snapshot_root_idx = root_slist_is_empty( ltc->shmem->root_ll, ltc->blockcache_shmem_pool ) ?
      75           6 :                               ULONG_MAX :
      76           6 :                               root_slist_idx_peek_tail( ltc->shmem->root_ll, ltc->blockcache_shmem_pool );
      77           6 :   writer->root_iter  = root_slist_iter_init( ltc->shmem->root_ll, ltc->blockcache_shmem_pool );
      78           6 :   writer->page_idx   = 0UL;
      79           6 :   writer->txn_idx    = 0UL;
      80           6 :   writer->txns_in_page = 0UL;
      81           6 :   return writer;
      82           6 : }
      83             : 
      84             : /* Size estimate */
      85             : 
      86             : #define ENCODE_FN     static ulong txncache_estimate( fd_txncache_writer_t * enc )
      87          27 : #define PREP          ulong sz = 0UL;
      88          84 : #define PUSH_VAL(t,n) do { sz += sizeof(t); (void)(n); } while(0)
      89          24 : #define RET_EXPR      sz
      90             : #include "fd_txncache_encoder.c"
      91             : 
      92             : ulong
      93             : fd_txncache_writer_serialized_sz( fd_txncache_t * tc,
      94           3 :                                   ulong           slot ) {
      95           3 :   fd_txncache_writer_t writer[1];
      96           3 :   fd_txncache_writer_init( writer, tc, slot );
      97           3 :   ulong sz = 0UL;
      98          27 :   for(;;) {
      99          27 :     ulong chunk = txncache_estimate( writer );
     100          27 :     if( FD_UNLIKELY( !chunk ) ) break;
     101          24 :     sz += chunk;
     102          24 :   }
     103           3 :   return sz;
     104           3 : }
     105             : 
     106             : /* Actual encoder */
     107             : 
     108             : __attribute__((cold,noreturn,unused))
     109             : static void fail( fd_txncache_writer_t const * enc,
     110             :                   ulong buf_sz,
     111           0 :                   ulong line_nr ) {
     112           0 :   FD_LOG_ERR(( "buffer overflow (state=%u, buf_sz=%lu, line_nr=%lu)", enc->state, buf_sz, line_nr ));
     113           0 : }
     114             : 
     115             : #define ENCODE_FN                                                         \
     116             :   ulong                                                                   \
     117             :   fd_txncache_writer_serialize( fd_txncache_writer_t * enc,               \
     118             :                                 uchar out_buf[ FD_TXNCACHE_WRITER_BUF_MIN ], \
     119             :                                 ulong buf_sz )
     120             : #define PREP                                                              \
     121          27 :   uchar * p  = out_buf;                                                   \
     122          27 :   uchar * p1 __attribute__((unused)) = out_buf+buf_sz;
     123             : #define PUSH_VAL( t, n )                                                  \
     124          84 :   FD_STORE( t, __extension__({                                            \
     125          84 :     if( FD_UNLIKELY( p+sizeof(t) > p1 ) ) fail( enc, buf_sz, __LINE__ ); \
     126          84 :     uchar * ret = p;                                                      \
     127          84 :     p += sizeof(t);                                                       \
     128          84 :     ret;                                                                  \
     129          84 :   }), (n) )
     130          24 : #define RET_EXPR (ulong)( p - out_buf )
     131             : #include "fd_txncache_encoder.c"

Generated by: LCOV version 1.14