LCOV - code coverage report
Current view: top level - discof/backup - fd_backup_shmem.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 8 64 12.5 %
Date: 2026-08-14 04:54:57 Functions: 1 40 2.5 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_discof_backup_fd_backup_shmem_h
       2             : #define HEADER_fd_src_discof_backup_fd_backup_shmem_h
       3             : 
       4             : /* fd_backup_shmem.h is a shared memory data structure tracking which
       5             :    accounts have been packed into the snapshot.  Each account is tracked by
       6             :    its position in the account index.
       7             :    
       8             :    For each visited account:
       9             :    - mark the account as visited (in snapmk)
      10             :    - copy and compress the account (in snapzp)
      11             :      - if the read failed recover via request from snapzp to snapmk
      12             :   
      13             :    Reads may fail when reading database cache that is concurrently
      14             :    evicted.  Accounts that failed to be read are added to the overrun
      15             :    queue, then retried via a later disk read.
      16             :    
      17             :    Data structures:
      18             :    - bit vector shadowing the account index
      19             :    - MPSC queue tracking overruns */
      20             : 
      21             : #include "../../util/fd_util.h"
      22             : 
      23             : /* Declare a bit vector */
      24             : 
      25             : #define SET_NAME visited_set
      26             : #include "../../util/tmpl/fd_set_dynamic.c"
      27             : 
      28             : static inline int
      29             : fd_backup_visited_test( visited_set_t const * set,
      30           0 :                         ulong                 idx ) {
      31           0 :   FD_DCHECK_CRIT( visited_set_valid_idx( set, idx ), "idx out of bounds" );
      32           0 :   return (int)( ( set[ idx>>6 ] >> (idx & 63UL) ) & 1UL );
      33           0 : }
      34             : 
      35             : static inline void
      36             : fd_backup_visited_insert( visited_set_t * set,
      37           0 :                           ulong           idx ) {
      38           0 :   FD_DCHECK_CRIT( visited_set_valid_idx( set, idx ), "idx out of bounds" );
      39           0 :   set[ idx>>6 ] |= 1UL << (idx & 63UL);
      40           0 : }
      41             : 
      42             : static inline int
      43             : fd_backup_visited_test_and_set( visited_set_t * set,
      44         747 :                                 ulong           idx ) {
      45         747 :   FD_DCHECK_CRIT( visited_set_valid_idx( set, idx ), "idx out of bounds" );
      46         747 :   ulong   mask = 1UL << (idx & 63UL);
      47         747 :   ulong * word = &set[ idx>>6 ];
      48         747 :   ulong   prev = *word;
      49         747 :   *word = prev | mask;
      50         747 :   return !!( prev & mask );
      51         747 : }
      52             : 
      53             : static inline void
      54             : fd_backup_visited_remove( visited_set_t * set,
      55           0 :                           ulong           idx ) {
      56           0 :   FD_DCHECK_CRIT( visited_set_valid_idx( set, idx ), "idx out of bounds" );
      57           0 :   set[ idx>>6 ] &= ~(1UL << (idx & 63UL));
      58           0 : }
      59             : 
      60             : /* Declare an MPSC queue for reporting overruns */
      61             : 
      62           0 : #define FD_BACKUP_OVERRUN_DEPTH (4096U)
      63             : 
      64             : struct __attribute__((aligned(8))) fd_backup_overrun_slot {
      65             :   uint seq;
      66             :   uint acc_idx;
      67             : };
      68             : 
      69             : typedef struct fd_backup_overrun_slot fd_backup_overrun_slot_t;
      70             : 
      71             : struct fd_backup_overrun {
      72             :   uint head __attribute__((aligned(128)));
      73             :   uint tail __attribute__((aligned(128)));
      74             :   fd_backup_overrun_slot_t slot[ FD_BACKUP_OVERRUN_DEPTH ] __attribute__((aligned(128)));
      75             : };
      76             : 
      77             : typedef struct fd_backup_overrun fd_backup_overrun_t;
      78             : 
      79             : FD_PROTOTYPES_BEGIN
      80             : 
      81             : static inline void
      82             : fd_backup_overrun_push( fd_backup_overrun_t * q,
      83           0 :                         uint                  acc_idx ) {
      84           0 :   uint pos = __atomic_fetch_add( &q->head, 1U, __ATOMIC_RELAXED );
      85           0 :   fd_backup_overrun_slot_t * slot = &q->slot[ pos & (FD_BACKUP_OVERRUN_DEPTH-1U) ];
      86           0 :   while( FD_UNLIKELY( __atomic_load_n( &slot->seq, __ATOMIC_ACQUIRE )!=pos-1U ) ) {
      87           0 :     FD_SPIN_PAUSE();
      88           0 :   }
      89           0 :   slot->acc_idx = acc_idx;
      90           0 :   __atomic_store_n( &slot->seq, pos, __ATOMIC_RELEASE );
      91           0 : }
      92             : 
      93             : FD_FN_CONST static inline ulong
      94           0 : fd_backup_align( void ) {
      95           0 :   return fd_ulong_max( alignof(fd_backup_overrun_t), visited_set_align() );
      96           0 : }
      97             : 
      98             : FD_FN_PURE static inline ulong
      99           0 : fd_backup_footprint( ulong max_accounts ) {
     100           0 :   return FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_INIT,
     101           0 :       alignof(fd_backup_overrun_t), sizeof(fd_backup_overrun_t) ),
     102           0 :       visited_set_align(),          visited_set_footprint( max_accounts ) ),
     103           0 :       fd_backup_align() );
     104           0 : }
     105             : 
     106             : static inline void *
     107             : fd_backup_new( void * mem,
     108           0 :                ulong  max_accounts ) {
     109           0 :   if( FD_UNLIKELY( !mem ) ) return NULL;
     110           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_backup_align() ) ) ) return NULL;
     111             : 
     112           0 :   FD_SCRATCH_ALLOC_INIT( l, mem );
     113           0 :   fd_backup_overrun_t * q = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_backup_overrun_t), sizeof(fd_backup_overrun_t) );
     114           0 :   void *          set_mem = FD_SCRATCH_ALLOC_APPEND( l, visited_set_align(),          visited_set_footprint( max_accounts ) );
     115           0 :   FD_CHECK_CRIT( (ulong)q==(ulong)mem, "layout error" );
     116             : 
     117           0 :   q->head = 0UL;
     118           0 :   q->tail = 0UL;
     119           0 :   for( uint i=0U; i<FD_BACKUP_OVERRUN_DEPTH; i++ ) {
     120           0 :     q->slot[ i ].seq     = i-1U;
     121           0 :     q->slot[ i ].acc_idx = UINT_MAX;
     122           0 :   }
     123             : 
     124           0 :   if( FD_UNLIKELY( !visited_set_new( set_mem, max_accounts ) ) ) return NULL;
     125           0 :   return mem;
     126           0 : }
     127             : 
     128             : /* fd_backup_overrun returns a pointer to the overrun queue. */
     129             : 
     130             : FD_FN_CONST static inline fd_backup_overrun_t *
     131           0 : fd_backup_overrun( void * mem ) {
     132           0 :   return (fd_backup_overrun_t *)mem;
     133           0 : }
     134             : 
     135             : /* fd_backup_set returns a join to the visited bit set. */
     136             : 
     137             : static inline visited_set_t *
     138           0 : fd_backup_set( void * mem ) {
     139           0 :   FD_SCRATCH_ALLOC_INIT( l, mem );
     140           0 :   /*             */FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_backup_overrun_t), sizeof(fd_backup_overrun_t) );
     141           0 :   void * set_mem = FD_SCRATCH_ALLOC_APPEND( l, visited_set_align(),          visited_set_footprint( 1UL ) );
     142           0 :   return visited_set_join( set_mem );
     143           0 : }
     144             : 
     145             : FD_PROTOTYPES_END
     146             : 
     147             : #endif /* HEADER_fd_src_discof_backup_fd_backup_shmem_h */

Generated by: LCOV version 1.14