corosync 3.1.7
stats.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017-2020 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Authors: Christine Caulfield (ccaulfie@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the MontaVista Software, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <config.h>
36
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <fcntl.h>
40#include <stdint.h>
41#include <stddef.h>
42#include <unistd.h>
43#include <libknet.h>
44
45#include <qb/qblist.h>
46#include <qb/qbipcs.h>
47#include <qb/qbipc_common.h>
48
49#include <corosync/corodefs.h>
50#include <corosync/coroapi.h>
51#include <corosync/logsys.h>
52#include <corosync/icmap.h>
54
55#include "util.h"
56#include "ipcs_stats.h"
57#include "stats.h"
58
60
61static qb_map_t *stats_map;
62
63/* Structure of an element in the schedmiss array */
65 uint64_t timestamp;
66 float delay;
67};
68#define MAX_SCHEDMISS_EVENTS 10
69static struct schedmiss_entry schedmiss_event[MAX_SCHEDMISS_EVENTS];
70static unsigned int highest_schedmiss_event;
71
72#define SCHEDMISS_PREFIX "stats.schedmiss"
73
74/* Convert iterator number to text and a stats pointer */
77 const char *name;
78 const size_t offset;
80};
81
83 { STAT_PG, "msg_queue_avail", offsetof(totempg_stats_t, msg_queue_avail), ICMAP_VALUETYPE_UINT32},
84 { STAT_PG, "msg_reserved", offsetof(totempg_stats_t, msg_reserved), ICMAP_VALUETYPE_UINT32},
85};
87 { STAT_SRP, "orf_token_tx", offsetof(totemsrp_stats_t, orf_token_tx), ICMAP_VALUETYPE_UINT64},
88 { STAT_SRP, "orf_token_rx", offsetof(totemsrp_stats_t, orf_token_rx), ICMAP_VALUETYPE_UINT64},
89 { STAT_SRP, "memb_merge_detect_tx", offsetof(totemsrp_stats_t, memb_merge_detect_tx), ICMAP_VALUETYPE_UINT64},
90 { STAT_SRP, "memb_merge_detect_rx", offsetof(totemsrp_stats_t, memb_merge_detect_rx), ICMAP_VALUETYPE_UINT64},
91 { STAT_SRP, "memb_join_tx", offsetof(totemsrp_stats_t, memb_join_tx), ICMAP_VALUETYPE_UINT64},
92 { STAT_SRP, "memb_join_rx", offsetof(totemsrp_stats_t, memb_join_rx), ICMAP_VALUETYPE_UINT64},
93 { STAT_SRP, "mcast_tx", offsetof(totemsrp_stats_t, mcast_tx), ICMAP_VALUETYPE_UINT64},
94 { STAT_SRP, "mcast_retx", offsetof(totemsrp_stats_t, mcast_retx), ICMAP_VALUETYPE_UINT64},
95 { STAT_SRP, "mcast_rx", offsetof(totemsrp_stats_t, mcast_rx), ICMAP_VALUETYPE_UINT64},
96 { STAT_SRP, "memb_commit_token_tx", offsetof(totemsrp_stats_t, memb_commit_token_tx), ICMAP_VALUETYPE_UINT64},
97 { STAT_SRP, "memb_commit_token_rx", offsetof(totemsrp_stats_t, memb_commit_token_rx), ICMAP_VALUETYPE_UINT64},
98 { STAT_SRP, "token_hold_cancel_tx", offsetof(totemsrp_stats_t, token_hold_cancel_tx), ICMAP_VALUETYPE_UINT64},
99 { STAT_SRP, "token_hold_cancel_rx", offsetof(totemsrp_stats_t, token_hold_cancel_rx), ICMAP_VALUETYPE_UINT64},
100 { STAT_SRP, "operational_entered", offsetof(totemsrp_stats_t, operational_entered), ICMAP_VALUETYPE_UINT64},
101 { STAT_SRP, "operational_token_lost", offsetof(totemsrp_stats_t, operational_token_lost), ICMAP_VALUETYPE_UINT64},
102 { STAT_SRP, "gather_entered", offsetof(totemsrp_stats_t, gather_entered), ICMAP_VALUETYPE_UINT64},
103 { STAT_SRP, "gather_token_lost", offsetof(totemsrp_stats_t, gather_token_lost), ICMAP_VALUETYPE_UINT64},
104 { STAT_SRP, "commit_entered", offsetof(totemsrp_stats_t, commit_entered), ICMAP_VALUETYPE_UINT64},
105 { STAT_SRP, "commit_token_lost", offsetof(totemsrp_stats_t, commit_token_lost), ICMAP_VALUETYPE_UINT64},
106 { STAT_SRP, "recovery_entered", offsetof(totemsrp_stats_t, recovery_entered), ICMAP_VALUETYPE_UINT64},
107 { STAT_SRP, "recovery_token_lost", offsetof(totemsrp_stats_t, recovery_token_lost), ICMAP_VALUETYPE_UINT64},
108 { STAT_SRP, "consensus_timeouts", offsetof(totemsrp_stats_t, consensus_timeouts), ICMAP_VALUETYPE_UINT64},
109 { STAT_SRP, "rx_msg_dropped", offsetof(totemsrp_stats_t, rx_msg_dropped), ICMAP_VALUETYPE_UINT64},
110 { STAT_SRP, "time_since_token_last_received", offsetof(totemsrp_stats_t, time_since_token_last_received), ICMAP_VALUETYPE_UINT64},
111 { STAT_SRP, "continuous_gather", offsetof(totemsrp_stats_t, continuous_gather), ICMAP_VALUETYPE_UINT32},
112 { STAT_SRP, "continuous_sendmsg_failures", offsetof(totemsrp_stats_t, continuous_sendmsg_failures), ICMAP_VALUETYPE_UINT32},
113 { STAT_SRP, "firewall_enabled_or_nic_failure", offsetof(totemsrp_stats_t, firewall_enabled_or_nic_failure), ICMAP_VALUETYPE_UINT8},
114 { STAT_SRP, "mtt_rx_token", offsetof(totemsrp_stats_t, mtt_rx_token), ICMAP_VALUETYPE_UINT32},
115 { STAT_SRP, "avg_token_workload", offsetof(totemsrp_stats_t, avg_token_workload), ICMAP_VALUETYPE_UINT32},
116 { STAT_SRP, "avg_backlog_calc", offsetof(totemsrp_stats_t, avg_backlog_calc), ICMAP_VALUETYPE_UINT32},
117};
118
120 { STAT_KNET, "enabled", offsetof(struct knet_link_status, enabled), ICMAP_VALUETYPE_UINT8},
121 { STAT_KNET, "connected", offsetof(struct knet_link_status, connected), ICMAP_VALUETYPE_UINT8},
122 { STAT_KNET, "mtu", offsetof(struct knet_link_status, mtu), ICMAP_VALUETYPE_UINT32},
123 { STAT_KNET, "tx_data_packets", offsetof(struct knet_link_status, stats.tx_data_packets), ICMAP_VALUETYPE_UINT64},
124 { STAT_KNET, "rx_data_packets", offsetof(struct knet_link_status, stats.rx_data_packets), ICMAP_VALUETYPE_UINT64},
125 { STAT_KNET, "tx_data_bytes", offsetof(struct knet_link_status, stats.tx_data_bytes), ICMAP_VALUETYPE_UINT64},
126 { STAT_KNET, "rx_data_bytes", offsetof(struct knet_link_status, stats.rx_data_bytes), ICMAP_VALUETYPE_UINT64},
127 { STAT_KNET, "tx_ping_packets", offsetof(struct knet_link_status, stats.tx_ping_packets), ICMAP_VALUETYPE_UINT64},
128 { STAT_KNET, "rx_ping_packets", offsetof(struct knet_link_status, stats.rx_ping_packets), ICMAP_VALUETYPE_UINT64},
129 { STAT_KNET, "tx_ping_bytes", offsetof(struct knet_link_status, stats.tx_ping_bytes), ICMAP_VALUETYPE_UINT64},
130 { STAT_KNET, "rx_ping_bytes", offsetof(struct knet_link_status, stats.rx_ping_bytes), ICMAP_VALUETYPE_UINT64},
131 { STAT_KNET, "tx_pong_packets", offsetof(struct knet_link_status, stats.tx_pong_packets), ICMAP_VALUETYPE_UINT64},
132 { STAT_KNET, "rx_pong_packets", offsetof(struct knet_link_status, stats.rx_pong_packets), ICMAP_VALUETYPE_UINT64},
133 { STAT_KNET, "tx_pong_bytes", offsetof(struct knet_link_status, stats.tx_pong_bytes), ICMAP_VALUETYPE_UINT64},
134 { STAT_KNET, "rx_pong_bytes", offsetof(struct knet_link_status, stats.rx_pong_bytes), ICMAP_VALUETYPE_UINT64},
135 { STAT_KNET, "tx_pmtu_packets", offsetof(struct knet_link_status, stats.tx_pmtu_packets), ICMAP_VALUETYPE_UINT64},
136 { STAT_KNET, "rx_pmtu_packets", offsetof(struct knet_link_status, stats.rx_pmtu_packets), ICMAP_VALUETYPE_UINT64},
137 { STAT_KNET, "tx_pmtu_bytes", offsetof(struct knet_link_status, stats.tx_pmtu_bytes), ICMAP_VALUETYPE_UINT64},
138 { STAT_KNET, "rx_pmtu_bytes", offsetof(struct knet_link_status, stats.rx_pmtu_bytes), ICMAP_VALUETYPE_UINT64},
139 { STAT_KNET, "tx_total_packets", offsetof(struct knet_link_status, stats.tx_total_packets), ICMAP_VALUETYPE_UINT64},
140 { STAT_KNET, "rx_total_packets", offsetof(struct knet_link_status, stats.rx_total_packets), ICMAP_VALUETYPE_UINT64},
141 { STAT_KNET, "tx_total_bytes", offsetof(struct knet_link_status, stats.tx_total_bytes), ICMAP_VALUETYPE_UINT64},
142 { STAT_KNET, "rx_total_bytes", offsetof(struct knet_link_status, stats.rx_total_bytes), ICMAP_VALUETYPE_UINT64},
143 { STAT_KNET, "tx_total_errors", offsetof(struct knet_link_status, stats.tx_total_errors), ICMAP_VALUETYPE_UINT64},
144 { STAT_KNET, "rx_total_retries", offsetof(struct knet_link_status, stats.tx_total_retries), ICMAP_VALUETYPE_UINT64},
145 { STAT_KNET, "tx_pmtu_errors", offsetof(struct knet_link_status, stats.tx_pmtu_errors), ICMAP_VALUETYPE_UINT32},
146 { STAT_KNET, "tx_pmtu_retries", offsetof(struct knet_link_status, stats.tx_pmtu_retries), ICMAP_VALUETYPE_UINT32},
147 { STAT_KNET, "tx_ping_errors", offsetof(struct knet_link_status, stats.tx_ping_errors), ICMAP_VALUETYPE_UINT32},
148 { STAT_KNET, "tx_ping_retries", offsetof(struct knet_link_status, stats.tx_ping_retries), ICMAP_VALUETYPE_UINT32},
149 { STAT_KNET, "tx_pong_errors", offsetof(struct knet_link_status, stats.tx_pong_errors), ICMAP_VALUETYPE_UINT32},
150 { STAT_KNET, "tx_pong_retries", offsetof(struct knet_link_status, stats.tx_pong_retries), ICMAP_VALUETYPE_UINT32},
151 { STAT_KNET, "tx_data_errors", offsetof(struct knet_link_status, stats.tx_data_errors), ICMAP_VALUETYPE_UINT32},
152 { STAT_KNET, "tx_data_retries", offsetof(struct knet_link_status, stats.tx_data_retries), ICMAP_VALUETYPE_UINT32},
153 { STAT_KNET, "latency_min", offsetof(struct knet_link_status, stats.latency_min), ICMAP_VALUETYPE_UINT32},
154 { STAT_KNET, "latency_max", offsetof(struct knet_link_status, stats.latency_max), ICMAP_VALUETYPE_UINT32},
155 { STAT_KNET, "latency_ave", offsetof(struct knet_link_status, stats.latency_ave), ICMAP_VALUETYPE_UINT32},
156 { STAT_KNET, "latency_samples", offsetof(struct knet_link_status, stats.latency_samples), ICMAP_VALUETYPE_UINT32},
157 { STAT_KNET, "down_count", offsetof(struct knet_link_status, stats.down_count), ICMAP_VALUETYPE_UINT32},
158 { STAT_KNET, "up_count", offsetof(struct knet_link_status, stats.up_count), ICMAP_VALUETYPE_UINT32},
159};
161 { STAT_KNET_HANDLE, "tx_uncompressed_packets", offsetof(struct knet_handle_stats, tx_uncompressed_packets), ICMAP_VALUETYPE_UINT64},
162 { STAT_KNET_HANDLE, "tx_compressed_packets", offsetof(struct knet_handle_stats, tx_compressed_packets), ICMAP_VALUETYPE_UINT64},
163 { STAT_KNET_HANDLE, "tx_compressed_original_bytes", offsetof(struct knet_handle_stats, tx_compressed_original_bytes), ICMAP_VALUETYPE_UINT64},
164 { STAT_KNET_HANDLE, "tx_compressed_size_bytes", offsetof(struct knet_handle_stats, tx_compressed_size_bytes), ICMAP_VALUETYPE_UINT64},
165 { STAT_KNET_HANDLE, "tx_compress_time_min", offsetof(struct knet_handle_stats, tx_compress_time_min), ICMAP_VALUETYPE_UINT64},
166 { STAT_KNET_HANDLE, "tx_compress_time_max", offsetof(struct knet_handle_stats, tx_compress_time_max), ICMAP_VALUETYPE_UINT64},
167 { STAT_KNET_HANDLE, "tx_compress_time_ave", offsetof(struct knet_handle_stats, tx_compress_time_ave), ICMAP_VALUETYPE_UINT64},
168 { STAT_KNET_HANDLE, "rx_compressed_packets", offsetof(struct knet_handle_stats, rx_compressed_packets), ICMAP_VALUETYPE_UINT64},
169 { STAT_KNET_HANDLE, "rx_compressed_original_bytes", offsetof(struct knet_handle_stats, rx_compressed_original_bytes), ICMAP_VALUETYPE_UINT64},
170 { STAT_KNET_HANDLE, "rx_compressed_size_bytes", offsetof(struct knet_handle_stats, rx_compressed_size_bytes), ICMAP_VALUETYPE_UINT64},
171 { STAT_KNET_HANDLE, "rx_compress_time_min", offsetof(struct knet_handle_stats, rx_compress_time_min), ICMAP_VALUETYPE_UINT64},
172 { STAT_KNET_HANDLE, "rx_compress_time_max", offsetof(struct knet_handle_stats, rx_compress_time_max), ICMAP_VALUETYPE_UINT64},
173 { STAT_KNET_HANDLE, "rx_compress_time_ave", offsetof(struct knet_handle_stats, rx_compress_time_ave), ICMAP_VALUETYPE_UINT64},
174 { STAT_KNET_HANDLE, "tx_crypt_time_min", offsetof(struct knet_handle_stats, tx_crypt_time_min), ICMAP_VALUETYPE_UINT64},
175 { STAT_KNET_HANDLE, "tx_crypt_time_max", offsetof(struct knet_handle_stats, tx_crypt_time_max), ICMAP_VALUETYPE_UINT64},
176 { STAT_KNET_HANDLE, "tx_crypt_time_ave", offsetof(struct knet_handle_stats, tx_crypt_time_ave), ICMAP_VALUETYPE_UINT64},
177 { STAT_KNET_HANDLE, "tx_crypt_byte_overhead", offsetof(struct knet_handle_stats, tx_crypt_byte_overhead), ICMAP_VALUETYPE_UINT64},
178 { STAT_KNET_HANDLE, "tx_crypt_packets", offsetof(struct knet_handle_stats, tx_crypt_packets), ICMAP_VALUETYPE_UINT64},
179 { STAT_KNET_HANDLE, "rx_crypt_time_min", offsetof(struct knet_handle_stats, rx_crypt_time_min), ICMAP_VALUETYPE_UINT64},
180 { STAT_KNET_HANDLE, "rx_crypt_time_max", offsetof(struct knet_handle_stats, rx_crypt_time_max), ICMAP_VALUETYPE_UINT64},
181 { STAT_KNET_HANDLE, "rx_crypt_time_ave", offsetof(struct knet_handle_stats, rx_crypt_time_ave), ICMAP_VALUETYPE_UINT64},
182 { STAT_KNET_HANDLE, "rx_crypt_packets", offsetof(struct knet_handle_stats, rx_crypt_packets), ICMAP_VALUETYPE_UINT64},
183};
184
186 { STAT_IPCSC, "queueing", offsetof(struct ipcs_conn_stats, cnx.queuing), ICMAP_VALUETYPE_INT32},
187 { STAT_IPCSC, "queued", offsetof(struct ipcs_conn_stats, cnx.queued), ICMAP_VALUETYPE_UINT32},
188 { STAT_IPCSC, "invalid_request", offsetof(struct ipcs_conn_stats, cnx.invalid_request), ICMAP_VALUETYPE_UINT64},
189 { STAT_IPCSC, "overload", offsetof(struct ipcs_conn_stats, cnx.overload), ICMAP_VALUETYPE_UINT64},
190 { STAT_IPCSC, "sent", offsetof(struct ipcs_conn_stats, cnx.sent), ICMAP_VALUETYPE_UINT32},
191 { STAT_IPCSC, "procname", offsetof(struct ipcs_conn_stats, cnx.proc_name), ICMAP_VALUETYPE_STRING},
192 { STAT_IPCSC, "requests", offsetof(struct ipcs_conn_stats, conn.requests), ICMAP_VALUETYPE_UINT64},
193 { STAT_IPCSC, "responses", offsetof(struct ipcs_conn_stats, conn.responses), ICMAP_VALUETYPE_UINT64},
194 { STAT_IPCSC, "dispatched", offsetof(struct ipcs_conn_stats, conn.events), ICMAP_VALUETYPE_UINT64},
195 { STAT_IPCSC, "send_retries", offsetof(struct ipcs_conn_stats, conn.send_retries), ICMAP_VALUETYPE_UINT64},
196 { STAT_IPCSC, "recv_retries", offsetof(struct ipcs_conn_stats, conn.recv_retries), ICMAP_VALUETYPE_UINT64},
197 { STAT_IPCSC, "flow_control", offsetof(struct ipcs_conn_stats, conn.flow_control_state), ICMAP_VALUETYPE_UINT32},
198 { STAT_IPCSC, "flow_control_count", offsetof(struct ipcs_conn_stats, conn.flow_control_count), ICMAP_VALUETYPE_UINT64},
199};
201 { STAT_IPCSG, "global.active", offsetof(struct ipcs_global_stats, active), ICMAP_VALUETYPE_UINT64},
202 { STAT_IPCSG, "global.closed", offsetof(struct ipcs_global_stats, closed), ICMAP_VALUETYPE_UINT64},
203};
205 { STAT_SCHEDMISS, "timestamp", offsetof(struct schedmiss_entry, timestamp), ICMAP_VALUETYPE_UINT64},
206 { STAT_SCHEDMISS, "delay", offsetof(struct schedmiss_entry, delay), ICMAP_VALUETYPE_FLOAT},
207};
208
209#define NUM_PG_STATS (sizeof(cs_pg_stats) / sizeof(struct cs_stats_conv))
210#define NUM_SRP_STATS (sizeof(cs_srp_stats) / sizeof(struct cs_stats_conv))
211#define NUM_KNET_STATS (sizeof(cs_knet_stats) / sizeof(struct cs_stats_conv))
212#define NUM_KNET_HANDLE_STATS (sizeof(cs_knet_handle_stats) / sizeof(struct cs_stats_conv))
213#define NUM_IPCSC_STATS (sizeof(cs_ipcs_conn_stats) / sizeof(struct cs_stats_conv))
214#define NUM_IPCSG_STATS (sizeof(cs_ipcs_global_stats) / sizeof(struct cs_stats_conv))
215
216/* What goes in the trie */
218 char *key_name;
220};
221
222/* One of these per tracker */
224{
225 char *key_name;
227 int32_t events;
229 uint64_t old_value;
230 struct qb_list_head list;
231};
232QB_LIST_DECLARE (stats_tracker_list_head);
233static const struct corosync_api_v1 *api;
234
235static void stats_map_set_value(struct cs_stats_conv *conv,
236 void *stat_array,
237 void *value,
238 size_t *value_len,
240{
241 if (value_len) {
242 *value_len = icmap_get_valuetype_len(conv->value_type);
243 }
244 if (type) {
245 *type = conv->value_type;
246 if ((*type == ICMAP_VALUETYPE_STRING) && value_len && stat_array) {
247 *value_len = strlen((char *)(stat_array) + conv->offset)+1;
248 }
249 }
250 if (value) {
251 assert(value_len != NULL);
252
253 memcpy(value, (char *)(stat_array) + conv->offset, *value_len);
254 }
255}
256
257static void stats_add_entry(const char *key, struct cs_stats_conv *cs_conv)
258{
259 struct stats_item *item = malloc(sizeof(struct stats_item));
260
261 if (item) {
262 item->cs_conv = cs_conv;
263 item->key_name = strdup(key);
264 qb_map_put(stats_map, item->key_name, item);
265 }
266}
267static void stats_rm_entry(const char *key)
268{
269 struct stats_item *item = qb_map_get(stats_map, key);
270
271 if (item) {
272 qb_map_rm(stats_map, item->key_name);
273 /* Structures freed in callback below */
274 }
275}
276
277static void stats_map_free_cb(uint32_t event,
278 char* key, void* old_value,
279 void* value, void* user_data)
280{
281 struct stats_item *item = (struct stats_item *)old_value;
282
283 if (item) {
284 free(item->key_name);
285 free(item);
286 }
287}
288
289cs_error_t stats_map_init(const struct corosync_api_v1 *corosync_api)
290{
291 int i;
293 int32_t err;
294
295 api = corosync_api;
296
297 stats_map = qb_trie_create();
298 if (!stats_map) {
299 return CS_ERR_INIT;
300 }
301
302 /* Populate the static portions of the trie */
303 for (i = 0; i<NUM_PG_STATS; i++) {
304 sprintf(param, "stats.pg.%s", cs_pg_stats[i].name);
305 stats_add_entry(param, &cs_pg_stats[i]);
306 }
307 for (i = 0; i<NUM_SRP_STATS; i++) {
308 sprintf(param, "stats.srp.%s", cs_srp_stats[i].name);
309 stats_add_entry(param, &cs_srp_stats[i]);
310 }
311 for (i = 0; i<NUM_IPCSG_STATS; i++) {
312 sprintf(param, "stats.ipcs.%s", cs_ipcs_global_stats[i].name);
313 stats_add_entry(param, &cs_ipcs_global_stats[i]);
314 }
315
316 /* KNET, IPCS & SCHEDMISS stats are added when appropriate */
317
318
319 /* Call us when we can free things */
320 err = qb_map_notify_add(stats_map, NULL, stats_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
321
322 return (qb_to_cs_error(err));
323}
324
326 void *value,
327 size_t *value_len,
329{
330 struct cs_stats_conv *statinfo;
331 struct stats_item *item;
332 totempg_stats_t *pg_stats;
333 struct knet_link_status link_status;
336 struct knet_handle_stats knet_handle_stats;
337 int res;
338 int nodeid;
339 int link_no;
340 int service_id;
341 uint32_t pid;
342 unsigned int sm_event;
343 char *sm_type;
344 void *conn_ptr;
345
346 item = qb_map_get(stats_map, key_name);
347 if (!item) {
348 return CS_ERR_NOT_EXIST;
349 }
350
351 statinfo = item->cs_conv;
352 switch (statinfo->type) {
353 case STAT_PG:
354 pg_stats = api->totem_get_stats();
355 stats_map_set_value(statinfo, pg_stats, value, value_len, type);
356 break;
357 case STAT_SRP:
358 pg_stats = api->totem_get_stats();
359 stats_map_set_value(statinfo, pg_stats->srp, value, value_len, type);
360 break;
361 case STAT_KNET_HANDLE:
362 res = totemknet_handle_get_stats(&knet_handle_stats);
363 if (res != CS_OK) {
364 return res;
365 }
366 stats_map_set_value(statinfo, &knet_handle_stats, value, value_len, type);
367 break;
368 case STAT_KNET:
369 if (sscanf(key_name, "stats.knet.node%d.link%d", &nodeid, &link_no) != 2) {
370 return CS_ERR_NOT_EXIST;
371 }
372
373 /* Validate node & link IDs */
374 if (nodeid <= 0 || nodeid > KNET_MAX_HOST ||
375 link_no < 0 || link_no > KNET_MAX_LINK) {
376 return CS_ERR_NOT_EXIST;
377 }
378
379 /* Always get the latest stats */
380 res = totemknet_link_get_status((knet_node_id_t)nodeid, (uint8_t)link_no, &link_status);
381 if (res != CS_OK) {
382 return CS_ERR_LIBRARY;
383 }
384 stats_map_set_value(statinfo, &link_status, value, value_len, type);
385 break;
386 case STAT_IPCSC:
387 if (sscanf(key_name, "stats.ipcs.service%d.%d.%p", &service_id, &pid, &conn_ptr) != 3) {
388 return CS_ERR_NOT_EXIST;
389 }
390 res = cs_ipcs_get_conn_stats(service_id, pid, conn_ptr, &ipcs_conn_stats);
391 if (res != CS_OK) {
392 return res;
393 }
394 stats_map_set_value(statinfo, &ipcs_conn_stats, value, value_len, type);
395 break;
396 case STAT_IPCSG:
398 stats_map_set_value(statinfo, &ipcs_global_stats, value, value_len, type);
399 break;
400 case STAT_SCHEDMISS:
401 if (sscanf(key_name, SCHEDMISS_PREFIX ".%d", &sm_event) != 1) {
402 return CS_ERR_NOT_EXIST;
403 }
404
405 sm_type = strrchr(key_name, '.');
406 if (sm_type == NULL) {
407 return CS_ERR_NOT_EXIST;
408 }
409 sm_type++;
410
411 if (strcmp(sm_type, "timestamp") == 0) {
412 memcpy(value, &schedmiss_event[sm_event].timestamp, sizeof(uint64_t));
413 *value_len = sizeof(uint64_t);
415 }
416 if (strcmp(sm_type, "delay") == 0) {
417 memcpy(value, &schedmiss_event[sm_event].delay, sizeof(float));
418 *value_len = sizeof(float);
420 }
421 break;
422 default:
423 return CS_ERR_LIBRARY;
424 }
425 return CS_OK;
426}
427
428static void schedmiss_clear_stats(void)
429{
430 int i;
432
433 for (i=0; i<MAX_SCHEDMISS_EVENTS; i++) {
434 if (i < highest_schedmiss_event) {
435 sprintf(param, SCHEDMISS_PREFIX ".%i.timestamp", i);
436 stats_rm_entry(param);
437 sprintf(param, SCHEDMISS_PREFIX ".%i.delay", i);
438 stats_rm_entry(param);
439 }
440 schedmiss_event[i].timestamp = (uint64_t)0LL;
441 schedmiss_event[i].delay = 0.0f;
442 }
443 highest_schedmiss_event = 0;
444}
445
446/* Called from main.c */
447void stats_add_schedmiss_event(uint64_t timestamp, float delay)
448{
450 int i;
451
452 /* Move 'em all up */
453 for (i=MAX_SCHEDMISS_EVENTS-2; i>=0; i--) {
454 schedmiss_event[i+1].timestamp = schedmiss_event[i].timestamp;
455 schedmiss_event[i+1].delay = schedmiss_event[i].delay;
456 }
457
458 /* New entries are always at the front */
459 schedmiss_event[0].timestamp = timestamp;
460 schedmiss_event[0].delay = delay;
461
462 /* If we've not run off the end then add an entry in the trie for the new 'end' one */
463 if (highest_schedmiss_event < MAX_SCHEDMISS_EVENTS) {
464 sprintf(param, SCHEDMISS_PREFIX ".%i.timestamp", highest_schedmiss_event);
465 stats_add_entry(param, &cs_schedmiss_stats[0]);
466 sprintf(param, SCHEDMISS_PREFIX ".%i.delay", highest_schedmiss_event);
467 stats_add_entry(param, &cs_schedmiss_stats[1]);
468 highest_schedmiss_event++;
469 }
470 /* Notifications get sent by the stats_updater */
471}
472
473#define STATS_CLEAR "stats.clear."
474#define STATS_CLEAR_KNET "stats.clear.knet"
475#define STATS_CLEAR_IPC "stats.clear.ipc"
476#define STATS_CLEAR_TOTEM "stats.clear.totem"
477#define STATS_CLEAR_ALL "stats.clear.all"
478#define STATS_CLEAR_SCHEDMISS "stats.clear.schedmiss"
479
480cs_error_t stats_map_set(const char *key_name,
481 const void *value,
482 size_t value_len,
484{
485 int cleared = 0;
486
487 if (strncmp(key_name, STATS_CLEAR_KNET, strlen(STATS_CLEAR_KNET)) == 0) {
489 cleared = 1;
490 }
491 if (strncmp(key_name, STATS_CLEAR_IPC, strlen(STATS_CLEAR_IPC)) == 0) {
493 cleared = 1;
494 }
495 if (strncmp(key_name, STATS_CLEAR_TOTEM, strlen(STATS_CLEAR_TOTEM)) == 0) {
497 cleared = 1;
498 }
499 if (strncmp(key_name, STATS_CLEAR_SCHEDMISS, strlen(STATS_CLEAR_SCHEDMISS)) == 0) {
500 schedmiss_clear_stats();
501 cleared = 1;
502 }
503 if (strncmp(key_name, STATS_CLEAR_ALL, strlen(STATS_CLEAR_ALL)) == 0) {
506 schedmiss_clear_stats();
507 cleared = 1;
508 }
509 if (!cleared) {
511 }
512 return CS_OK;
513}
514
515cs_error_t stats_map_adjust_int(const char *key_name, int32_t step)
516{
518}
519
520cs_error_t stats_map_delete(const char *key_name)
521{
523}
524
525int stats_map_is_key_ro(const char *key_name)
526{
527 /* It's all read-only apart from the 'clear' destinations */
528 if (strncmp(key_name, STATS_CLEAR, strlen(STATS_CLEAR)) == 0) {
529 return 0;
530 } else {
531 return 1;
532 }
533}
534
536{
537 return (qb_map_pref_iter_create(stats_map, prefix));
538}
539
540
541const char *stats_map_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
542{
543 const char *res;
544 struct stats_item *item;
545
546 res = qb_map_iter_next(iter, (void **)&item);
547 if (res == NULL) {
548 return (res);
549 }
550 stats_map_set_value(item->cs_conv, NULL, NULL, value_len, type);
551
552 return res;
553}
554
556{
557 qb_map_iter_free(iter);
558}
559
560
562{
563 struct cs_stats_tracker *tracker;
564 struct qb_list_head *iter;
565 cs_error_t res;
566 size_t value_len;
568 uint64_t value;
569 struct icmap_notify_value new_val;
570 struct icmap_notify_value old_val;
571
572 qb_list_for_each(iter, &stats_tracker_list_head) {
573
574 tracker = qb_list_entry(iter, struct cs_stats_tracker, list);
575 if (tracker->events & ICMAP_TRACK_PREFIX || !tracker->key_name ) {
576 continue;
577 }
578
579 res = stats_map_get(tracker->key_name,
580 &value, &value_len, &type);
581
582 /* Check if it has changed */
583 if ((res == CS_OK) && (memcmp(&value, &tracker->old_value, value_len) != 0)) {
584
585 old_val.type = new_val.type = type;
586 old_val.len = new_val.len = value_len;
587 old_val.data = new_val.data = &value;
588
589 tracker->notify_fn(ICMAP_TRACK_MODIFY, tracker->key_name,
590 old_val, new_val, tracker->user_data);
591
592 memcpy(&tracker->old_value, &value, value_len);
593 }
594 }
595}
596
597
598/* Callback from libqb when a key is added/removed */
599static void stats_map_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
600{
601 struct cs_stats_tracker *tracker = user_data;
602 struct icmap_notify_value new_val;
603 struct icmap_notify_value old_val;
604 char new_value[64];
605
606 if (value == NULL && old_value == NULL) {
607 return ;
608 }
609
610 /* Ignore schedmiss trackers as the values are read from the circular buffer */
611 if (strncmp(key, SCHEDMISS_PREFIX, strlen(SCHEDMISS_PREFIX)) == 0 ) {
612 return ;
613 }
614
615 new_val.data = new_value;
616 if (stats_map_get(key,
617 &new_value,
618 &new_val.len,
619 &new_val.type) != CS_OK) {
620 log_printf(LOGSYS_LEVEL_WARNING, "get value of notified key %s failed", key);
621 return ;
622 }
623
624 /* We don't know what the old value was
625 but as this only tracks ADD & DELETE I'm not worried
626 about it */
627 memcpy(&old_val, &new_val, sizeof(new_val));
628
629 tracker->notify_fn(icmap_qbtt_to_tt(event),
630 key,
631 new_val,
632 old_val,
633 tracker->user_data);
634
635}
636
637cs_error_t stats_map_track_add(const char *key_name,
638 int32_t track_type,
639 icmap_notify_fn_t notify_fn,
640 void *user_data,
642{
643 struct cs_stats_tracker *tracker;
644 size_t value_len;
646 cs_error_t err;
647
648 /* We can track adding or deleting a key under a prefix */
649 if ((track_type & ICMAP_TRACK_PREFIX) &&
650 (!(track_type & ICMAP_TRACK_DELETE) ||
651 !(track_type & ICMAP_TRACK_ADD))) {
653 }
654
655 tracker = malloc(sizeof(struct cs_stats_tracker));
656 if (!tracker) {
657 return CS_ERR_NO_MEMORY;
658 }
659
660 tracker->notify_fn = notify_fn;
661 tracker->user_data = user_data;
662 tracker->events = track_type;
663 if (key_name) {
664 tracker->key_name = strdup(key_name);
665 if (!tracker->key_name) {
666 free(tracker);
667 return CS_ERR_NO_MEMORY;
668 }
669 /* Get initial value */
670 if (stats_map_get(tracker->key_name,
671 &tracker->old_value, &value_len, &type) != CS_OK) {
672 tracker->old_value = 0ULL;
673 }
674 } else {
675 tracker->key_name = NULL;
676 tracker->old_value = 0ULL;
677 }
678
679 /* Add/delete trackers can use the qb_map tracking */
680 if ((track_type & ICMAP_TRACK_ADD) ||
681 (track_type & ICMAP_TRACK_DELETE)) {
682 err = qb_map_notify_add(stats_map, tracker->key_name,
683 stats_map_notify_fn,
684 icmap_tt_to_qbtt(track_type),
685 tracker);
686 if (err != 0) {
687 log_printf(LOGSYS_LEVEL_ERROR, "creating stats tracker %s failed. %d\n", tracker->key_name, err);
688 free(tracker->key_name);
689 free(tracker);
690 return (qb_to_cs_error(err));
691 }
692 }
693
694 qb_list_add (&tracker->list, &stats_tracker_list_head);
695
696 *icmap_track = (icmap_track_t)tracker;
697 return CS_OK;
698}
699
701{
702 struct cs_stats_tracker *tracker = (struct cs_stats_tracker *)icmap_track;
703 int err;
704
705 if ((tracker->events & ICMAP_TRACK_ADD) ||
706 (tracker->events & ICMAP_TRACK_DELETE)) {
707 err = qb_map_notify_del_2(stats_map,
708 tracker->key_name, stats_map_notify_fn,
709 icmap_tt_to_qbtt(tracker->events), tracker);
710 if (err) {
711 log_printf(LOGSYS_LEVEL_ERROR, "deleting tracker %s failed. %d\n", tracker->key_name, err);
712 }
713 }
714
715 qb_list_del(&tracker->list);
716 free(tracker->key_name);
717 free(tracker);
718
719 return CS_OK;
720}
721
723{
724 struct cs_stats_tracker *tracker = (struct cs_stats_tracker *)icmap_track;
725
726 return tracker->user_data;
727}
728
729/* Called from totemknet to add/remove keys from our map */
730void stats_knet_add_member(knet_node_id_t nodeid, uint8_t link_no)
731{
732 int i;
734
735 for (i = 0; i<NUM_KNET_STATS; i++) {
736 sprintf(param, "stats.knet.node%d.link%d.%s", nodeid, link_no, cs_knet_stats[i].name);
737 stats_add_entry(param, &cs_knet_stats[i]);
738 }
739}
740void stats_knet_del_member(knet_node_id_t nodeid, uint8_t link_no)
741{
742 int i;
744
745 for (i = 0; i<NUM_KNET_STATS; i++) {
746 sprintf(param, "stats.knet.node%d.link%d.%s", nodeid, link_no, cs_knet_stats[i].name);
747 stats_rm_entry(param);
748 }
749}
750
751/* This is separated out from stats_map_init() because we don't know whether
752 knet is in use until much later in the startup */
754{
755 int i;
757
758 for (i = 0; i<NUM_KNET_HANDLE_STATS; i++) {
759 sprintf(param, "stats.knet.handle.%s", cs_knet_handle_stats[i].name);
760 stats_add_entry(param, &cs_knet_handle_stats[i]);
761 }
762}
763
764/* Called from ipc_glue to add/remove keys from our map */
765void stats_ipcs_add_connection(int service_id, uint32_t pid, void *ptr)
766{
767 int i;
769
770 for (i = 0; i<NUM_IPCSC_STATS; i++) {
771 sprintf(param, "stats.ipcs.service%d.%d.%p.%s", service_id, pid, ptr, cs_ipcs_conn_stats[i].name);
772 stats_add_entry(param, &cs_ipcs_conn_stats[i]);
773 }
774}
775void stats_ipcs_del_connection(int service_id, uint32_t pid, void *ptr)
776{
777 int i;
779
780 for (i = 0; i<NUM_IPCSC_STATS; i++) {
781 sprintf(param, "stats.ipcs.service%d.%d.%p.%s", service_id, pid, ptr, cs_ipcs_conn_stats[i].name);
782 stats_rm_entry(param);
783 }
784}
unsigned int nodeid
Definition: coroapi.h:0
cs_error_t qb_to_cs_error(int result)
qb_to_cs_error
cs_error_t
The cs_error_t enum.
Definition: corotypes.h:98
@ CS_ERR_NO_MEMORY
Definition: corotypes.h:106
@ CS_OK
Definition: corotypes.h:99
@ CS_ERR_LIBRARY
Definition: corotypes.h:100
@ CS_ERR_NOT_EXIST
Definition: corotypes.h:110
@ CS_ERR_INIT
Definition: corotypes.h:102
@ CS_ERR_NOT_SUPPORTED
Definition: corotypes.h:117
struct cmap_map stats_map
Definition: exec/cmap.c:112
uint8_t param
uint32_t value
int32_t icmap_tt_to_qbtt(int32_t track_type)
Definition: icmap.c:127
#define ICMAP_TRACK_MODIFY
Definition: icmap.h:78
icmap_value_types_t
Possible types of value.
Definition: icmap.h:58
@ ICMAP_VALUETYPE_UINT64
Definition: icmap.h:66
@ ICMAP_VALUETYPE_UINT8
Definition: icmap.h:60
@ ICMAP_VALUETYPE_UINT32
Definition: icmap.h:64
@ ICMAP_VALUETYPE_STRING
Definition: icmap.h:69
@ ICMAP_VALUETYPE_FLOAT
Definition: icmap.h:67
@ ICMAP_VALUETYPE_INT32
Definition: icmap.h:63
#define ICMAP_TRACK_DELETE
Definition: icmap.h:77
int32_t icmap_qbtt_to_tt(int32_t track_type)
Definition: icmap.c:150
#define ICMAP_TRACK_PREFIX
Whole prefix is tracked, instead of key only (so "totem." tracking means that "totem....
Definition: icmap.h:85
size_t icmap_get_valuetype_len(icmap_value_types_t type)
Definition: icmap.c:306
void(* icmap_notify_fn_t)(int32_t event, const char *key_name, struct icmap_notify_value new_value, struct icmap_notify_value old_value, void *user_data)
Prototype for notify callback function.
Definition: icmap.h:103
qb_map_iter_t * icmap_iter_t
Itterator type.
Definition: icmap.h:123
struct icmap_track * icmap_track_t
Track type.
Definition: icmap.h:128
#define ICMAP_KEYNAME_MAXLEN
Maximum length of key in icmap.
Definition: icmap.h:48
#define ICMAP_TRACK_ADD
Definition: icmap.h:76
cs_error_t cs_ipcs_get_conn_stats(int service_id, uint32_t pid, void *conn_ptr, struct ipcs_conn_stats *ipcs_stats)
Definition: ipc_glue.c:675
void cs_ipcs_get_global_stats(struct ipcs_global_stats *ipcs_stats)
Definition: ipc_glue.c:670
void cs_ipcs_clear_stats()
Definition: ipc_glue.c:709
#define LOGSYS_LEVEL_ERROR
Definition: logsys.h:72
#define log_printf(level, format, args...)
Definition: logsys.h:332
#define LOGSYS_LEVEL_WARNING
Definition: logsys.h:73
void * user_data
Definition: sam.c:127
#define NUM_PG_STATS
Definition: stats.c:209
void stats_knet_del_member(knet_node_id_t nodeid, uint8_t link_no)
Definition: stats.c:740
struct cs_stats_conv cs_schedmiss_stats[]
Definition: stats.c:204
void stats_ipcs_add_connection(int service_id, uint32_t pid, void *ptr)
Definition: stats.c:765
#define STATS_CLEAR_IPC
Definition: stats.c:475
void stats_knet_add_handle(void)
Definition: stats.c:753
const char * stats_map_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
Definition: stats.c:541
QB_LIST_DECLARE(stats_tracker_list_head)
#define STATS_CLEAR_TOTEM
Definition: stats.c:476
void stats_add_schedmiss_event(uint64_t timestamp, float delay)
Definition: stats.c:447
void * stats_map_track_get_user_data(icmap_track_t icmap_track)
Definition: stats.c:722
struct cs_stats_conv cs_ipcs_conn_stats[]
Definition: stats.c:185
cs_error_t stats_map_delete(const char *key_name)
Definition: stats.c:520
cs_error_t stats_map_track_delete(icmap_track_t icmap_track)
Definition: stats.c:700
#define STATS_CLEAR
Definition: stats.c:473
#define NUM_SRP_STATS
Definition: stats.c:210
#define NUM_KNET_HANDLE_STATS
Definition: stats.c:212
#define SCHEDMISS_PREFIX
Definition: stats.c:72
icmap_iter_t stats_map_iter_init(const char *prefix)
Definition: stats.c:535
struct cs_stats_conv cs_knet_stats[]
Definition: stats.c:119
#define NUM_IPCSG_STATS
Definition: stats.c:214
struct cs_stats_conv cs_srp_stats[]
Definition: stats.c:86
void stats_trigger_trackers()
Definition: stats.c:561
#define NUM_KNET_STATS
Definition: stats.c:211
int stats_map_is_key_ro(const char *key_name)
Definition: stats.c:525
#define NUM_IPCSC_STATS
Definition: stats.c:213
void stats_ipcs_del_connection(int service_id, uint32_t pid, void *ptr)
Definition: stats.c:775
#define STATS_CLEAR_KNET
Definition: stats.c:474
cs_error_t stats_map_set(const char *key_name, const void *value, size_t value_len, icmap_value_types_t type)
Definition: stats.c:480
void stats_map_iter_finalize(icmap_iter_t iter)
Definition: stats.c:555
struct cs_stats_conv cs_pg_stats[]
Definition: stats.c:82
cs_error_t stats_map_get(const char *key_name, void *value, size_t *value_len, icmap_value_types_t *type)
Definition: stats.c:325
#define STATS_CLEAR_SCHEDMISS
Definition: stats.c:478
cs_error_t stats_map_adjust_int(const char *key_name, int32_t step)
Definition: stats.c:515
struct cs_stats_conv cs_ipcs_global_stats[]
Definition: stats.c:200
LOGSYS_DECLARE_SUBSYS("STATS")
cs_error_t stats_map_track_add(const char *key_name, int32_t track_type, icmap_notify_fn_t notify_fn, void *user_data, icmap_track_t *icmap_track)
Definition: stats.c:637
void stats_knet_add_member(knet_node_id_t nodeid, uint8_t link_no)
Definition: stats.c:730
struct cs_stats_conv cs_knet_handle_stats[]
Definition: stats.c:160
#define STATS_CLEAR_ALL
Definition: stats.c:477
cs_error_t stats_map_init(const struct corosync_api_v1 *corosync_api)
Definition: stats.c:289
#define MAX_SCHEDMISS_EVENTS
Definition: stats.c:68
The corosync_api_v1 struct.
Definition: coroapi.h:225
void *(* totem_get_stats)(void)
Definition: coroapi.h:435
const char * name
Definition: stats.c:77
const size_t offset
Definition: stats.c:78
@ STAT_IPCSG
Definition: stats.c:76
@ STAT_SRP
Definition: stats.c:76
@ STAT_SCHEDMISS
Definition: stats.c:76
@ STAT_KNET
Definition: stats.c:76
@ STAT_KNET_HANDLE
Definition: stats.c:76
@ STAT_IPCSC
Definition: stats.c:76
enum cs_stats_conv::@10 type
const icmap_value_types_t value_type
Definition: stats.c:79
icmap_notify_fn_t notify_fn
Definition: stats.c:228
struct qb_list_head list
Definition: stats.c:230
int32_t events
Definition: stats.c:227
char * key_name
Definition: stats.c:225
uint64_t old_value
Definition: stats.c:229
void * user_data
Definition: stats.c:226
Structure passed as new_value and old_value in change callback.
Definition: icmap.h:91
icmap_value_types_t type
Definition: icmap.h:92
const void * data
Definition: icmap.h:94
size_t len
Definition: icmap.h:93
Definition: stats.c:64
float delay
Definition: stats.c:66
uint64_t timestamp
Definition: stats.c:65
char * key_name
Definition: stats.c:218
struct cs_stats_conv * cs_conv
Definition: stats.c:219
totemsrp_stats_t * srp
Definition: totemstats.h:96
char type
Definition: totem.h:2
#define TOTEMPG_STATS_CLEAR_TOTEM
Definition: totemstats.h:115
#define TOTEMPG_STATS_CLEAR_TRANSPORT
Definition: totemstats.h:116
int totemknet_handle_get_stats(struct knet_handle_stats *stats)
Definition: totemknet.c:1855
int totemknet_link_get_status(knet_node_id_t node, uint8_t link, struct knet_link_status *status)
Definition: totemknet.c:1818
void totempg_stats_clear(int flags)
Definition: totempg.c:1576