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 "../sleep/fd_sleep.h"
22 : #include "../../tango/mcache/fd_mcache.h"
23 : #include "../../tango/dcache/fd_dcache.h"
24 :
25 : struct fd_event_reporter {
26 : fd_frag_meta_t * mcache; /* mcache of the event link (joined) */
27 : ulong depth; /* mcache depth */
28 : ulong seq; /* next sequence number to publish */
29 : ulong * seq_store; /* mcache header seq */
30 :
31 : fd_wksp_t * mem; /* workspace containing the dcache (chunk base) */
32 : ulong chunk; /* current write chunk */
33 : ulong chunk0; /* first chunk */
34 : ulong wmark; /* wrap watermark */
35 : ulong mtu; /* link mtu (== max_event_sz) */
36 :
37 : fd_sleep_t * sleep;
38 : ulong link_id;
39 : fd_sleep_wake_t wake[ FD_SLEEP_BITS_CNT ];
40 : ulong wake_cnt;
41 : };
42 :
43 : typedef struct fd_event_reporter fd_event_reporter_t;
44 :
45 : /* The thread-local reporter for the currently running tile, or NULL if the
46 : tile has no event link. */
47 :
48 : extern FD_TL fd_event_reporter_t * fd_event_tl;
49 :
50 : FD_PROTOTYPES_BEGIN
51 :
52 : /* fd_event_register sets up fd_event_tl for the calling tile. If the tile
53 : has an event link (tile->event_link_id != ULONG_MAX) it joins the link's
54 : mcache/dcache; otherwise fd_event_tl is left NULL and reporting is a
55 : no-op. Must be called once, after the tile's tango objects are joined
56 : (i.e. after fd_topo_fill_tile), before the run loop. */
57 :
58 : void
59 : fd_event_register( fd_topo_t const * topo,
60 : fd_topo_tile_t const * tile );
61 :
62 0 : #define FD_EVENT_SIG( type, sz ) ( ((ulong)(sz)<<8) | ((ulong)(type)&0xFFUL) )
63 0 : #define FD_EVENT_SIG_TYPE( sig ) ( (ulong)(sig)&0xFFUL )
64 0 : #define FD_EVENT_SIG_SZ( sig ) ( (ulong)(sig)>>8 )
65 :
66 : struct fd_event_report_iov {
67 : void const * base;
68 : ulong sz;
69 : };
70 :
71 : typedef struct fd_event_report_iov fd_event_report_iov_t;
72 :
73 : /* fd_event_report_ publishes a single event of sz bytes (the serialized
74 : fd_event_<name>_t struct) to the event link. type is the event schema
75 : id, carried with the byte size in the frag sig (see FD_EVENT_SIG) so the
76 : event tile can dispatch and size-validate; the frag sz field is too
77 : narrow for large events and is published as 0. No-op when
78 : fd_event_tl is NULL. The generated fd_event_report_<name>() helpers call
79 : this with the right type and size. */
80 :
81 : static inline void
82 0 : fd_event_report_ring_( fd_event_reporter_t * r ) {
83 0 : if( FD_LIKELY( !r->sleep ) ) return;
84 0 : __atomic_store_n( &r->sleep->seq_mirror[ r->link_id ], r->seq, __ATOMIC_RELEASE );
85 0 : fd_sleep_wake_check( r->sleep, r->wake, r->wake_cnt );
86 0 : }
87 :
88 : static inline void
89 : fd_event_report_( ulong type,
90 : void const * event,
91 0 : ulong sz ) {
92 0 : fd_event_reporter_t * r = fd_event_tl;
93 0 : if( FD_UNLIKELY( !r ) ) return; /* no event link / telemetry off */
94 :
95 0 : FD_TEST( type<=0xFFUL );
96 0 : FD_TEST( sz<=r->mtu );
97 :
98 0 : ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
99 :
100 0 : fd_memcpy( fd_chunk_to_laddr( r->mem, r->chunk ), event, sz );
101 0 : fd_mcache_publish( r->mcache, r->depth, r->seq, FD_EVENT_SIG( type, sz ), r->chunk, 0UL, 0UL, 0UL, tspub );
102 0 : r->seq = fd_seq_inc( r->seq, 1UL );
103 0 : r->chunk = fd_dcache_compact_next( r->chunk, sz, r->chunk0, r->wmark );
104 0 : fd_mcache_seq_update( r->seq_store, r->seq );
105 0 : fd_event_report_ring_( r );
106 0 : }
107 :
108 : static inline void
109 : fd_event_report_gather_( ulong type,
110 : fd_event_report_iov_t const * iov,
111 0 : ulong iov_cnt ) {
112 0 : fd_event_reporter_t * r = fd_event_tl;
113 0 : if( FD_UNLIKELY( !r ) ) return; /* no event link / telemetry off */
114 :
115 0 : FD_TEST( type<=0xFFUL );
116 0 : ulong sz = 0UL;
117 0 : for( ulong i=0UL; i<iov_cnt; i++ ) {
118 0 : FD_TEST( iov[ i ].sz<=r->mtu-sz );
119 0 : sz += iov[ i ].sz;
120 0 : }
121 :
122 0 : ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
123 :
124 0 : uchar * dst = fd_chunk_to_laddr( r->mem, r->chunk );
125 0 : for( ulong i=0UL; i<iov_cnt; i++ ) {
126 0 : fd_memcpy( dst, iov[ i ].base, iov[ i ].sz );
127 0 : dst += iov[ i ].sz;
128 0 : }
129 0 : fd_mcache_publish( r->mcache, r->depth, r->seq, FD_EVENT_SIG( type, sz ), r->chunk, 0UL, 0UL, 0UL, tspub );
130 0 : r->seq = fd_seq_inc( r->seq, 1UL );
131 0 : r->chunk = fd_dcache_compact_next( r->chunk, sz, r->chunk0, r->wmark );
132 0 : fd_mcache_seq_update( r->seq_store, r->seq );
133 0 : fd_event_report_ring_( r );
134 0 : }
135 :
136 0 : #define FD_EVENT_TYPE_METRICS_TRIGGER (255UL)
137 :
138 : struct fd_event_metrics_trigger {
139 : uint reason;
140 : ulong slot;
141 : ulong snapct_state;
142 : };
143 :
144 : typedef struct fd_event_metrics_trigger fd_event_metrics_trigger_t;
145 :
146 : static inline void
147 : fd_event_metrics_trigger( uint reason,
148 : ulong slot,
149 0 : ulong snapct_state ) {
150 0 : fd_event_metrics_trigger_t t = { .reason = reason, .slot = slot, .snapct_state = snapct_state };
151 0 : fd_event_report_( FD_EVENT_TYPE_METRICS_TRIGGER, &t, sizeof(t) );
152 0 : }
153 :
154 : FD_PROTOTYPES_END
155 :
156 : #endif /* HEADER_fd_src_disco_events_fd_event_report_h */
|