LCOV - code coverage report
Current view: top level - discof/repair - fd_inflight.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 32 0.0 %
Date: 2026-05-17 07:08:10 Functions: 0 16 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_discof_repair_fd_inflight_h
       2             : #define HEADER_fd_src_discof_repair_fd_inflight_h
       3             : 
       4             : #include "fd_policy.h"
       5             : 
       6             : /* fd_inflight tracks repair requests that are inflight to other
       7             :    validators.  This module is useful for metrics and reporting.
       8             :    In-exact updates of orphan requests and highest window requests from
       9             :    this module are non-critical, but exact updates of shred requests are
      10             :    critical. Repair tile relies on this module to be able to re-request
      11             :    any shreds that it has sent, because policy next does not request any
      12             :    shred twice.
      13             : 
      14             :    Requests are key-ed by (slot, shred_idx, nonce) as in the current
      15             :    strategy (see fd_policy.h).  Since we generate the nonce based on the
      16             :    time bucketed by 16ms, which is less than the retransmission timeout,
      17             :    it's highly unlikely that a retransmission request will have the same
      18             :    nonce.  The chances that an inflight request does not get a response
      19             :    are non-negligible due to shred tile upstream deduping duplicates. */
      20             : 
      21             : /* Max number of pending requests */
      22           0 : #define FD_INFLIGHT_REQ_MAX (1<<20)
      23             : 
      24             : struct fd_inflight_key {
      25             :   ulong slot;       /* slot of the request */
      26             :   ulong shred_idx;  /* shred index of the request */
      27             :   ulong nonce;      /* computed nonce */
      28             : };
      29             : typedef struct fd_inflight_key fd_inflight_key_t;
      30             : 
      31             : struct __attribute__((aligned(128UL))) fd_inflight {
      32             :   fd_inflight_key_t key;
      33             :   ulong             next;          /* reserved for internal use by fd_pool and fd_map_chain */
      34             :   ulong             prev;          /* for fd_map_chain */
      35             :   long              timestamp_ns;  /* timestamp when request was created (nanoseconds) */
      36             :   fd_pubkey_t       pubkey;        /* public key of the peer */
      37             : 
      38             : 
      39             :   /* Reserved for DLL eviction */
      40             :   ulong             prevll;      /* pool index of previous element in DLL */
      41             :   ulong             nextll;      /* pool index of next element in DLL */
      42             : };
      43             : typedef struct fd_inflight fd_inflight_t;
      44             : 
      45             : #define POOL_NAME   fd_inflight_pool
      46           0 : #define POOL_T      fd_inflight_t
      47             : #include "../../util/tmpl/fd_pool.c"
      48             : 
      49             : #define MAP_NAME            fd_inflight_map
      50           0 : #define MAP_KEY             key
      51           0 : #define MAP_ELE_T           fd_inflight_t
      52             : #define MAP_KEY_T           fd_inflight_key_t
      53           0 : #define MAP_KEY_EQ(k0, k1)  (((k0)->nonce==(k1)->nonce) & ((k0)->shred_idx==(k1)->shred_idx) & ((k0)->slot==(k1)->slot))
      54           0 : #define MAP_KEY_HASH(k,s)   fd_hash( (s), (k), sizeof(fd_inflight_key_t) )
      55             : #define MAP_MULTI           1 /* It's possible but extremely unlikely that we'll insert duplicates */
      56             : /* Removal via the non-_fast version is kind of strange in the possible
      57             :    presence of duplicate keys. */
      58             : #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
      59             : #include "../../util/tmpl/fd_map_chain.c"
      60             : 
      61             : #define DLIST_NAME      fd_inflight_dlist
      62             : #define DLIST_ELE_T     fd_inflight_t
      63           0 : #define DLIST_PREV      prevll
      64           0 : #define DLIST_NEXT      nextll
      65             : #include "../../util/tmpl/fd_dlist.c"
      66             : 
      67             : struct fd_inflights {
      68             :   /* Each element in the pool is either OUTSTANDING, POPPED (when it
      69             :      times out), or FREE.
      70             : 
      71             :             insert                  pop
      72             :      FREE  --------> OUTSTANDING -----------> POPPED
      73             :       ^                  |                      |
      74             :       |     remove       |  remove, or evicted  |
      75             :       -------------------------------------------
      76             : 
      77             :     All elements begin as FREE.  Elements that are FREE are released in
      78             :     the pool.  Elements that are OUTSTANDING are in map and
      79             :     outstanding_dl.  Elements that are POPPED are in popped_map and
      80             :     popped_dl.  If we need to acquire an element and the pool is empty,
      81             :     the oldest POPPED element will be evicted. */
      82             :   fd_inflight_t       * pool;
      83             :   fd_inflight_map_t   * map;
      84             :   fd_inflight_map_t   * popped_map;
      85             :   fd_inflight_dlist_t   outstanding_dl[1];
      86             :   fd_inflight_dlist_t   popped_dl[1];
      87             :   ulong                 popped_cnt;
      88             : };
      89             : typedef struct fd_inflights fd_inflights_t;
      90             : 
      91             : FD_FN_CONST static inline ulong
      92           0 : fd_inflights_align( void ) { return 128UL; }
      93             : 
      94             : FD_FN_CONST static inline ulong
      95           0 : fd_inflights_footprint( void ) {
      96           0 :   ulong chain_cnt = fd_inflight_map_chain_cnt_est( FD_INFLIGHT_REQ_MAX );
      97           0 :   return FD_LAYOUT_FINI(
      98           0 :     FD_LAYOUT_APPEND(
      99           0 :     FD_LAYOUT_APPEND(
     100           0 :     FD_LAYOUT_APPEND(
     101           0 :     FD_LAYOUT_APPEND(
     102           0 :     FD_LAYOUT_INIT,
     103           0 :       alignof(fd_inflights_t),  sizeof(fd_inflights_t)                            ),
     104           0 :       fd_inflight_pool_align(), fd_inflight_pool_footprint( FD_INFLIGHT_REQ_MAX ) ),
     105           0 :       fd_inflight_map_align(),  fd_inflight_map_footprint ( chain_cnt           ) ),
     106           0 :       fd_inflight_map_align(),  fd_inflight_map_footprint ( chain_cnt           ) ),
     107           0 :     fd_inflights_align() );
     108           0 : }
     109             : 
     110             : void *
     111             : fd_inflights_new( void * shmem,
     112             :                   ulong  seed );
     113             : 
     114             : fd_inflights_t *
     115             : fd_inflights_join( void * shmem );
     116             : 
     117             : void
     118             : fd_inflights_request_insert( fd_inflights_t * table, ulong nonce, fd_pubkey_t const * pubkey, ulong slot, ulong shred_idx );
     119             : 
     120             : long
     121             : fd_inflights_request_remove( fd_inflights_t * table, ulong nonce, ulong slot, ulong shred_idx, fd_pubkey_t * peer_out );
     122             : 
     123             : /* Important! Caller must guarantee that the request list is not empty.
     124             :    This function cannot fail and will always try to populate the output
     125             :    parameters. Typical use should only call this after
     126             :    fd_inflights_should_drain returns true. */
     127             : 
     128             : void
     129             : fd_inflights_request_pop( fd_inflights_t * table, ulong * nonce_out, ulong * slot_out, ulong * shred_idx_out );
     130             : 
     131             : static inline int
     132           0 : fd_inflights_should_drain( fd_inflights_t * table, long now ) {
     133             :   /* peek at head */
     134           0 :   if( FD_UNLIKELY( fd_inflight_dlist_is_empty( table->outstanding_dl, table->pool ) ) ) return 0;
     135             : 
     136           0 :   fd_inflight_t * inflight_req = fd_inflight_dlist_ele_peek_head( table->outstanding_dl, table->pool );
     137           0 :   if( FD_UNLIKELY( inflight_req->timestamp_ns + FD_POLICY_DEDUP_TIMEOUT < now ) ) return 1;
     138           0 :   return 0;
     139           0 : }
     140             : 
     141             : /* Returns the number of new outstanding requests that can be made
     142             :    until the inflight pool is full, and there are no popped
     143             :    requests to evict.  If this is 0, then the next insert would
     144             :    evict an outstanding request. */
     145             : 
     146             : static inline ulong
     147           0 : fd_inflights_outstanding_free( fd_inflights_t * table ) {
     148           0 :   return fd_inflight_pool_free( table->pool ) + table->popped_cnt;
     149           0 : }
     150             : 
     151             : void
     152             : fd_inflights_print( fd_inflight_dlist_t * dlist, fd_inflight_t * pool );
     153             : 
     154             : #endif /* HEADER_fd_src_discof_repair_fd_inflight_h */

Generated by: LCOV version 1.14