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 : /* fd_event_reporter_join sets up r to publish on topo link link_id,
63 : whose mcache/dcache the calling tile has joined. Returns r. */
64 :
65 : fd_event_reporter_t *
66 : fd_event_reporter_join( fd_event_reporter_t * r,
67 : fd_topo_t const * topo,
68 : ulong link_id );
69 :
70 0 : #define FD_EVENT_SIG( type, sz ) ( ((ulong)(sz)<<8) | ((ulong)(type)&0xFFUL) )
71 0 : #define FD_EVENT_SIG_TYPE( sig ) ( (ulong)(sig)&0xFFUL )
72 0 : #define FD_EVENT_SIG_SZ( sig ) ( (ulong)(sig)>>8 )
73 :
74 : struct fd_event_report_iov {
75 : void const * base;
76 : ulong sz;
77 : };
78 :
79 : typedef struct fd_event_report_iov fd_event_report_iov_t;
80 :
81 : /* fd_event_report_ publishes a single event of sz bytes (the serialized
82 : fd_event_<name>_t struct) to the event link. type is the event schema
83 : id, carried with the byte size in the frag sig (see FD_EVENT_SIG) so the
84 : event tile can dispatch and size-validate; the frag sz field is too
85 : narrow for large events and is published as 0. No-op when
86 : fd_event_tl is NULL. The generated fd_event_report_<name>() helpers call
87 : this with the right type and size. */
88 :
89 : static inline void
90 0 : fd_event_report_ring_( fd_event_reporter_t * r ) {
91 0 : if( FD_LIKELY( !r->sleep ) ) return;
92 0 : __atomic_store_n( &r->sleep->seq_mirror[ r->link_id ], r->seq, __ATOMIC_RELEASE );
93 0 : fd_sleep_wake_check( r->sleep, r->wake, r->wake_cnt );
94 0 : }
95 :
96 : static inline void
97 : fd_event_report_( ulong type,
98 : void const * event,
99 0 : ulong sz ) {
100 0 : fd_event_reporter_t * r = fd_event_tl;
101 0 : if( FD_UNLIKELY( !r ) ) return; /* no event link / telemetry off */
102 :
103 0 : FD_TEST( type<=0xFFUL );
104 0 : FD_TEST( sz<=r->mtu );
105 :
106 0 : ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
107 :
108 0 : fd_memcpy( fd_chunk_to_laddr( r->mem, r->chunk ), event, sz );
109 0 : fd_mcache_publish( r->mcache, r->depth, r->seq, FD_EVENT_SIG( type, sz ), r->chunk, 0UL, 0UL, 0UL, tspub );
110 0 : r->seq = fd_seq_inc( r->seq, 1UL );
111 0 : r->chunk = fd_dcache_compact_next( r->chunk, sz, r->chunk0, r->wmark );
112 0 : fd_mcache_seq_update( r->seq_store, r->seq );
113 0 : fd_event_report_ring_( r );
114 0 : }
115 :
116 : static inline void
117 : fd_event_report_gather_( ulong type,
118 : fd_event_report_iov_t const * iov,
119 0 : ulong iov_cnt ) {
120 0 : fd_event_reporter_t * r = fd_event_tl;
121 0 : if( FD_UNLIKELY( !r ) ) return; /* no event link / telemetry off */
122 :
123 0 : FD_TEST( type<=0xFFUL );
124 0 : ulong sz = 0UL;
125 0 : for( ulong i=0UL; i<iov_cnt; i++ ) {
126 0 : FD_TEST( iov[ i ].sz<=r->mtu-sz );
127 0 : sz += iov[ i ].sz;
128 0 : }
129 :
130 0 : ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
131 :
132 0 : uchar * dst = fd_chunk_to_laddr( r->mem, r->chunk );
133 0 : for( ulong i=0UL; i<iov_cnt; i++ ) {
134 0 : fd_memcpy( dst, iov[ i ].base, iov[ i ].sz );
135 0 : dst += iov[ i ].sz;
136 0 : }
137 0 : fd_mcache_publish( r->mcache, r->depth, r->seq, FD_EVENT_SIG( type, sz ), r->chunk, 0UL, 0UL, 0UL, tspub );
138 0 : r->seq = fd_seq_inc( r->seq, 1UL );
139 0 : r->chunk = fd_dcache_compact_next( r->chunk, sz, r->chunk0, r->wmark );
140 0 : fd_mcache_seq_update( r->seq_store, r->seq );
141 0 : fd_event_report_ring_( r );
142 0 : }
143 :
144 0 : #define FD_EVENT_TYPE_METRICS_TRIGGER (255UL)
145 :
146 : struct fd_event_metrics_trigger {
147 : uint reason;
148 : ulong slot;
149 : ulong snapct_state;
150 : };
151 :
152 : typedef struct fd_event_metrics_trigger fd_event_metrics_trigger_t;
153 :
154 : static inline void
155 : fd_event_metrics_trigger( uint reason,
156 : ulong slot,
157 0 : ulong snapct_state ) {
158 0 : fd_event_metrics_trigger_t t = { .reason = reason, .slot = slot, .snapct_state = snapct_state };
159 0 : fd_event_report_( FD_EVENT_TYPE_METRICS_TRIGGER, &t, sizeof(t) );
160 0 : }
161 :
162 : FD_PROTOTYPES_END
163 :
164 : #endif /* HEADER_fd_src_disco_events_fd_event_report_h */
|