LCOV - code coverage report
Current view: top level - discof/repair - fd_inflight.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 95 129 73.6 %
Date: 2026-09-17 04:28:31 Functions: 10 11 90.9 %

          Line data    Source code
       1             : #include "fd_inflight.h"
       2             : 
       3             : void *
       4             : fd_inflights_new( void * shmem,
       5          48 :                   ulong  seed ) {
       6          48 :   if( FD_UNLIKELY( !shmem ) ) {
       7           0 :     FD_LOG_WARNING(( "NULL mem" ));
       8           0 :     return NULL;
       9           0 :   }
      10             : 
      11          48 :   ulong footprint = fd_inflights_footprint();
      12          48 :   ulong chain_cnt = fd_inflight_map_chain_cnt_est( FD_INFLIGHT_REQ_MAX );
      13             : 
      14          48 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
      15          48 :   fd_inflights_t * table = FD_SCRATCH_ALLOC_APPEND( l, fd_inflights_align(),     sizeof(fd_inflights_t) );
      16          48 :   void *           pool  = FD_SCRATCH_ALLOC_APPEND( l, fd_inflight_pool_align(), fd_inflight_pool_footprint( FD_INFLIGHT_REQ_MAX ) );
      17          48 :   void *           map   = FD_SCRATCH_ALLOC_APPEND( l, fd_inflight_map_align(),  fd_inflight_map_footprint ( chain_cnt           ) );
      18          48 :   void *           pmap  = FD_SCRATCH_ALLOC_APPEND( l, fd_inflight_map_align(),  fd_inflight_map_footprint ( chain_cnt           ) );
      19          48 :   FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_inflights_align() ) == (ulong)shmem + footprint );
      20             : 
      21          48 :   table->pool       = fd_inflight_pool_join( fd_inflight_pool_new( pool, FD_INFLIGHT_REQ_MAX ) );
      22          48 :   table->map        = fd_inflight_map_join ( fd_inflight_map_new ( map,  chain_cnt, seed    ) );
      23          48 :   table->popped_map = fd_inflight_map_join ( fd_inflight_map_new ( pmap, chain_cnt, seed    ) );
      24          48 :   table->popped_cnt = 0UL;
      25          48 :   FD_TEST( table->outstanding_dl==fd_inflight_dlist_join( fd_inflight_dlist_new( table->outstanding_dl ) ) );
      26          48 :   FD_TEST( table->popped_dl     ==fd_inflight_dlist_join( fd_inflight_dlist_new( table->popped_dl      ) ) );
      27             : 
      28          48 :   FD_TEST( table->pool       );
      29          48 :   FD_TEST( table->map        );
      30          48 :   FD_TEST( table->popped_map );
      31          48 :   return shmem;
      32          48 : }
      33             : 
      34             : fd_inflights_t *
      35          48 : fd_inflights_join( void * shmem ) {
      36          48 :   fd_inflights_t * table = (fd_inflights_t *)shmem;
      37             : 
      38          48 :   if( FD_UNLIKELY( !table ) ) {
      39           0 :     FD_LOG_WARNING(( "NULL inflight table" ));
      40           0 :     return NULL;
      41           0 :   }
      42             : 
      43          48 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)table, fd_inflights_align() ) ) ) {
      44           0 :     FD_LOG_WARNING(( "misaligned inflight table" ));
      45           0 :     return NULL;
      46           0 :   }
      47             : 
      48          48 :   return table;
      49          48 : }
      50             : 
      51             : /* inflight_acquire returns a FREE record, evicting the oldest POPPED
      52             :    record if none is free, and the oldest OUTSTANDING one as a last
      53             :    resort.  The caller fills the key and payload, then commits it to
      54             :    the OUTSTANDING set with inflight_commit. */
      55             : 
      56             : static fd_inflight_t *
      57        2121 : inflight_acquire( fd_inflights_t * table ) {
      58        2121 :   if( FD_UNLIKELY( !fd_inflight_pool_free( table->pool ) ) ) {
      59           0 :     if( FD_LIKELY( !fd_inflight_dlist_is_empty( table->popped_dl, table->pool ) ) ) {
      60           0 :       fd_inflight_t * evict = fd_inflight_dlist_ele_pop_head( table->popped_dl, table->pool );
      61           0 :       table->popped_cnt--;
      62           0 :       fd_inflight_map_ele_remove_fast( table->popped_map, evict, table->pool );
      63           0 :       fd_inflight_pool_ele_release   ( table->pool,       evict );
      64           0 :     } else {
      65             :       /* (pool free cnt) + (popped_dl cnt) + (outstanding_dl cnt) ==
      66             :          FD_INFLIGHT_REQ_MAX, so they can't all be 0.  Should be
      67             :          impossible in practice: callers gate new requests on
      68             :          fd_inflights_outstanding_free. */
      69           0 :       fd_inflight_t * evict = fd_inflight_dlist_ele_pop_head( table->outstanding_dl, table->pool );
      70           0 :       FD_LOG_WARNING(( "evicting outstanding request kind %u slot %lu idx %u nonce %u", evict->key.kind, evict->key.slot, evict->key.idx, evict->key.nonce ));
      71           0 :       fd_inflight_map_ele_remove_fast( table->map,  evict, table->pool );
      72           0 :       fd_inflight_pool_ele_release   ( table->pool, evict );
      73           0 :     }
      74           0 :   }
      75        2121 :   return fd_inflight_pool_ele_acquire( table->pool );
      76        2121 : }
      77             : 
      78             : static void
      79             : inflight_commit( fd_inflights_t * table,
      80             :                  fd_inflight_t *  req,
      81        2121 :                  long             now ) {
      82        2121 :   req->timestamp_ns = now;
      83        2121 :   fd_inflight_map_ele_insert     ( table->map,            req, table->pool );
      84        2121 :   fd_inflight_dlist_ele_push_tail( table->outstanding_dl, req, table->pool );
      85        2121 : }
      86             : 
      87             : /* inflight_match removes every record with key from the outstanding
      88             :    then the popped set, copying the oldest to *out.  Returns the number
      89             :    of records removed. */
      90             : 
      91             : static ulong
      92             : inflight_match( fd_inflights_t *          table,
      93             :                 fd_inflight_key_t const * key,
      94        1908 :                 fd_inflight_t *           out ) {
      95        1908 :   ulong cnt    = 0UL;
      96        1908 :   long  oldest = LONG_MAX;
      97        5724 :   for( int popped=0; popped<2; popped++ ) {
      98        3816 :     fd_inflight_map_t   * map   = popped ? table->popped_map : table->map;
      99        3816 :     fd_inflight_dlist_t * dlist = popped ? table->popped_dl  : table->outstanding_dl;
     100        5700 :     for(;;) {
     101        5700 :       fd_inflight_t * req = fd_inflight_map_ele_remove( map, key, NULL, table->pool );
     102        5700 :       if( FD_LIKELY( !req ) ) break;
     103        1884 :       if( FD_LIKELY( req->timestamp_ns<oldest ) ) { oldest = req->timestamp_ns; *out = *req; }
     104        1884 :       fd_inflight_dlist_ele_remove( dlist,       req, table->pool );
     105        1884 :       fd_inflight_pool_ele_release( table->pool, req              );
     106        1884 :       table->popped_cnt -= (ulong)popped;
     107        1884 :       cnt++;
     108        1884 :     }
     109        3816 :   }
     110        1908 :   return cnt;
     111        1908 : }
     112             : 
     113             : void
     114             : fd_inflights_shred_insert( fd_inflights_t *    table,
     115             :                            ulong               nonce,
     116             :                            fd_pubkey_t const * pubkey,
     117             :                            ulong               slot,
     118             :                            ulong               shred_idx,
     119             :                            fd_hash_t const *   block_id,
     120             :                            fd_hash_t const *   fec_root,
     121        1941 :                            long                now ) {
     122        1941 :   fd_inflight_t * req = inflight_acquire( table );
     123        1941 :   fd_inflight_key_init( &req->key, FD_REPAIR_KIND_SHRED, slot, shred_idx, nonce, fec_root );
     124        1941 :   req->pubkey = *pubkey;
     125        1941 :   if( FD_LIKELY( block_id ) ) req->block_id = *block_id;
     126           9 :   else                        fd_memset( &req->block_id, 0, sizeof(fd_hash_t) );
     127        1941 :   inflight_commit( table, req, now );
     128        1941 : }
     129             : 
     130             : long
     131             : fd_inflights_shred_match( fd_inflights_t *  table,
     132             :                           ulong             nonce,
     133             :                           ulong             slot,
     134             :                           ulong             shred_idx,
     135             :                           fd_hash_t const * fec_root,
     136             :                           fd_pubkey_t *     peer_out,
     137             :                           fd_hash_t *       block_id_out,
     138        1752 :                           long              now ) {
     139        1752 :   fd_inflight_key_t key[1];
     140        1752 :   fd_inflight_key_init( key, FD_REPAIR_KIND_SHRED, slot, shred_idx, nonce, fec_root );
     141        1752 :   fd_inflight_t req[1];
     142        1752 :   if( FD_UNLIKELY( !inflight_match( table, key, req ) ) ) return 0L;
     143        1734 :   *peer_out = req->pubkey;
     144        1734 :   if( FD_LIKELY( block_id_out ) ) *block_id_out = req->block_id;
     145        1734 :   return fd_long_max( now-req->timestamp_ns, 1L ); /* >0 marks a match even if now has not advanced */
     146        1752 : }
     147             : 
     148             : void
     149             : fd_inflights_meta_insert( fd_inflights_t *    table,
     150             :                           ulong               nonce,
     151             :                           uint                kind,
     152             :                           fd_pubkey_t const * pubkey,
     153             :                           ulong               slot,
     154             :                           fd_hash_t const *   block_id,
     155             :                           uint                fec_set_idx,
     156         180 :                           long                now ) {
     157         180 :   fd_inflight_t * req = inflight_acquire( table );
     158         180 :   fd_inflight_key_init( &req->key, kind, slot, fec_set_idx, nonce, NULL );
     159         180 :   req->pubkey   = *pubkey;
     160         180 :   req->block_id = *block_id;
     161         180 :   inflight_commit( table, req, now );
     162         180 : }
     163             : 
     164             : int
     165             : fd_inflights_meta_match( fd_inflights_t * table,
     166             :                          ulong            nonce,
     167         156 :                          fd_inflight_t *  out ) {
     168         156 :   fd_inflight_key_t key[1];
     169         156 :   fd_inflight_key_init( key, AG_REPAIR_KIND_PARENT_FEC_COUNT, 0UL, 0UL, nonce, NULL ); /* only the nonce is key material for metadata kinds */
     170         156 :   return !!inflight_match( table, key, out );
     171         156 : }
     172             : 
     173             : void
     174             : fd_inflights_pop( fd_inflights_t * table,
     175          33 :                   fd_inflight_t *  out ) {
     176          33 :   fd_inflight_t * req = fd_inflight_dlist_ele_pop_head( table->outstanding_dl, table->pool );
     177          33 :   fd_inflight_map_ele_remove_fast( table->map, req, table->pool );
     178          33 :   *out = *req;
     179             : 
     180             :   /* A null record (nonce 0) was never sent, release it rather than
     181             :      parking it in the popped set. */
     182          33 :   if( FD_UNLIKELY( !req->key.nonce ) ) {
     183           3 :     fd_inflight_pool_ele_release( table->pool, req );
     184           3 :     return;
     185           3 :   }
     186             : 
     187          30 :   fd_inflight_map_ele_insert     ( table->popped_map, req, table->pool );
     188          30 :   fd_inflight_dlist_ele_push_tail( table->popped_dl,  req, table->pool );
     189          30 :   table->popped_cnt++;
     190          30 : }
     191             : 
     192             : #include <stdio.h>
     193             : 
     194             : void
     195           0 : fd_inflights_print( fd_inflight_dlist_t * dlist, fd_inflight_t * pool ) {
     196             : 
     197           0 :   printf("%-5s %-15s %-8s %-15s %-44s\n", "Kind", "Slot", "Idx", "Timestamp", "Peer");
     198           0 :   printf("%-5s %-15s %-8s %-15s %-44s\n",
     199           0 :           "-----", "---------------", "--------", "------------",
     200           0 :           "--------------------------------------------");
     201           0 :   for( fd_inflight_dlist_iter_t iter = fd_inflight_dlist_iter_fwd_init( dlist, pool );
     202           0 :        !fd_inflight_dlist_iter_done( iter, dlist, pool );
     203           0 :        iter = fd_inflight_dlist_iter_fwd_next( iter, dlist, pool ) ) {
     204           0 :     fd_inflight_t * req = fd_inflight_dlist_iter_ele( iter, dlist, pool );
     205           0 :     FD_BASE58_ENCODE_32_BYTES( req->pubkey.uc, peer );
     206           0 :     printf("%-5u %-15lu %-8u %-15lu %-44.44s\n", req->key.kind, req->key.slot, req->key.idx, (ulong)req->timestamp_ns / (ulong)1e6, peer );
     207           0 :   }
     208             :   printf("\n");
     209           0 : }

Generated by: LCOV version 1.14