Line data Source code
1 : #include "fd_gui_peers.h"
2 : #include "fd_gui_printf.h"
3 :
4 : #include "../../ballet/json/cJSON.h"
5 : #include "../../flamenco/gossip/fd_gossip_private.h"
6 : #include "../../flamenco/gossip/fd_gossip_types.h"
7 :
8 : #define LOGGING 0
9 :
10 : FD_FN_CONST ulong
11 0 : fd_gui_peers_align( void ) {
12 0 : ulong a = 128UL;
13 0 : a = fd_ulong_max( a, alignof(fd_gui_peers_ctx_t) );
14 0 : a = fd_ulong_max( a, fd_gui_peers_live_table_align() );
15 0 : a = fd_ulong_max( a, fd_gui_peers_bandwidth_tracking_align() );
16 0 : a = fd_ulong_max( a, fd_gui_peers_node_pubkey_map_align() );
17 0 : a = fd_ulong_max( a, fd_gui_peers_node_sock_map_align() );
18 0 : a = fd_ulong_max( a, alignof(fd_gui_peers_ws_conn_t) );
19 0 : FD_TEST( fd_ulong_pow2_up( a )==a );
20 0 : return a;
21 0 : }
22 :
23 : FD_FN_CONST ulong
24 0 : fd_gui_peers_footprint( ulong max_ws_conn_cnt ) {
25 0 : ulong pubkey_chain_cnt = fd_gui_peers_node_pubkey_map_chain_cnt_est( FD_CONTACT_INFO_TABLE_SIZE );
26 0 : ulong sock_chain_cnt = fd_gui_peers_node_sock_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
27 :
28 0 : ulong l = FD_LAYOUT_INIT;
29 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_gui_peers_ctx_t), sizeof(fd_gui_peers_ctx_t) );
30 0 : l = FD_LAYOUT_APPEND( l, fd_gui_peers_live_table_align(), fd_gui_peers_live_table_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
31 0 : l = FD_LAYOUT_APPEND( l, fd_gui_peers_bandwidth_tracking_align(), fd_gui_peers_bandwidth_tracking_footprint( FD_CONTACT_INFO_TABLE_SIZE ) );
32 0 : l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_pubkey_map_align(), fd_gui_peers_node_pubkey_map_footprint ( pubkey_chain_cnt ) );
33 0 : l = FD_LAYOUT_APPEND( l, fd_gui_peers_node_sock_map_align(), fd_gui_peers_node_sock_map_footprint ( sock_chain_cnt ) );
34 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_gui_peers_ws_conn_t), max_ws_conn_cnt*sizeof(fd_gui_peers_ws_conn_t) );
35 :
36 0 : return FD_LAYOUT_FINI( l, fd_gui_peers_align() );
37 0 : }
38 :
39 : void *
40 : fd_gui_peers_new( void * shmem,
41 : fd_http_server_t * http,
42 : fd_topo_t * topo,
43 : ulong max_ws_conn_cnt,
44 0 : long now ) {
45 0 : if( FD_UNLIKELY( !shmem ) ) {
46 0 : FD_LOG_WARNING(( "NULL shmem" ));
47 0 : return NULL;
48 0 : }
49 :
50 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_gui_peers_align() ) ) ) {
51 0 : FD_LOG_WARNING(( "misaligned shmem" ));
52 0 : return NULL;
53 0 : }
54 :
55 0 : ulong pubkey_chain_cnt = fd_gui_peers_node_pubkey_map_chain_cnt_est( FD_CONTACT_INFO_TABLE_SIZE );
56 0 : ulong sock_chain_cnt = fd_gui_peers_node_sock_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE );
57 :
58 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
59 0 : fd_gui_peers_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_gui_peers_ctx_t), sizeof(fd_gui_peers_ctx_t) );
60 0 : void * _live_table = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_live_table_align(), fd_gui_peers_live_table_footprint ( FD_CONTACT_INFO_TABLE_SIZE ) );
61 0 : void * _bw_tracking = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_bandwidth_tracking_align(), fd_gui_peers_bandwidth_tracking_footprint( FD_CONTACT_INFO_TABLE_SIZE ) );
62 0 : void * _pubkey_map = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_pubkey_map_align(), fd_gui_peers_node_pubkey_map_footprint ( pubkey_chain_cnt ) );
63 0 : void * _sock_map = FD_SCRATCH_ALLOC_APPEND( l, fd_gui_peers_node_sock_map_align(), fd_gui_peers_node_sock_map_footprint ( sock_chain_cnt ) );
64 0 : ctx->client_viewports = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_gui_peers_ws_conn_t), max_ws_conn_cnt*sizeof(fd_gui_peers_ws_conn_t) );
65 :
66 0 : for( ulong i = 0UL; i<max_ws_conn_cnt; i++ ) ctx->client_viewports[ i ].connected = 0;
67 :
68 0 : ctx->http = http;
69 0 : ctx->topo = topo;
70 :
71 0 : ctx->max_ws_conn_cnt = max_ws_conn_cnt;
72 0 : ctx->open_ws_conn_cnt = 0UL;
73 0 : ctx->active_ws_conn_id = ULONG_MAX;
74 :
75 0 : ctx->next_client_nanos = now;
76 0 : ctx->next_metric_rate_update_nanos = now;
77 0 : ctx->next_gossip_stats_update_nanos = now;
78 0 : memset( &ctx->gossip_stats, 0, sizeof(ctx->gossip_stats) );
79 :
80 0 : for( ulong i = 0; i<FD_CONTACT_INFO_TABLE_SIZE; i++) ctx->contact_info_table[ i ].valid = 0;
81 :
82 0 : ctx->live_table = fd_gui_peers_live_table_join( fd_gui_peers_live_table_new( _live_table, FD_CONTACT_INFO_TABLE_SIZE ) );
83 0 : fd_gui_peers_live_table_seed( ctx->contact_info_table, FD_CONTACT_INFO_TABLE_SIZE, 42UL );
84 :
85 0 : ctx->bw_tracking = fd_gui_peers_bandwidth_tracking_join( fd_gui_peers_bandwidth_tracking_new( _bw_tracking, FD_CONTACT_INFO_TABLE_SIZE ) );
86 0 : fd_gui_peers_bandwidth_tracking_seed( ctx->contact_info_table, FD_CONTACT_INFO_TABLE_SIZE, 42UL );
87 :
88 0 : ctx->node_pubkey_map = fd_gui_peers_node_pubkey_map_join( fd_gui_peers_node_pubkey_map_new( _pubkey_map, fd_gui_peers_node_pubkey_map_chain_cnt_est( FD_CONTACT_INFO_TABLE_SIZE ), 42UL ) );
89 0 : ctx->node_sock_map = fd_gui_peers_node_sock_map_join ( fd_gui_peers_node_sock_map_new ( _sock_map, fd_gui_peers_node_sock_map_chain_cnt_est ( FD_CONTACT_INFO_TABLE_SIZE ), 42UL ) );
90 :
91 0 : return shmem;
92 0 : }
93 :
94 : fd_gui_peers_ctx_t *
95 0 : fd_gui_peers_join( void * shmem ) {
96 0 : if( FD_UNLIKELY( !shmem ) ) {
97 0 : FD_LOG_WARNING(( "NULL shmem" ));
98 0 : return NULL;
99 0 : }
100 :
101 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_gui_peers_align() ) ) ) {
102 0 : FD_LOG_WARNING(( "misaligned shmem" ));
103 0 : return NULL;
104 0 : }
105 :
106 0 : fd_gui_peers_ctx_t * ctx = (fd_gui_peers_ctx_t *)shmem;
107 :
108 0 : return ctx;
109 0 : }
110 :
111 : static ulong
112 : fd_gui_sum_tiles_counter( fd_gui_peers_ctx_t * peers,
113 : char const * name,
114 : ulong tile_cnt,
115 0 : ulong metric_idx ) {
116 0 : ulong total = 0UL;
117 0 : for( ulong i = 0UL; i < peers->topo->tile_cnt; i++ ) {
118 0 : if( FD_UNLIKELY( !strcmp( peers->topo->tiles[ i ].name, name ) ) ) {
119 0 : FD_TEST( peers->topo->tiles[ i ].kind_id < tile_cnt );
120 0 : fd_topo_tile_t const * tile = &peers->topo->tiles[ i ];
121 0 : volatile ulong const * tile_metrics = fd_metrics_tile( tile->metrics );
122 0 : total += tile_metrics[ metric_idx ];
123 0 : }
124 0 : }
125 0 : return total;
126 0 : }
127 :
128 : static void
129 : fd_gui_peers_gossip_stats_snap( fd_gui_peers_ctx_t * peers,
130 : fd_gui_peers_gossip_stats_t * gossip_stats,
131 0 : long now ) {
132 0 : gossip_stats->sample_time = now;
133 0 : ulong gossvf_tile_cnt = fd_topo_tile_name_cnt( peers->topo, "gossvf" );
134 0 : ulong gossip_tile_cnt = 1UL;
135 :
136 0 : gossip_stats->network_health_pull_response_msg_rx_success =
137 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) );
138 0 : gossip_stats->network_health_pull_response_msg_rx_failure =
139 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) );
140 0 : gossip_stats->network_health_push_msg_rx_success =
141 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) );
142 0 : gossip_stats->network_health_push_msg_rx_failure =
143 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) );
144 0 : gossip_stats->network_health_push_crds_rx_success =
145 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PUSH ) );
146 0 : gossip_stats->network_health_push_crds_rx_failure =
147 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_STALE ) )
148 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) )
149 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_SIGNATURE ) )
150 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_RELAYER_NO_CONTACT_INFO ) )
151 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_RELAYER_SHRED_VERSION ) )
152 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_NO_CONTACT_INFO ) )
153 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_ORIGIN_SHRED_VERSION ) )
154 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_INACTIVE ) )
155 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PUSH_WALLCLOCK ) );
156 0 : gossip_stats->network_health_pull_response_crds_rx_success =
157 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_UPSERTED_PULL_RESPONSE ) );
158 0 : gossip_stats->network_health_pull_response_crds_rx_failure =
159 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_STALE ) )
160 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_WALLCLOCK ) )
161 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) )
162 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) )
163 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_SIGNATURE ) )
164 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_RELAYER_SHRED_VERSION ) )
165 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_NO_CONTACT_INFO ) )
166 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_ORIGIN_SHRED_VERSION ) )
167 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_INACTIVE ) );
168 0 : gossip_stats->network_health_push_crds_rx_duplicate =
169 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PUSH_DUPLICATE ) );
170 0 : gossip_stats->network_health_pull_response_crds_rx_duplicate =
171 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) )
172 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, CRDS_RX_COUNT_DROPPED_PULL_RESPONSE_DUPLICATE ) );
173 :
174 0 : gossip_stats->network_health_total_stake = 0UL; /* todo ... fetch from RPC */
175 0 : gossip_stats->network_health_total_peers = 0UL; /* todo ... fetch from RPC */
176 :
177 0 : gossip_stats->network_health_connected_stake = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_PEER_TOTAL_STAKE ) );
178 0 : gossip_stats->network_health_connected_staked_peers = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_PEER_STAKED_COUNT ) );
179 0 : gossip_stats->network_health_connected_unstaked_peers = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_PEER_UNSTAKED_COUNT ) );
180 :
181 0 : gossip_stats->network_ingress_peer_sz = fd_ulong_min( fd_gui_peers_bandwidth_tracking_ele_cnt( peers->bw_tracking ), FD_GUI_PEERS_GOSSIP_TOP_PEERS_CNT );
182 0 : gossip_stats->network_ingress_total_bytes_per_sec = 0UL;
183 :
184 0 : for( fd_gui_peers_bandwidth_tracking_fwd_iter_t iter = fd_gui_peers_bandwidth_tracking_fwd_iter_init( peers->bw_tracking, &FD_GUI_PEERS_BW_TRACKING_INGRESS_SORT_KEY, peers->contact_info_table ), j = 0UL;
185 0 : !fd_gui_peers_bandwidth_tracking_fwd_iter_done( iter );
186 0 : iter = fd_gui_peers_bandwidth_tracking_fwd_iter_next( iter, peers->contact_info_table ), j++ ) {
187 0 : fd_gui_peers_node_t * cur = fd_gui_peers_bandwidth_tracking_fwd_iter_ele( iter, peers->contact_info_table );
188 :
189 0 : if( FD_UNLIKELY( j<gossip_stats->network_ingress_peer_sz ) ) {
190 0 : if( FD_LIKELY( cur->has_node_info ) ) FD_TEST( fd_cstr_printf_check( gossip_stats->network_ingress_peer_names[ j ], sizeof(gossip_stats->network_ingress_peer_names[ j ]), NULL, "%s", cur->name ) );
191 0 : else gossip_stats->network_ingress_peer_names[ j ][ 0 ] = '\0';
192 0 : gossip_stats->network_ingress_peer_bytes_per_sec[ j ] = cur->gossvf_rx_sum.rate;
193 0 : fd_memcpy( &gossip_stats->network_ingress_peer_identities[ j ], cur->contact_info.pubkey.uc, 32UL );
194 0 : }
195 :
196 0 : gossip_stats->network_ingress_total_bytes_per_sec += cur->gossvf_rx_sum.rate;
197 0 : }
198 :
199 0 : gossip_stats->network_ingress_total_bytes =
200 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST) )
201 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE) )
202 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH) )
203 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE) )
204 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING) )
205 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG) )
206 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_UNPARSEABLE) )
207 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO) )
208 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_LOOPBACK) )
209 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_INACTIVE) )
210 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_WALLCLOCK) )
211 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SIGNATURE) )
212 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_REQUEST_SHRED_VERSION) )
213 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_DESTINATION) )
214 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_WALLCLOCK) )
215 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PRUNE_SIGNATURE) )
216 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PUSH_NO_VALID_CRDS) )
217 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PULL_RESPONSE_NO_VALID_CRDS) )
218 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PING_SIGNATURE) )
219 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_DROPPED_PONG_SIGNATURE) );
220 :
221 0 : gossip_stats->network_egress_peer_sz = fd_ulong_min( fd_gui_peers_bandwidth_tracking_ele_cnt( peers->bw_tracking ), FD_GUI_PEERS_GOSSIP_TOP_PEERS_CNT );
222 :
223 0 : FD_TEST( gossip_stats->network_egress_peer_sz==gossip_stats->network_ingress_peer_sz );
224 :
225 0 : gossip_stats->network_egress_peer_sz = fd_ulong_min( fd_gui_peers_bandwidth_tracking_ele_cnt( peers->bw_tracking ), FD_GUI_PEERS_GOSSIP_TOP_PEERS_CNT );
226 0 : gossip_stats->network_egress_total_bytes_per_sec = 0UL;
227 :
228 0 : for( fd_gui_peers_bandwidth_tracking_fwd_iter_t iter = fd_gui_peers_bandwidth_tracking_fwd_iter_init( peers->bw_tracking, &FD_GUI_PEERS_BW_TRACKING_EGRESS_SORT_KEY, peers->contact_info_table ), j = 0UL;
229 0 : !fd_gui_peers_bandwidth_tracking_fwd_iter_done( iter );
230 0 : iter = fd_gui_peers_bandwidth_tracking_fwd_iter_next( iter, peers->contact_info_table ), j++ ) {
231 0 : fd_gui_peers_node_t * cur = fd_gui_peers_bandwidth_tracking_fwd_iter_ele( iter, peers->contact_info_table );
232 :
233 0 : if( FD_UNLIKELY( j<gossip_stats->network_egress_peer_sz ) ) {
234 0 : if( FD_LIKELY( cur->has_node_info ) ) FD_TEST( fd_cstr_printf_check( gossip_stats->network_egress_peer_names[ j ], sizeof(gossip_stats->network_egress_peer_names[ j ]), NULL, "%s", cur->name ) );
235 0 : else gossip_stats->network_egress_peer_names[ j ][ 0 ] = '\0';
236 0 : gossip_stats->network_egress_peer_bytes_per_sec[ j ] = cur->gossip_tx_sum.rate;
237 0 : fd_memcpy( &gossip_stats->network_egress_peer_identities[ j ], cur->contact_info.pubkey.uc, 32UL );
238 0 : }
239 :
240 0 : gossip_stats->network_egress_total_bytes_per_sec += cur->gossip_tx_sum.rate;
241 0 : }
242 :
243 0 : gossip_stats->network_egress_total_bytes =
244 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) )
245 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) )
246 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) )
247 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) )
248 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) )
249 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) );
250 :
251 0 : gossip_stats->storage_capacity = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_CAPACITY ) );
252 0 : gossip_stats->storage_expired_cnt = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_EXPIRED_COUNT ) );
253 0 : gossip_stats->storage_evicted_cnt = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_EVICTED_COUNT ) );
254 :
255 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_CONTACT_INFO_V1_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V1 ) );
256 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_VOTE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_VOTE ) );
257 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_LOWEST_SLOT_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_LOWEST_SLOT ) );
258 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_SNAPSHOT_HASHES_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_SNAPSHOT_HASHES ) );
259 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_ACCOUNTS_HASHES_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_ACCOUNTS_HASHES ) );
260 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_EPOCH_SLOTS_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_EPOCH_SLOTS ) );
261 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_VERSION_V1_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_VERSION_V1 ) );
262 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_VERSION_V2_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_VERSION_V2 ) );
263 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_NODE_INSTANCE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_NODE_INSTANCE ) );
264 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_DUPLICATE_SHRED_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_DUPLICATE_SHRED ) );
265 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_INCREMENTAL_SNAPSHOT_HASHES_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_INCREMENTAL_SNAPSHOT_HASHES ) );
266 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_CONTACT_INFO_V2_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_CONTACT_INFO_V2 ) );
267 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_RESTART_LAST_VOTED_FORK_SLOTS_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_RESTART_LAST_VOTED_FORK_SLOTS ) );
268 0 : gossip_stats->storage_active_cnt[ FD_METRICS_ENUM_CRDS_VALUE_V_RESTART_HEAVIEST_FORK_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( GAUGE, GOSSIP, CRDS_COUNT_RESTART_HEAVIEST_FORK ) );
269 :
270 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_CONTACT_INFO_V1_IDX ] =
271 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_CONTACT_INFO_V1 ) )
272 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_CONTACT_INFO_V1 ) );
273 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_VOTE_IDX ] =
274 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_VOTE ) )
275 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_VOTE ) );
276 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_LOWEST_SLOT_IDX ] =
277 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_LOWEST_SLOT ) )
278 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_LOWEST_SLOT ) );
279 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_SNAPSHOT_HASHES_IDX ] =
280 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_SNAPSHOT_HASHES ) )
281 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_SNAPSHOT_HASHES ) );
282 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_ACCOUNTS_HASHES_IDX ] =
283 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_ACCOUNTS_HASHES ) )
284 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_ACCOUNTS_HASHES ) );
285 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_EPOCH_SLOTS_IDX ] =
286 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_EPOCH_SLOTS ) )
287 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_EPOCH_SLOTS ) );
288 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_VERSION_V1_IDX ] =
289 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_VERSION_V1 ) )
290 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_VERSION_V1 ) );
291 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_VERSION_V2_IDX ] =
292 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_VERSION_V2 ) )
293 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_VERSION_V2 ) );
294 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_NODE_INSTANCE_IDX ] =
295 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_NODE_INSTANCE ) )
296 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_NODE_INSTANCE ) );
297 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_DUPLICATE_SHRED_IDX ] =
298 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_DUPLICATE_SHRED ) )
299 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_DUPLICATE_SHRED ) );
300 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_INCREMENTAL_SNAPSHOT_HASHES_IDX ] =
301 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_INCREMENTAL_SNAPSHOT_HASHES ) )
302 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_INCREMENTAL_SNAPSHOT_HASHES ) );
303 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_CONTACT_INFO_V2_IDX ] =
304 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_CONTACT_INFO_V2 ) )
305 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_CONTACT_INFO_V2 ) );
306 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_RESTART_LAST_VOTED_FORK_SLOTS_IDX ] =
307 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_RESTART_LAST_VOTED_FORK_SLOTS ) )
308 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_RESTART_LAST_VOTED_FORK_SLOTS ) );
309 0 : gossip_stats->storage_cnt_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_RESTART_HEAVIEST_FORK_IDX ] =
310 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_COUNT_RESTART_HEAVIEST_FORK ) )
311 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_COUNT_RESTART_HEAVIEST_FORK ) );
312 :
313 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_CONTACT_INFO_V1_IDX ] =
314 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_CONTACT_INFO_V1 ) )
315 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_CONTACT_INFO_V1 ) );
316 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_VOTE_IDX ] =
317 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_VOTE ) )
318 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_VOTE ) );
319 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_LOWEST_SLOT_IDX ] =
320 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_LOWEST_SLOT ) )
321 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_LOWEST_SLOT ) );
322 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_SNAPSHOT_HASHES_IDX ] =
323 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_SNAPSHOT_HASHES ) )
324 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_SNAPSHOT_HASHES ) );
325 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_ACCOUNTS_HASHES_IDX ] =
326 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_ACCOUNTS_HASHES ) )
327 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_ACCOUNTS_HASHES ) );
328 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_EPOCH_SLOTS_IDX ] =
329 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_EPOCH_SLOTS ) )
330 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_EPOCH_SLOTS ) );
331 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_VERSION_V1_IDX ] =
332 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_VERSION_V1 ) )
333 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_VERSION_V1 ) );
334 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_VERSION_V2_IDX ] =
335 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_VERSION_V2 ) )
336 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_VERSION_V2 ) );
337 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_NODE_INSTANCE_IDX ] =
338 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_NODE_INSTANCE ) )
339 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_NODE_INSTANCE ) );
340 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_DUPLICATE_SHRED_IDX ] =
341 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_DUPLICATE_SHRED ) )
342 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_DUPLICATE_SHRED ) );
343 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_INCREMENTAL_SNAPSHOT_HASHES_IDX ] =
344 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_INCREMENTAL_SNAPSHOT_HASHES ) )
345 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_INCREMENTAL_SNAPSHOT_HASHES ) );
346 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_CONTACT_INFO_V2_IDX ] =
347 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_CONTACT_INFO_V2 ) )
348 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_CONTACT_INFO_V2 ) );
349 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_RESTART_LAST_VOTED_FORK_SLOTS_IDX ] =
350 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_RESTART_LAST_VOTED_FORK_SLOTS ) )
351 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_RESTART_LAST_VOTED_FORK_SLOTS ) );
352 0 : gossip_stats->storage_bytes_tx[ FD_METRICS_ENUM_CRDS_VALUE_V_RESTART_HEAVIEST_FORK_IDX ] =
353 0 : fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PUSH_BYTES_RESTART_HEAVIEST_FORK ) )
354 0 : + fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, CRDS_TX_PULL_RESPONSE_BYTES_RESTART_HEAVIEST_FORK ) );
355 :
356 0 : gossip_stats->messages_bytes_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_REQUEST_IDX ] = fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_REQUEST ) );
357 0 : gossip_stats->messages_bytes_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_RESPONSE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PULL_RESPONSE ) );
358 0 : gossip_stats->messages_bytes_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PUSH_IDX ] = fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PUSH ) );
359 0 : gossip_stats->messages_bytes_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PING_IDX ] = fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PING ) );
360 0 : gossip_stats->messages_bytes_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PONG_IDX ] = fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PONG ) );
361 0 : gossip_stats->messages_bytes_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PRUNE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_BYTES_SUCCESS_PRUNE ) );
362 :
363 0 : gossip_stats->messages_count_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_REQUEST_IDX ] =
364 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_REQUEST ) )
365 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_NOT_CONTACT_INFO ) )
366 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_LOOPBACK ) )
367 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_INACTIVE ) )
368 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_WALLCLOCK ) )
369 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SIGNATURE ) )
370 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_REQUEST_SHRED_VERSION ) );
371 0 : gossip_stats->messages_count_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_RESPONSE_IDX ] =
372 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PULL_RESPONSE ) )
373 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PULL_RESPONSE_NO_VALID_CRDS ) );
374 0 : gossip_stats->messages_count_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PUSH_IDX ] =
375 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PUSH ) )
376 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PUSH_NO_VALID_CRDS ) );
377 0 : gossip_stats->messages_count_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PING_IDX ] =
378 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PING ) )
379 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PING_SIGNATURE ) );
380 0 : gossip_stats->messages_count_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PONG_IDX ] =
381 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PONG ) )
382 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PONG_SIGNATURE ) );
383 0 : gossip_stats->messages_count_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PRUNE_IDX ] =
384 0 : fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_SUCCESS_PRUNE ) )
385 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_DESTINATION ) )
386 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_WALLCLOCK ) )
387 0 : + fd_gui_sum_tiles_counter( peers, "gossvf", gossvf_tile_cnt, MIDX( COUNTER, GOSSVF, MESSAGE_RX_COUNT_DROPPED_PRUNE_SIGNATURE ) );
388 :
389 0 : gossip_stats->messages_bytes_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_REQUEST_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_REQUEST ) );
390 0 : gossip_stats->messages_bytes_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_RESPONSE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PULL_RESPONSE ) );
391 0 : gossip_stats->messages_bytes_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PUSH_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PUSH ) );
392 0 : gossip_stats->messages_bytes_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PING_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PING ) );
393 0 : gossip_stats->messages_bytes_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PONG_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PONG ) );
394 0 : gossip_stats->messages_bytes_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PRUNE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_BYTES_PRUNE ) );
395 :
396 0 : gossip_stats->messages_count_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_REQUEST_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_REQUEST ) );
397 0 : gossip_stats->messages_count_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_RESPONSE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PULL_RESPONSE ) );
398 0 : gossip_stats->messages_count_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PUSH_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PUSH ) );
399 0 : gossip_stats->messages_count_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PING_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PING ) );
400 0 : gossip_stats->messages_count_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PONG_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PONG ) );
401 0 : gossip_stats->messages_count_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PRUNE_IDX ] = fd_gui_sum_tiles_counter( peers, "gossip", gossip_tile_cnt, MIDX( COUNTER, GOSSIP, MESSAGE_TX_COUNT_PRUNE ) );
402 0 : }
403 :
404 : static int
405 : fd_gui_peers_contact_info_eq( fd_contact_info_t const * ci1,
406 0 : fd_contact_info_t const * ci2 ) {
407 0 : int ci_eq =
408 0 : ci1->shred_version == ci2->shred_version
409 0 : && ci1->instance_creation_wallclock_nanos== ci2->instance_creation_wallclock_nanos
410 : // && ci1->wallclock_nanos == ci2->wallclock_nanos
411 0 : && ci1->version.client == ci2->version.client
412 0 : && ci1->version.major == ci2->version.major
413 0 : && ci1->version.minor == ci2->version.minor
414 0 : && ci1->version.patch == ci2->version.patch
415 0 : && ci1->version.commit == ci2->version.commit
416 0 : && ci1->version.feature_set == ci2->version.feature_set;
417 :
418 0 : if( FD_LIKELY( !ci_eq ) ) return 0;
419 0 : for( ulong j=0UL; j<(FD_CONTACT_INFO_SOCKET_CNT); j++ ) {
420 0 : if( FD_LIKELY( !(ci1->sockets[ j ].addr==ci2->sockets[ j ].addr && ci1->sockets[ j ].port==ci2->sockets[ j ].port) ) ) return 0;
421 0 : }
422 0 : return 1;
423 0 : }
424 :
425 : void
426 : fd_gui_peers_handle_gossip_message( fd_gui_peers_ctx_t * peers,
427 : uchar const * payload,
428 : ulong payload_sz,
429 : fd_ip4_port_t const * peer_sock,
430 0 : int is_rx ) {
431 0 : fd_gui_peers_node_t * peer = fd_gui_peers_node_sock_map_ele_query( peers->node_sock_map, peer_sock, NULL, peers->contact_info_table );
432 :
433 : /* We set MAP_MULTI=1 since there are not guarantees that duplicates
434 : sockets wont exist. In cases where we see multiple sockets the
435 : update timestamp in fd_gui_peers_node_t is the tiebreaker */
436 0 : for( fd_gui_peers_node_t * p = peer; p!=NULL; p=(fd_gui_peers_node_t *)fd_gui_peers_node_sock_map_ele_next_const( p, NULL, peers->contact_info_table ) ) {
437 0 : if( peer->update_time_nanos>p->update_time_nanos ) peer = p;
438 0 : }
439 :
440 0 : if( FD_UNLIKELY( !peer ) ) return; /* NOP, peer not known yet */
441 :
442 0 : fd_gossip_view_t view[ 1 ];
443 0 : ulong decode_sz = fd_gossip_msg_parse( view, payload, payload_sz );
444 0 : if( FD_UNLIKELY( !decode_sz ) ) return; /* NOP, msg unparsable */
445 :
446 0 : FD_TEST( view->tag < FD_METRICS_ENUM_GOSSIP_MESSAGE_CNT );
447 0 : fd_ptr_if( is_rx, &peer->gossvf_rx[ view->tag ], &peer->gossip_tx[ view->tag ] )->cur += payload_sz;
448 0 : fd_ptr_if( is_rx, (fd_gui_peers_metric_rate_t *)&peer->gossvf_rx_sum, (fd_gui_peers_metric_rate_t *)&peer->gossip_tx_sum )->cur += payload_sz;
449 : #if LOGGING
450 : if( is_rx ) FD_LOG_WARNING(("payload rx=%lu", payload_sz ));
451 : else FD_LOG_WARNING(("payload tx=%lu", payload_sz ));
452 : #endif
453 0 : }
454 :
455 : int
456 : fd_gui_peers_handle_gossip_update( fd_gui_peers_ctx_t * peers,
457 : fd_gossip_update_message_t const * update,
458 0 : long now ) {
459 0 : switch( update->tag ) {
460 0 : case FD_GOSSIP_UPDATE_TAG_CONTACT_INFO: {
461 : /* origin_pubkey should be the same as the contact info pubkey */
462 0 : if( FD_UNLIKELY( memcmp( update->contact_info.contact_info->pubkey.uc, update->origin_pubkey, 32UL ) ) ) {
463 0 : char ci_pk[ FD_BASE58_ENCODED_32_SZ ];
464 0 : char og_pk[ FD_BASE58_ENCODED_32_SZ ];
465 0 : fd_base58_encode_32( update->contact_info.contact_info->pubkey.uc, NULL, ci_pk );
466 0 : fd_base58_encode_32( update->origin_pubkey, NULL, og_pk );
467 :
468 0 : FD_LOG_ERR(( "invariant violation: update->contact_info.contact_info->pubkey.uc=%s != update->origin_pubkey=%s ", ci_pk, og_pk ));
469 0 : }
470 0 : if( FD_UNLIKELY( update->contact_info.idx>=FD_CONTACT_INFO_TABLE_SIZE ) ) FD_LOG_ERR(( "unexpected contact_info_idx %lu >= %lu", update->contact_info.idx, FD_CONTACT_INFO_TABLE_SIZE ));
471 0 : fd_gui_peers_node_t * peer = &peers->contact_info_table[ update->contact_info.idx ];
472 :
473 0 : if( FD_LIKELY( peer->valid ) ) {
474 : #if LOGGING
475 : char _pk[ FD_BASE58_ENCODED_32_SZ ];
476 : fd_base58_encode_32( update->origin_pubkey, NULL, _pk );
477 : FD_LOG_WARNING(("UPDATE %lu pk=%s", update->contact_info.idx, _pk ));
478 : #endif
479 : /* invariant checks */
480 0 : if( FD_UNLIKELY( memcmp( peer->contact_info.pubkey.uc, update->origin_pubkey, 32UL ) ) ) {
481 0 : char ci_pk[ FD_BASE58_ENCODED_32_SZ ];
482 0 : char og_pk[ FD_BASE58_ENCODED_32_SZ ];
483 0 : fd_base58_encode_32( peer->contact_info.pubkey.uc, NULL, ci_pk );
484 0 : fd_base58_encode_32( update->origin_pubkey, NULL, og_pk );
485 :
486 : /* A new pubkey is not allowed to overwrite an existing valid index */
487 0 : FD_LOG_ERR(( "invariant violation: peer->contact_info.pubkey.uc=%s != update->origin_pubkey=%s ", ci_pk, og_pk ));
488 0 : }
489 0 : FD_TEST( peer==fd_gui_peers_node_pubkey_map_ele_query_const( peers->node_pubkey_map, (fd_pubkey_t * )update->origin_pubkey, NULL, peers->contact_info_table ) );
490 0 : fd_gui_peers_node_t * peer_sock = fd_gui_peers_node_sock_map_ele_query( peers->node_sock_map, &peer->contact_info.sockets[ FD_CONTACT_INFO_SOCKET_GOSSIP ], NULL, peers->contact_info_table );
491 0 : int found = 0;
492 0 : for( fd_gui_peers_node_t * p = peer_sock; !!p; p=(fd_gui_peers_node_t *)fd_gui_peers_node_sock_map_ele_next_const( p, NULL, peers->contact_info_table ) ) {
493 0 : if( peer==p ) {
494 0 : found = 1;
495 0 : break;
496 0 : }
497 0 : }
498 0 : FD_TEST( found );
499 :
500 : /* update does nothing */
501 0 : if( FD_UNLIKELY( fd_gui_peers_contact_info_eq( &peer->contact_info, update->contact_info.contact_info ) ) ) {
502 0 : peer->contact_info.wallclock_nanos = update->contact_info.contact_info->wallclock_nanos;
503 0 : return FD_GUI_PEERS_NODE_NOP;
504 0 : }
505 :
506 0 : fd_gui_peers_node_sock_map_idx_remove_fast( peers->node_sock_map, update->contact_info.idx, peers->contact_info_table );
507 0 : fd_gui_peers_live_table_idx_remove ( peers->live_table, update->contact_info.idx, peers->contact_info_table );
508 0 : fd_gui_peers_bandwidth_tracking_idx_remove( peers->bw_tracking, update->contact_info.idx, peers->contact_info_table );
509 :
510 0 : fd_memcpy( &peer->contact_info, update->contact_info.contact_info, sizeof(peer->contact_info) );
511 0 : peer->update_time_nanos = now;
512 :
513 0 : fd_gui_peers_bandwidth_tracking_idx_insert( peers->bw_tracking, update->contact_info.idx, peers->contact_info_table );
514 0 : fd_gui_peers_live_table_idx_insert ( peers->live_table, update->contact_info.idx, peers->contact_info_table );
515 0 : fd_gui_peers_node_sock_map_idx_insert ( peers->node_sock_map, update->contact_info.idx, peers->contact_info_table );
516 :
517 0 : return FD_GUI_PEERS_NODE_UPDATE;
518 0 : } else {
519 0 : FD_TEST( !fd_gui_peers_node_pubkey_map_ele_query_const( peers->node_pubkey_map, &update->contact_info.contact_info->pubkey, NULL, peers->contact_info_table ) );
520 : #if LOGGING
521 : char _pk[ FD_BASE58_ENCODED_32_SZ ];
522 : fd_base58_encode_32( update->origin_pubkey, NULL, _pk );
523 : FD_LOG_WARNING(( "ADD %lu pk=%s", update->contact_info.idx, _pk ));
524 : #endif
525 0 : memset( &peer->gossvf_rx, 0, sizeof(peer->gossvf_rx) );
526 0 : memset( &peer->gossip_tx, 0, sizeof(peer->gossip_tx) );
527 0 : memset( &peer->gossvf_rx_sum, 0, sizeof(peer->gossvf_rx_sum) );
528 0 : memset( &peer->gossip_tx_sum, 0, sizeof(peer->gossip_tx_sum) );
529 0 : peer->has_node_info = 0;
530 0 : peer->valid = 1;
531 0 : peer->update_time_nanos = now;
532 0 : fd_memcpy( &peer->contact_info, update->contact_info.contact_info, sizeof(peer->contact_info) );
533 :
534 : /* update pubkey_map, sock_map */
535 0 : fd_gui_peers_node_sock_map_idx_insert ( peers->node_sock_map, update->contact_info.idx, peers->contact_info_table );
536 0 : fd_gui_peers_node_pubkey_map_idx_insert( peers->node_pubkey_map, update->contact_info.idx, peers->contact_info_table );
537 :
538 : /* update live tables */
539 0 : fd_gui_peers_live_table_idx_insert ( peers->live_table, update->contact_info.idx, peers->contact_info_table );
540 0 : fd_gui_peers_bandwidth_tracking_idx_insert( peers->bw_tracking, update->contact_info.idx, peers->contact_info_table );
541 :
542 0 : fd_gui_printf_peers_view_resize( peers, fd_gui_peers_live_table_ele_cnt( peers->live_table ) );
543 0 : FD_TEST( !fd_http_server_ws_broadcast( peers->http ) );
544 :
545 0 : return FD_GUI_PEERS_NODE_ADD;
546 0 : }
547 :
548 0 : break;
549 0 : }
550 0 : case FD_GOSSIP_UPDATE_TAG_CONTACT_INFO_REMOVE: {
551 0 : if( FD_UNLIKELY( update->contact_info_remove.idx>=FD_CONTACT_INFO_TABLE_SIZE ) ) FD_LOG_ERR(( "unexpected remove_contact_info_idx %lu >= %lu", update->contact_info_remove.idx, FD_CONTACT_INFO_TABLE_SIZE ));
552 : #if LOGGING
553 : char _pk[ FD_BASE58_ENCODED_32_SZ ];
554 : fd_base58_encode_32( update->origin_pubkey, NULL, _pk );
555 : FD_LOG_WARNING(( "REMOVE %lu pk=%s",update->contact_info.idx, _pk ));
556 : #endif
557 :
558 0 : fd_gui_peers_node_t * peer = &peers->contact_info_table[ update->contact_info_remove.idx ];
559 :
560 : /* invariant checks */
561 0 : FD_TEST( peer->valid ); /* Should have already been in the table */
562 0 : FD_TEST( peer==fd_gui_peers_node_pubkey_map_ele_query_const( peers->node_pubkey_map, (fd_pubkey_t * )update->origin_pubkey, NULL, peers->contact_info_table ) );
563 0 : fd_gui_peers_node_t * peer_sock = fd_gui_peers_node_sock_map_ele_query( peers->node_sock_map, &peer->contact_info.sockets[ FD_CONTACT_INFO_SOCKET_GOSSIP ], NULL, peers->contact_info_table );
564 0 : int found = 0;
565 0 : for( fd_gui_peers_node_t const * p = peer_sock; !!p; p=(fd_gui_peers_node_t const *)fd_gui_peers_node_sock_map_ele_next_const( p, NULL, peers->contact_info_table ) ) {
566 0 : if( peer==p ) {
567 0 : found = 1;
568 0 : break;
569 0 : }
570 0 : }
571 0 : FD_TEST( found );
572 :
573 0 : fd_gui_peers_live_table_idx_remove ( peers->live_table, update->contact_info_remove.idx, peers->contact_info_table );
574 0 : fd_gui_peers_bandwidth_tracking_idx_remove ( peers->bw_tracking, update->contact_info_remove.idx, peers->contact_info_table );
575 0 : fd_gui_peers_node_sock_map_idx_remove_fast ( peers->node_sock_map, update->contact_info_remove.idx, peers->contact_info_table );
576 0 : fd_gui_peers_node_pubkey_map_idx_remove_fast( peers->node_pubkey_map, update->contact_info_remove.idx, peers->contact_info_table );
577 0 : peer->valid = 0;
578 :
579 0 : fd_gui_printf_peers_view_resize( peers, fd_gui_peers_live_table_ele_cnt( peers->live_table ) );
580 0 : FD_TEST( !fd_http_server_ws_broadcast( peers->http ) );
581 0 : break;
582 0 : }
583 0 : default: break;
584 0 : }
585 :
586 0 : return FD_GUI_PEERS_NODE_NOP;
587 0 : }
588 :
589 : static void
590 0 : fd_gui_peers_viewport_snap( fd_gui_peers_ctx_t * peers, ulong ws_conn_id ) {
591 0 : FD_TEST( peers->client_viewports[ ws_conn_id ].connected );
592 0 : if( !(peers->client_viewports[ ws_conn_id ].row_cnt && peers->client_viewports[ ws_conn_id ].row_cnt<FD_GUI_PEERS_WS_VIEWPORT_MAX_SZ) ) FD_LOG_ERR(("row_cnt=%lu", peers->client_viewports[ ws_conn_id ].row_cnt ));
593 :
594 0 : if( FD_UNLIKELY( fd_gui_peers_live_table_active_sort_key_cnt( peers->live_table )==FD_GUI_PEERS_CI_TABLE_SORT_KEY_CNT ) ) {
595 : /* we're out of cached sort keys. disconnect the oldest client */
596 0 : ulong oldest_ws_conn_id = ULONG_MAX;
597 0 : long oldest_connected_time = LONG_MAX;
598 0 : for( ulong i=0UL; i<peers->max_ws_conn_cnt; i++ ) {
599 0 : if( FD_UNLIKELY( peers->client_viewports[ i ].connected && peers->client_viewports[ i ].connected_time < oldest_connected_time ) ) {
600 0 : oldest_ws_conn_id = i;
601 0 : oldest_connected_time = peers->client_viewports[ i ].connected_time;
602 0 : }
603 0 : }
604 0 : FD_TEST( oldest_ws_conn_id!=ULONG_MAX );
605 0 : fd_gui_peers_live_table_sort_key_remove( peers->live_table, peers->client_viewports[ oldest_ws_conn_id ].sort_key );
606 0 : FD_TEST( fd_gui_peers_live_table_active_sort_key_cnt( peers->live_table )==FD_GUI_PEERS_CI_TABLE_SORT_KEY_CNT-1UL );
607 0 : }
608 :
609 0 : for( fd_gui_peers_live_table_fwd_iter_t iter = fd_gui_peers_live_table_fwd_iter_init( peers->live_table, peers->client_viewports[ ws_conn_id ].sort_key, peers->contact_info_table ), j = 0;
610 0 : !fd_gui_peers_live_table_fwd_iter_done( iter ) && j<peers->client_viewports[ ws_conn_id ].start_row+peers->client_viewports[ ws_conn_id ].row_cnt;
611 0 : iter = fd_gui_peers_live_table_fwd_iter_next( iter, peers->contact_info_table ), j++ ) {
612 0 : if( FD_LIKELY( j<peers->client_viewports[ ws_conn_id ].start_row ) ) continue;
613 0 : fd_gui_peers_node_t const * cur = fd_gui_peers_live_table_fwd_iter_ele_const( iter, peers->contact_info_table );
614 0 : fd_gui_peers_node_t * ref = &peers->client_viewports[ ws_conn_id ].viewport[ j ];
615 :
616 0 : fd_memcpy( ref, cur, sizeof(fd_gui_peers_node_t) );
617 0 : }
618 0 : }
619 :
620 : static int
621 : fd_gui_peers_request_scroll( fd_gui_peers_ctx_t * peers,
622 : ulong ws_conn_id,
623 : ulong request_id,
624 0 : cJSON const * params ) {
625 0 : if( FD_UNLIKELY( !peers->client_viewports[ ws_conn_id ].connected ) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
626 :
627 0 : const cJSON * start_row_param = cJSON_GetObjectItemCaseSensitive( params, "start_row" );
628 0 : if( FD_UNLIKELY( !cJSON_IsNumber( start_row_param ) ) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
629 0 : ulong _start_row = start_row_param->valueulong;
630 :
631 0 : const cJSON * row_cnt_param = cJSON_GetObjectItemCaseSensitive( params, "row_cnt" );
632 0 : if( FD_UNLIKELY( !cJSON_IsNumber( row_cnt_param ) ) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
633 0 : ulong _row_cnt = row_cnt_param->valueulong;
634 :
635 0 : if( FD_UNLIKELY( _row_cnt==0 || _row_cnt > FD_GUI_PEERS_WS_VIEWPORT_MAX_SZ ) ) {
636 0 : fd_gui_printf_null_query_response( peers->http, "gossip", "query_scroll", request_id );
637 0 : FD_TEST( !fd_http_server_ws_send( peers->http, ws_conn_id ) );
638 0 : return 0;
639 0 : }
640 :
641 0 : if( FD_UNLIKELY( peers->client_viewports[ ws_conn_id ].start_row==_start_row && peers->client_viewports[ ws_conn_id ].row_cnt==_row_cnt ) ) {
642 0 : return 0; /* NOP, scroll window hasn't changed */
643 0 : }
644 :
645 : /* update the client's viewport */
646 0 : peers->client_viewports[ ws_conn_id ].start_row = _start_row;
647 0 : peers->client_viewports[ ws_conn_id ].row_cnt = _row_cnt;
648 :
649 0 : fd_gui_printf_peers_viewport_request( peers, "query_scroll", ws_conn_id, request_id );
650 0 : FD_TEST( !fd_http_server_ws_send( peers->http, ws_conn_id ) );
651 0 : return 0;
652 0 : }
653 :
654 : static int
655 : fd_gui_peers_request_sort( fd_gui_peers_ctx_t * peers,
656 : ulong ws_conn_id,
657 : ulong request_id,
658 0 : cJSON const * params ) {
659 0 : if( FD_UNLIKELY( !peers->client_viewports[ ws_conn_id ].connected ) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
660 :
661 0 : const cJSON * col_id_param = cJSON_GetObjectItemCaseSensitive( params, "col_id" );
662 0 : if( FD_UNLIKELY( !cJSON_IsString( col_id_param ) ) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
663 0 : char * _col_name = col_id_param->valuestring;
664 :
665 0 : ulong _col_idx = fd_gui_peers_live_table_col_name_to_idx( peers->live_table, _col_name );
666 0 : if( FD_UNLIKELY( _col_idx==ULONG_MAX) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
667 0 : ulong sort_idx = ULONG_MAX;
668 0 : for( ulong i=0UL; i<FD_GUI_PEERS_CI_TABLE_SORT_KEY_CNT; i++ ) {
669 0 : if( FD_UNLIKELY( _col_idx==peers->client_viewports[ ws_conn_id ].sort_key->col[ i ] ) ) {
670 0 : sort_idx = i;
671 0 : break;
672 0 : }
673 0 : }
674 0 : FD_TEST( sort_idx!=ULONG_MAX );
675 :
676 0 : const cJSON * dir_param = cJSON_GetObjectItemCaseSensitive( params, "dir" );
677 0 : if( FD_UNLIKELY( !cJSON_IsNumber( dir_param ) ) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
678 0 : int _dir = dir_param->valueint;
679 :
680 0 : if( FD_UNLIKELY( _dir > 1 || _dir < -1 ) ) return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
681 :
682 0 : if( FD_UNLIKELY( peers->client_viewports[ ws_conn_id ].sort_key->dir[ sort_idx ]==_dir ) ) return 0; /* NOP, sort_key hasn't changed */
683 :
684 : /* shift the column to the front of the sort key */
685 0 : for( ulong i=sort_idx; i>0; i-- ) {
686 0 : peers->client_viewports[ ws_conn_id ].sort_key->col[ i ] = peers->client_viewports[ ws_conn_id ].sort_key->col[ i-1UL ];
687 0 : peers->client_viewports[ ws_conn_id ].sort_key->dir[ i ] = peers->client_viewports[ ws_conn_id ].sort_key->dir[ i-1UL ];
688 0 : }
689 0 : peers->client_viewports[ ws_conn_id ].sort_key->col[ 0 ] = _col_idx;
690 0 : peers->client_viewports[ ws_conn_id ].sort_key->dir[ 0 ] = _dir;
691 :
692 0 : if( FD_UNLIKELY( peers->client_viewports[ ws_conn_id ].row_cnt==0 )) return 0; /* NOP */
693 :
694 0 : fd_gui_printf_peers_viewport_request( peers, "query_sort_col", ws_conn_id, request_id );
695 0 : FD_TEST( !fd_http_server_ws_send( peers->http, ws_conn_id ) );
696 0 : return 0;
697 0 : }
698 :
699 : int
700 : fd_gui_peers_ws_message( fd_gui_peers_ctx_t * peers,
701 : ulong ws_conn_id,
702 : uchar const * data,
703 0 : ulong data_len ) {
704 : /* TODO: cJSON allocates, might fail SIGSYS due to brk(2)...
705 : switch off this (or use wksp allocator) */
706 0 : const char * parse_end;
707 0 : cJSON * json = cJSON_ParseWithLengthOpts( (char *)data, data_len, &parse_end, 0 );
708 0 : if( FD_UNLIKELY( !json ) ) {
709 0 : return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
710 0 : }
711 :
712 0 : const cJSON * node = cJSON_GetObjectItemCaseSensitive( json, "id" );
713 0 : if( FD_UNLIKELY( !cJSON_IsNumber( node ) ) ) {
714 0 : cJSON_Delete( json );
715 0 : return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
716 0 : }
717 0 : ulong id = node->valueulong;
718 :
719 0 : const cJSON * topic = cJSON_GetObjectItemCaseSensitive( json, "topic" );
720 0 : if( FD_UNLIKELY( !cJSON_IsString( topic ) || topic->valuestring==NULL ) ) {
721 0 : cJSON_Delete( json );
722 0 : return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
723 0 : }
724 :
725 0 : const cJSON * key = cJSON_GetObjectItemCaseSensitive( json, "key" );
726 0 : if( FD_UNLIKELY( !cJSON_IsString( key ) || key->valuestring==NULL ) ) {
727 0 : cJSON_Delete( json );
728 0 : return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
729 0 : }
730 :
731 0 : if( FD_LIKELY( !strcmp( topic->valuestring, "gossip" ) && !strcmp( key->valuestring, "query_sort_col" ) ) ) {
732 0 : const cJSON * params = cJSON_GetObjectItemCaseSensitive( json, "params" );
733 0 : if( FD_UNLIKELY( !cJSON_IsObject( params ) ) ) {
734 0 : cJSON_Delete( json );
735 0 : return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
736 0 : }
737 :
738 0 : int result = fd_gui_peers_request_sort( peers, ws_conn_id, id, params );
739 0 : cJSON_Delete( json );
740 0 : return result;
741 0 : } else if( FD_LIKELY( !strcmp( topic->valuestring, "gossip" ) && !strcmp( key->valuestring, "query_scroll" ) ) ) {
742 0 : const cJSON * params = cJSON_GetObjectItemCaseSensitive( json, "params" );
743 0 : if( FD_UNLIKELY( !cJSON_IsObject( params ) ) ) {
744 0 : cJSON_Delete( json );
745 0 : return FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST;
746 0 : }
747 :
748 0 : int result = fd_gui_peers_request_scroll( peers, ws_conn_id, id, params );
749 0 : cJSON_Delete( json );
750 0 : return result;
751 0 : }
752 :
753 0 : cJSON_Delete( json );
754 0 : return FD_HTTP_SERVER_CONNECTION_CLOSE_UNKNOWN_METHOD;
755 0 : }
756 :
757 : static void
758 : fd_gui_peers_viewport_log( fd_gui_peers_ctx_t * peers,
759 0 : ulong ws_conn_id) {
760 :
761 0 : FD_TEST( peers->client_viewports[ ws_conn_id ].row_cnt && peers->client_viewports[ ws_conn_id ].row_cnt < FD_GUI_PEERS_WS_VIEWPORT_MAX_SZ );
762 :
763 0 : char out[ 1<<14 ];
764 0 : char * p = fd_cstr_init( out );
765 :
766 0 : p = fd_cstr_append_printf( p,
767 0 : "\n[Viewport] table_size=%lu max_viewport_size=%lu\n"
768 0 : "+-------+----------------+----------------+----------------+----------------+----------------------------------------------------+-----------------+\n"
769 0 : "| Row # | RX Push (bps) | RX Pull (bps) | TX Push (bps) | TX Pull (bps) | Pubkey | IP Address |\n"
770 0 : "+-------+----------------+----------------+----------------+----------------+----------------------------------------------------+-----------------+\n",
771 0 : fd_gui_peers_live_table_ele_cnt( peers->live_table ), peers->client_viewports[ ws_conn_id ].row_cnt );
772 :
773 0 : FD_TEST( peers->client_viewports[ ws_conn_id ].connected );
774 0 : for( fd_gui_peers_live_table_fwd_iter_t iter = fd_gui_peers_live_table_fwd_iter_init( peers->live_table, peers->client_viewports[ ws_conn_id ].sort_key, peers->contact_info_table ), j = 0UL;
775 0 : !fd_gui_peers_live_table_fwd_iter_done(iter) && j < peers->client_viewports[ ws_conn_id ].start_row + peers->client_viewports[ ws_conn_id ].row_cnt;
776 0 : iter = fd_gui_peers_live_table_fwd_iter_next(iter, peers->contact_info_table), j++ ) {
777 0 : if( FD_LIKELY( j < peers->client_viewports[ ws_conn_id ].start_row ) ) continue;
778 :
779 0 : fd_gui_peers_node_t const * cur = fd_gui_peers_live_table_fwd_iter_ele_const( iter, peers->contact_info_table );
780 :
781 0 : char pubkey_base58[ FD_BASE58_ENCODED_32_SZ ];
782 0 : fd_base58_encode_32( cur->contact_info.pubkey.uc, NULL, pubkey_base58 );
783 :
784 0 : char peer_addr[ 16 ]; /* 255.255.255.255 + '\0' */
785 0 : FD_TEST(fd_cstr_printf_check( peer_addr, sizeof(peer_addr), NULL, FD_IP4_ADDR_FMT,
786 0 : FD_IP4_ADDR_FMT_ARGS( cur->contact_info.sockets[FD_CONTACT_INFO_SOCKET_GOSSIP].addr ) ) );
787 :
788 0 : long cur_egress_push_bps = cur->gossip_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PUSH_IDX ].rate;
789 0 : long cur_ingress_push_bps = cur->gossvf_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PUSH_IDX ].rate;
790 0 : long cur_egress_pull_response_bps = cur->gossip_tx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_RESPONSE_IDX ].rate;
791 0 : long cur_ingress_pull_response_bps = cur->gossvf_rx[ FD_METRICS_ENUM_GOSSIP_MESSAGE_V_PULL_RESPONSE_IDX ].rate;
792 :
793 0 : p = fd_cstr_append_printf( p,
794 0 : "| %5lu | %14ld | %14ld | %14ld | %14ld | %-50s | %-15s |\n",
795 0 : peers->client_viewports[ ws_conn_id ].start_row + j,
796 0 : cur_ingress_push_bps,
797 0 : cur_ingress_pull_response_bps,
798 0 : cur_egress_push_bps,
799 0 : cur_egress_pull_response_bps,
800 0 : pubkey_base58,
801 0 : peer_addr );
802 0 : }
803 0 : p = fd_cstr_append_printf(p, "+-------+----------------+----------------+----------------+----------------+----------------------------------------------------+-----------------+" );
804 0 : fd_cstr_fini( p );
805 0 : FD_LOG_NOTICE(( "%s", out ));
806 0 : }
807 :
808 : static void
809 0 : fd_gui_peers_ws_conn_rr_grow( fd_gui_peers_ctx_t * peers, ulong ws_conn_id ) {
810 0 : if( FD_UNLIKELY( !peers->open_ws_conn_cnt ) ) peers->active_ws_conn_id = ws_conn_id;
811 0 : peers->open_ws_conn_cnt++;
812 0 : }
813 :
814 : static void
815 0 : fd_gui_peers_ws_conn_rr_shrink( fd_gui_peers_ctx_t * peers, ulong ws_conn_id ) {
816 0 : peers->open_ws_conn_cnt--;
817 :
818 0 : if( FD_UNLIKELY( peers->open_ws_conn_cnt && peers->active_ws_conn_id==ws_conn_id ) ) {
819 0 : for( ulong i=0UL; i<peers->max_ws_conn_cnt; i++ ) {
820 0 : ulong next_ws_conn_id = (ws_conn_id + i) % peers->max_ws_conn_cnt;
821 0 : if( FD_UNLIKELY( peers->client_viewports[ next_ws_conn_id ].connected ) ) {
822 0 : peers->active_ws_conn_id = next_ws_conn_id;
823 0 : break;
824 0 : }
825 0 : }
826 0 : }
827 0 : }
828 :
829 : static int
830 0 : fd_gui_peers_ws_conn_rr_advance( fd_gui_peers_ctx_t * peers, long now ) {
831 0 : if( FD_LIKELY( !peers->open_ws_conn_cnt || now <= peers->next_client_nanos ) ) return 0;
832 :
833 0 : for( ulong i=1UL; i<peers->max_ws_conn_cnt; i++ ) {
834 0 : ulong next_ws_conn_id = (peers->active_ws_conn_id + i) % peers->max_ws_conn_cnt;
835 0 : if( FD_UNLIKELY( peers->client_viewports[ next_ws_conn_id ].connected ) ) {
836 0 : peers->active_ws_conn_id = next_ws_conn_id;
837 0 : break;
838 0 : }
839 0 : }
840 0 : return 1;
841 0 : }
842 :
843 : int
844 0 : fd_gui_peers_poll( fd_gui_peers_ctx_t * peers, long now ) {
845 0 : int did_work = 0;
846 :
847 : /* update client viewports in a round-robin */
848 0 : if( FD_UNLIKELY( fd_gui_peers_ws_conn_rr_advance( peers, now ) ) ) {
849 0 : FD_TEST( peers->client_viewports[ peers->active_ws_conn_id ].connected );
850 0 : if( FD_LIKELY( peers->client_viewports[ peers->active_ws_conn_id ].row_cnt ) ) {
851 : /* broadcast the diff as cell updates */
852 0 : fd_gui_printf_peers_viewport_update( peers, peers->active_ws_conn_id );
853 0 : FD_TEST( !fd_http_server_ws_send( peers->http, peers->active_ws_conn_id ) );
854 :
855 : /* log the diff */
856 0 : fd_gui_peers_viewport_log( peers, peers->active_ws_conn_id );
857 0 : (void)fd_gui_peers_viewport_log;
858 :
859 : /* update client state to the latest viewport */
860 0 : fd_gui_peers_viewport_snap( peers, peers->active_ws_conn_id );
861 0 : }
862 :
863 0 : peers->next_client_nanos = now + ((FD_GUI_PEERS_WS_VIEWPORT_UPDATE_INTERVAL_MILLIS * 1000000L) / (long)peers->open_ws_conn_cnt);
864 0 : did_work = 1;
865 0 : }
866 :
867 0 : if( FD_UNLIKELY( now >= peers->next_metric_rate_update_nanos ) ) {
868 0 : for( fd_gui_peers_node_pubkey_map_iter_t iter = fd_gui_peers_node_pubkey_map_iter_init( peers->node_pubkey_map, peers->contact_info_table );
869 0 : !fd_gui_peers_node_pubkey_map_iter_done( iter, peers->node_pubkey_map, peers->contact_info_table );
870 0 : iter = fd_gui_peers_node_pubkey_map_iter_next( iter, peers->node_pubkey_map, peers->contact_info_table ) ) {
871 0 : fd_gui_peers_node_t * peer = fd_gui_peers_node_pubkey_map_iter_ele( iter, peers->node_pubkey_map, peers->contact_info_table );
872 :
873 0 : double window = (double)(now - (peers->next_metric_rate_update_nanos - (FD_GUI_PEERS_METRIC_RATE_UPDATE_INTERVAL_MILLIS * 1000000L)));
874 :
875 : /* optimization: no need to remove / re-insert if the rates haven't changed */
876 0 : int change = 0;
877 0 : for( ulong i=0UL; i<FD_METRICS_ENUM_GOSSIP_MESSAGE_CNT; i++ ) {
878 0 : fd_gui_peers_metric_rate_t * metric = &peer->gossvf_rx[ i ];
879 0 : long new_rate = (long)(((double)((long)metric->cur - (long)metric->ref) * 1e9 / window));
880 0 : if( FD_LIKELY( metric->rate == new_rate ) ) continue;
881 0 : change = 1;
882 0 : break;
883 0 : }
884 :
885 0 : if( !change) {
886 0 : for( ulong i=0UL; i<FD_METRICS_ENUM_GOSSIP_MESSAGE_CNT; i++ ) {
887 0 : fd_gui_peers_metric_rate_t * metric = &peer->gossip_tx[ i ];
888 0 : long new_rate = (long)(((double)((long)metric->cur - (long)metric->ref) * 1e9 / window));
889 0 : if( FD_LIKELY( metric->rate == new_rate ) ) continue;
890 0 : change = 1;
891 0 : break;
892 0 : }
893 0 : }
894 :
895 0 : if( !change ) continue;
896 :
897 : /* live_table */
898 0 : fd_gui_peers_live_table_ele_remove( peers->live_table, peer, peers->contact_info_table );
899 0 : for( ulong i=0UL; i<FD_METRICS_ENUM_GOSSIP_MESSAGE_CNT; i++ ) {
900 0 : fd_gui_peers_metric_rate_t * metric = &peer->gossvf_rx[ i ];
901 0 : metric->rate = (long)(((double)((long)metric->cur - (long)metric->ref) * 1e9 / window));
902 0 : metric->ref = metric->cur;
903 0 : }
904 :
905 0 : for( ulong i=0UL; i<FD_METRICS_ENUM_GOSSIP_MESSAGE_CNT; i++ ) {
906 0 : fd_gui_peers_metric_rate_t * metric = &peer->gossip_tx[ i ];
907 0 : metric->rate = (long)(((double)((long)metric->cur - (long)metric->ref) * 1e9 / window));
908 0 : metric->ref = metric->cur;
909 0 : }
910 0 : fd_gui_peers_live_table_ele_insert( peers->live_table, peer, peers->contact_info_table );
911 :
912 : /* bandwidth_tracking */
913 0 : fd_gui_peers_bandwidth_tracking_ele_remove( peers->bw_tracking, peer, peers->contact_info_table );
914 0 : peer->gossvf_rx_sum.rate = (long)(((double)((long)peer->gossvf_rx_sum.cur - (long)peer->gossvf_rx_sum.ref) * 1e9 / window));
915 0 : peer->gossvf_rx_sum.ref = peer->gossvf_rx_sum.cur;
916 :
917 0 : peer->gossip_tx_sum.rate = (long)(((double)((long)peer->gossip_tx_sum.cur - (long)peer->gossip_tx_sum.ref) * 1e9 / window));
918 0 : peer->gossip_tx_sum.ref = peer->gossip_tx_sum.cur;
919 0 : fd_gui_peers_bandwidth_tracking_ele_insert( peers->bw_tracking, peer, peers->contact_info_table );
920 0 : }
921 :
922 0 : peers->next_metric_rate_update_nanos = now + (FD_GUI_PEERS_METRIC_RATE_UPDATE_INTERVAL_MILLIS * 1000000L);
923 0 : did_work = 1;
924 0 : fd_gui_peers_live_table_verify( peers->live_table, peers->contact_info_table ); /* todo ... remove */
925 0 : }
926 :
927 0 : if( FD_LIKELY( now >= peers->next_gossip_stats_update_nanos ) ) {
928 0 : fd_gui_peers_gossip_stats_snap( peers, peers->gossip_stats, now );
929 0 : fd_gui_peers_printf_gossip_stats( peers );
930 0 : fd_http_server_ws_broadcast( peers->http );
931 :
932 0 : peers->next_gossip_stats_update_nanos = now + (FD_GUI_PEERS_GOSSIP_STATS_UPDATE_INTERVAL_MILLIS * 1000000L);
933 0 : did_work = 1;
934 0 : }
935 :
936 0 : return did_work;
937 0 : }
938 :
939 : void
940 0 : fd_gui_peers_ws_open( fd_gui_peers_ctx_t * peers, ulong ws_conn_id, long now ) {
941 0 : fd_gui_peers_ws_conn_rr_grow( peers, ws_conn_id );
942 0 : peers->client_viewports[ ws_conn_id ].connected = 1;
943 0 : peers->client_viewports[ ws_conn_id ].connected_time = now;
944 0 : peers->client_viewports[ ws_conn_id ].start_row = 0;
945 0 : peers->client_viewports[ ws_conn_id ].row_cnt = 0;
946 0 : fd_memcpy( peers->client_viewports[ ws_conn_id ].sort_key, &FD_GUI_PEERS_LIVE_TABLE_DEFAULT_SORT_KEY, sizeof(fd_gui_peers_live_table_sort_key_t) );
947 0 : }
948 :
949 : void
950 0 : fd_gui_peers_ws_close( fd_gui_peers_ctx_t * peers, ulong ws_conn_id ) {
951 0 : fd_gui_peers_live_table_sort_key_remove( peers->live_table, peers->client_viewports[ ws_conn_id ].sort_key );
952 0 : peers->client_viewports[ ws_conn_id ].connected = 0;
953 0 : fd_gui_peers_ws_conn_rr_shrink( peers, ws_conn_id );
954 0 : }
955 :
956 : #undef LOGGING
|