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 */