LCOV - code coverage report
Current view: top level - waltz/quic/log - fd_quic_log_tx.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 28 28 100.0 %
Date: 2025-01-08 12:08:44 Functions: 4 48 8.3 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_quic_log_fd_quic_log_tx_h
       2             : #define HEADER_fd_src_waltz_quic_log_fd_quic_log_tx_h
       3             : 
       4             : /* fd_quic_log_tx.h provides internal APIs for high performance
       5             :    logging of events.  Programs that wish to read logs should use
       6             :    fd_quic_log_user.h instead.
       7             : 
       8             :    These are designed to handle millions of events per second in a
       9             :    production environment without significantly impacting application
      10             :    performance.  That said, the below inlines still contribute to code
      11             :    bloat so they should be used sparingly in the hot path.
      12             : 
      13             :    Currently uses an unstable custom binary log format, could be made
      14             :    compatible with qlog in the future.
      15             : 
      16             :    ### Architecture
      17             : 
      18             :    fd_quic_log is split into an internal API (initialization, producing
      19             :    logs) and a public API (reading logs).  This allows for changes to
      20             :    log producers without having to recompile consumers.
      21             : 
      22             :    Public APIs (fd_quic_log_user.h):
      23             :    - quic_log_abi: Stable ABI for a quic_log shared memory object
      24             :    - quic_log_rx: Log consumer join to a quic_log (via quic_log_abi)
      25             : 
      26             :    Internal APIs (fd_quic_log_tx.h which is this file):
      27             :    - quic_log_buf: SPMC queue for log messages (implements quic_log_abi)
      28             :    - quic_log_tx: Log producer join to a quic_log_buf */
      29             : 
      30             : #include "fd_quic_log_user.h"
      31             : #include "../../../tango/mcache/fd_mcache.h"
      32             : #include "../../../tango/dcache/fd_dcache.h"
      33             : 
      34             : /* FD_QUIC_LOG_MTU is the max message size of a quic_log_buf.
      35             :    This parameter can be modified without changes to quic_log_abi. */
      36             : 
      37       17325 : #define FD_QUIC_LOG_MTU FD_CHUNK_SZ
      38             : 
      39             : /* A quic_log_buf object is an SPMC queue for log messages suitable for
      40             :    use over shared memory.  fd_quic_log_buf_t is the header of a
      41             :    quic_log_buf object.
      42             : 
      43             :    A quic_log_buf is joined by at most one producer (via quic_log_tx) and
      44             :    an arbitrary number of consumers (via quic_log_rx).  A producer and
      45             :    the consumers do not need to be in the same address space.  Consumers
      46             :    do not need to write to quic_log_buf memory. */
      47             : 
      48             : struct __attribute__((aligned(64))) fd_quic_log_buf {
      49             :   /* Public ABI for consumers */
      50             :   fd_quic_log_abi_t abi;
      51             : 
      52             :   /* Private params follow ... */
      53             :   ulong magic;
      54             :   uint  dcache_off;
      55             :   uint  chunk0;
      56             :   uint  wmark;
      57             : };
      58             : 
      59             : typedef struct fd_quic_log_buf fd_quic_log_buf_t;
      60             : 
      61             : /* FD_QUIC_LOG_BUF_MAGIC is used to signal the layout of shared memory
      62             :    region of a quic_log_buf. */
      63             : 
      64        2130 : #define FD_QUIC_LOG_BUF_MAGIC (0x11df9ddf66ea2912)
      65             : 
      66             : /* FD_QUIC_LOG_BUF_{ALIGN,FOOTPRINT} specify parameters for the memory
      67             :    region backing a quic_log_buf.  U.B. if depth is invalid. */
      68             : 
      69       10935 : #define FD_QUIC_LOG_BUF_ALIGN FD_QUIC_LOG_ALIGN
      70             : #define FD_QUIC_LOG_BUF_FOOTPRINT(depth)                                                                      \
      71             :   FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_INIT,                       \
      72             :     FD_QUIC_LOG_BUF_ALIGN, sizeof(fd_quic_log_buf_t) ),                                                       \
      73             :     FD_MCACHE_ALIGN,       FD_MCACHE_FOOTPRINT( depth, 0 ) ),                                                 \
      74             :     FD_DCACHE_ALIGN,       FD_DCACHE_FOOTPRINT( FD_DCACHE_REQ_DATA_SZ( FD_QUIC_LOG_MTU, depth, 1, 1 ), 0 ) ), \
      75             :     FD_QUIC_LOG_BUF_ALIGN )
      76             : 
      77             : FD_PROTOTYPES_BEGIN
      78             : 
      79             : /* fd_quic_log_buf_align returns FD_QUIC_LOG_BUF_ALIGN. */
      80             : 
      81             : FD_FN_CONST ulong
      82             : fd_quic_log_buf_align( void );
      83             : 
      84             : /* fd_quic_log_buf_footprint returns the required size of a memory region
      85             :    backing a quic_log_buf.  Silently returns 0 if depth is invalid (thus
      86             :    can be used as a quick way to check if depth is valid). */
      87             : 
      88             : FD_FN_CONST ulong
      89             : fd_quic_log_buf_footprint( ulong depth );
      90             : 
      91             : /* fd_quic_log_buf_new formats a memory region as a quic_log_buf.  Returns
      92             :    NULL and logs warning on failure (e.g. invalid depth).  On success,
      93             :    returns shmlog which now ready for producer joins
      94             :    (fd_quic_log_buf_join) and consumer joins (fd_quic_log_rx_join). */
      95             : 
      96             : void *
      97             : fd_quic_log_buf_new( void * shmlog,
      98             :                      ulong  depth );
      99             : 
     100             : /* fd_quic_log_buf_delete releases the memory region backing a
     101             :    quic_log_buf back to the caller.  Assumes that there are no active
     102             :    joins to quic_log_buf. */
     103             : 
     104             : void *
     105             : fd_quic_log_buf_delete( void * shmlog );
     106             : 
     107             : FD_PROTOTYPES_END
     108             : 
     109             : /* fd_quic_log_tx describes a producer-side join to a fd_quic_log_buf. */
     110             : 
     111             : struct fd_quic_log_tx {
     112             :   fd_frag_meta_t * mcache;
     113             :   ulong *          mcache_seq;
     114             :   void *           base;
     115             :   ulong            depth;
     116             :   ulong            seq;
     117             :   uint             chunk;
     118             :   uint             chunk0;
     119             :   uint             wmark;
     120             : };
     121             : 
     122             : typedef struct fd_quic_log_tx fd_quic_log_tx_t;
     123             : 
     124             : FD_PROTOTYPES_BEGIN
     125             : 
     126             : /* fd_quic_log_tx_join joins the caller thread to a quic_log_buf as a
     127             :    producer.  shmlog points to a quic_log_buf object in the local
     128             :    address space.  On success, fills tx with join info and returns tx.
     129             :    On failure, returns NULL.  Reasons for failure include shmlog is a
     130             :    NULL pointer or does obviously not point to a quic_log_buf object.
     131             :    It is U.B. to join multiple producers to the same shmlog. */
     132             : 
     133             : fd_quic_log_tx_t *
     134             : fd_quic_log_tx_join( fd_quic_log_tx_t * tx,
     135             :                      void *             shmlog );
     136             : 
     137             : /* fd_quic_log_tx_leave releases the caller thread from the
     138             :    quic_log_buf.  It is safe to call this function when consumers are
     139             :    still attached. */
     140             : 
     141             : void *
     142             : fd_quic_log_tx_leave( fd_quic_log_tx_t * logger );
     143             : 
     144             : /* fd_quic_log_seq_update updates the seq[0] parameter.
     145             :    (See fd_mcache.h) */
     146             : 
     147             : static inline void
     148    79319448 : fd_quic_log_tx_seq_update( fd_quic_log_tx_t * log ) {
     149    79319448 :   fd_mcache_seq_update( log->mcache_seq, log->seq );
     150    79319448 : }
     151             : 
     152             : /* fd_quic_log_tx_prepare starts a new log message write.  Any other
     153             :    in-flight write by this producer is dropped.  Returns a pointer to
     154             :    the log message buffer (in memory owned by quic_log_buf).  Up to
     155             :    FD_QUIC_LOG_BUF_MTU bytes may be written to this pointer. */
     156             : 
     157             : static inline void *
     158          81 : fd_quic_log_tx_prepare( fd_quic_log_tx_t * log ) {
     159          81 :   return fd_chunk_to_laddr( log->base, log->chunk );
     160          81 : }
     161             : 
     162             : /* fd_quic_log_tx_submit submits an in-flight log message write. */
     163             : 
     164             : static inline void
     165             : fd_quic_log_tx_submit( fd_quic_log_tx_t * tx,
     166             :                        ulong              sz,     /* in [0,FD_QUIC_LOG_BUF_MTU) */
     167             :                        ulong              sig,    /* see fd_quic_log_sig() */
     168          81 :                        long               ts ) {  /* usually fd_tickcount() */
     169          81 :   fd_frag_meta_t * mcache  = tx->mcache;
     170          81 :   ulong            chunk   = tx->chunk;
     171          81 :   ulong            depth   = tx->depth;
     172          81 :   ulong            seq     = tx->seq;
     173          81 :   ulong            ctl     = fd_frag_meta_ctl( 0, 1, 1, 0 );
     174          81 :   uint             ts_comp = (uint)fd_frag_meta_ts_comp( ts );
     175          81 :   ulong            chunk0  = tx->chunk0;
     176          81 :   uint             wmark   = tx->wmark;
     177             : 
     178          81 : #if FD_HAS_SSE
     179          81 : #define fd_quic_log_publish fd_mcache_publish_sse
     180             : #else
     181             : #define fd_quic_log_publish fd_mcache_publish
     182             : #endif
     183          81 :   fd_quic_log_publish( mcache, depth, seq, sig, chunk, sz, ctl, 0, ts_comp );
     184          81 : #undef fd_quic_log_publish
     185             : 
     186          81 :   tx->seq   = fd_seq_inc( seq, 1UL );
     187          81 :   tx->chunk = (uint)fd_dcache_compact_next( chunk, sz, chunk0, wmark );
     188          81 : }
     189             : 
     190             : static inline ulong
     191          81 : fd_quic_log_sig( uint event ) {
     192          81 :   return (ulong)event;
     193          81 : }
     194             : 
     195             : FD_PROTOTYPES_END
     196             : 
     197             : #endif /* HEADER_fd_src_waltz_quic_log_fd_quic_log_tx_h */

Generated by: LCOV version 1.14