LCOV - code coverage report
Current view: top level - disco/events - fd_event_report.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 3 35 8.6 %
Date: 2026-09-17 04:28:31 Functions: 1 68 1.5 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_events_fd_event_report_h
       2             : #define HEADER_fd_src_disco_events_fd_event_report_h
       3             : 
       4             : /* fd_event_report.h provides a thread-local, fire-and-forget path for a
       5             :    tile to report a telemetry event to the event tile, mirroring how the
       6             :    metrics thread-local (fd_metrics_tl / FD_MCNT_*) works.
       7             : 
       8             :    A tile opts in by setting fd_topo_run_tile_t.max_event_sz; the topology
       9             :    then auto-wires a dedicated unreliable link from the tile to the event
      10             :    tile (see topology construction).  At tile boot, fd_event_register()
      11             :    sets up the thread-local reporter from that link.  Generated code emits
      12             :    one fd_event_report_<name>( msg ) macro per event schema (see
      13             :    generated/fd_event_gen.h) which forwards to fd_event_report_().
      14             : 
      15             :    The link is written directly via fd_mcache_publish (outside fd_stem); it
      16             :    is unreliable, so events are dropped if the event tile falls behind.
      17             :    When a tile has no event link (telemetry off / max_event_sz==0),
      18             :    fd_event_tl is NULL and reporting is a no-op. */
      19             : 
      20             : #include "../topo/fd_topo.h"
      21             : #include "../../tango/mcache/fd_mcache.h"
      22             : #include "../../tango/dcache/fd_dcache.h"
      23             : 
      24             : struct fd_event_reporter {
      25             :   fd_frag_meta_t * mcache;  /* mcache of the event link (joined) */
      26             :   ulong            depth;   /* mcache depth */
      27             :   ulong            seq;     /* next sequence number to publish */
      28             :   ulong *          seq_store; /* mcache header seq */
      29             : 
      30             :   fd_wksp_t *      mem;     /* workspace containing the dcache (chunk base) */
      31             :   ulong            chunk;   /* current write chunk */
      32             :   ulong            chunk0;  /* first chunk */
      33             :   ulong            wmark;   /* wrap watermark */
      34             :   ulong            mtu;     /* link mtu (== max_event_sz) */
      35             : };
      36             : 
      37             : typedef struct fd_event_reporter fd_event_reporter_t;
      38             : 
      39             : /* The thread-local reporter for the currently running tile, or NULL if the
      40             :    tile has no event link. */
      41             : 
      42             : extern FD_TL fd_event_reporter_t * fd_event_tl;
      43             : 
      44             : FD_PROTOTYPES_BEGIN
      45             : 
      46             : /* fd_event_register sets up fd_event_tl for the calling tile.  If the tile
      47             :    has an event link (tile->event_link_id != ULONG_MAX) it joins the link's
      48             :    mcache/dcache; otherwise fd_event_tl is left NULL and reporting is a
      49             :    no-op.  Must be called once, after the tile's tango objects are joined
      50             :    (i.e. after fd_topo_fill_tile), before the run loop. */
      51             : 
      52             : void
      53             : fd_event_register( fd_topo_t const *      topo,
      54             :                    fd_topo_tile_t const * tile );
      55             : 
      56           0 : #define FD_EVENT_SIG( type, sz ) ( ((ulong)(sz)<<8) | ((ulong)(type)&0xFFUL) )
      57           0 : #define FD_EVENT_SIG_TYPE( sig ) ( (ulong)(sig)&0xFFUL )
      58           0 : #define FD_EVENT_SIG_SZ( sig )   ( (ulong)(sig)>>8 )
      59             : 
      60             : struct fd_event_report_iov {
      61             :   void const * base;
      62             :   ulong        sz;
      63             : };
      64             : 
      65             : typedef struct fd_event_report_iov fd_event_report_iov_t;
      66             : 
      67             : /* fd_event_report_ publishes a single event of sz bytes (the serialized
      68             :    fd_event_<name>_t struct) to the event link.  type is the event schema
      69             :    id, carried with the byte size in the frag sig (see FD_EVENT_SIG) so the
      70             :    event tile can dispatch and size-validate; the frag sz field is too
      71             :    narrow for large events and is published as 0.  No-op when
      72             :    fd_event_tl is NULL.  The generated fd_event_report_<name>() helpers call
      73             :    this with the right type and size. */
      74             : 
      75             : static inline void
      76             : fd_event_report_( ulong        type,
      77             :                   void const * event,
      78          66 :                   ulong        sz ) {
      79          66 :   fd_event_reporter_t * r = fd_event_tl;
      80          66 :   if( FD_UNLIKELY( !r ) ) return; /* no event link / telemetry off */
      81             : 
      82           0 :   FD_TEST( type<=0xFFUL );
      83           0 :   FD_TEST( sz<=r->mtu );
      84             : 
      85           0 :   ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
      86             : 
      87           0 :   fd_memcpy( fd_chunk_to_laddr( r->mem, r->chunk ), event, sz );
      88           0 :   fd_mcache_publish( r->mcache, r->depth, r->seq, FD_EVENT_SIG( type, sz ), r->chunk, 0UL, 0UL, 0UL, tspub );
      89           0 :   r->seq   = fd_seq_inc( r->seq, 1UL );
      90           0 :   r->chunk = fd_dcache_compact_next( r->chunk, sz, r->chunk0, r->wmark );
      91           0 :   fd_mcache_seq_update( r->seq_store, r->seq );
      92           0 : }
      93             : 
      94             : static inline void
      95             : fd_event_report_gather_( ulong                         type,
      96             :                          fd_event_report_iov_t const * iov,
      97           0 :                          ulong                         iov_cnt ) {
      98           0 :   fd_event_reporter_t * r = fd_event_tl;
      99           0 :   if( FD_UNLIKELY( !r ) ) return; /* no event link / telemetry off */
     100             : 
     101           0 :   FD_TEST( type<=0xFFUL );
     102           0 :   ulong sz = 0UL;
     103           0 :   for( ulong i=0UL; i<iov_cnt; i++ ) {
     104           0 :     FD_TEST( iov[ i ].sz<=r->mtu-sz );
     105           0 :     sz += iov[ i ].sz;
     106           0 :   }
     107             : 
     108           0 :   ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
     109             : 
     110           0 :   uchar * dst = fd_chunk_to_laddr( r->mem, r->chunk );
     111           0 :   for( ulong i=0UL; i<iov_cnt; i++ ) {
     112           0 :     fd_memcpy( dst, iov[ i ].base, iov[ i ].sz );
     113           0 :     dst += iov[ i ].sz;
     114           0 :   }
     115           0 :   fd_mcache_publish( r->mcache, r->depth, r->seq, FD_EVENT_SIG( type, sz ), r->chunk, 0UL, 0UL, 0UL, tspub );
     116           0 :   r->seq   = fd_seq_inc( r->seq, 1UL );
     117           0 :   r->chunk = fd_dcache_compact_next( r->chunk, sz, r->chunk0, r->wmark );
     118           0 :   fd_mcache_seq_update( r->seq_store, r->seq );
     119           0 : }
     120             : 
     121             : FD_PROTOTYPES_END
     122             : 
     123             : #endif /* HEADER_fd_src_disco_events_fd_event_report_h */

Generated by: LCOV version 1.14