corosync  3.0.1
stats.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 
61 static qb_map_t *stats_map;
62 
63 /* Convert iterator number to text and a stats pointer */
64 struct cs_stats_conv {
66  const char *name;
67  const size_t offset;
69 };
70 
71 struct cs_stats_conv cs_pg_stats[] = {
72  { STAT_PG, "msg_queue_avail", offsetof(totempg_stats_t, msg_queue_avail), ICMAP_VALUETYPE_UINT32},
73  { STAT_PG, "msg_reserved", offsetof(totempg_stats_t, msg_reserved), ICMAP_VALUETYPE_UINT32},
74 };
75 struct cs_stats_conv cs_srp_stats[] = {
76  { STAT_SRP, "orf_token_tx", offsetof(totemsrp_stats_t, orf_token_tx), ICMAP_VALUETYPE_UINT64},
77  { STAT_SRP, "orf_token_rx", offsetof(totemsrp_stats_t, orf_token_rx), ICMAP_VALUETYPE_UINT64},
78  { STAT_SRP, "memb_merge_detect_tx", offsetof(totemsrp_stats_t, memb_merge_detect_tx), ICMAP_VALUETYPE_UINT64},
79  { STAT_SRP, "memb_merge_detect_rx", offsetof(totemsrp_stats_t, memb_merge_detect_rx), ICMAP_VALUETYPE_UINT64},
80  { STAT_SRP, "memb_join_tx", offsetof(totemsrp_stats_t, memb_join_tx), ICMAP_VALUETYPE_UINT64},
81  { STAT_SRP, "memb_join_rx", offsetof(totemsrp_stats_t, memb_join_rx), ICMAP_VALUETYPE_UINT64},
82  { STAT_SRP, "mcast_tx", offsetof(totemsrp_stats_t, mcast_tx), ICMAP_VALUETYPE_UINT64},
83  { STAT_SRP, "mcast_retx", offsetof(totemsrp_stats_t, mcast_retx), ICMAP_VALUETYPE_UINT64},
84  { STAT_SRP, "mcast_rx", offsetof(totemsrp_stats_t, mcast_rx), ICMAP_VALUETYPE_UINT64},
85  { STAT_SRP, "memb_commit_token_tx", offsetof(totemsrp_stats_t, memb_commit_token_tx), ICMAP_VALUETYPE_UINT64},
86  { STAT_SRP, "memb_commit_token_rx", offsetof(totemsrp_stats_t, memb_commit_token_rx), ICMAP_VALUETYPE_UINT64},
87  { STAT_SRP, "token_hold_cancel_tx", offsetof(totemsrp_stats_t, token_hold_cancel_tx), ICMAP_VALUETYPE_UINT64},
88  { STAT_SRP, "token_hold_cancel_rx", offsetof(totemsrp_stats_t, token_hold_cancel_rx), ICMAP_VALUETYPE_UINT64},
89  { STAT_SRP, "operational_entered", offsetof(totemsrp_stats_t, operational_entered), ICMAP_VALUETYPE_UINT64},
90  { STAT_SRP, "operational_token_lost", offsetof(totemsrp_stats_t, operational_token_lost), ICMAP_VALUETYPE_UINT64},
91  { STAT_SRP, "gather_entered", offsetof(totemsrp_stats_t, gather_entered), ICMAP_VALUETYPE_UINT64},
92  { STAT_SRP, "gather_token_lost", offsetof(totemsrp_stats_t, gather_token_lost), ICMAP_VALUETYPE_UINT64},
93  { STAT_SRP, "commit_entered", offsetof(totemsrp_stats_t, commit_entered), ICMAP_VALUETYPE_UINT64},
94  { STAT_SRP, "commit_token_lost", offsetof(totemsrp_stats_t, commit_token_lost), ICMAP_VALUETYPE_UINT64},
95  { STAT_SRP, "recovery_entered", offsetof(totemsrp_stats_t, recovery_entered), ICMAP_VALUETYPE_UINT64},
96  { STAT_SRP, "recovery_token_lost", offsetof(totemsrp_stats_t, recovery_token_lost), ICMAP_VALUETYPE_UINT64},
97  { STAT_SRP, "consensus_timeouts", offsetof(totemsrp_stats_t, consensus_timeouts), ICMAP_VALUETYPE_UINT64},
98  { STAT_SRP, "rx_msg_dropped", offsetof(totemsrp_stats_t, rx_msg_dropped), ICMAP_VALUETYPE_UINT64},
99  { STAT_SRP, "time_since_token_last_received", offsetof(totemsrp_stats_t, time_since_token_last_received), ICMAP_VALUETYPE_UINT64},
100  { STAT_SRP, "continuous_gather", offsetof(totemsrp_stats_t, continuous_gather), ICMAP_VALUETYPE_UINT32},
101  { STAT_SRP, "continuous_sendmsg_failures", offsetof(totemsrp_stats_t, continuous_sendmsg_failures), ICMAP_VALUETYPE_UINT32},
102  { STAT_SRP, "firewall_enabled_or_nic_failure", offsetof(totemsrp_stats_t, firewall_enabled_or_nic_failure), ICMAP_VALUETYPE_UINT8},
103  { STAT_SRP, "mtt_rx_token", offsetof(totemsrp_stats_t, mtt_rx_token), ICMAP_VALUETYPE_UINT32},
104  { STAT_SRP, "avg_token_workload", offsetof(totemsrp_stats_t, avg_token_workload), ICMAP_VALUETYPE_UINT32},
105  { STAT_SRP, "avg_backlog_calc", offsetof(totemsrp_stats_t, avg_backlog_calc), ICMAP_VALUETYPE_UINT32},
106 };
107 
108 struct cs_stats_conv cs_knet_stats[] = {
109  { STAT_KNET, "enabled", offsetof(struct knet_link_status, enabled), ICMAP_VALUETYPE_UINT8},
110  { STAT_KNET, "connected", offsetof(struct knet_link_status, connected), ICMAP_VALUETYPE_UINT8},
111  { STAT_KNET, "mtu", offsetof(struct knet_link_status, mtu), ICMAP_VALUETYPE_UINT32},
112  { STAT_KNET, "tx_data_packets", offsetof(struct knet_link_status, stats.tx_data_packets), ICMAP_VALUETYPE_UINT64},
113  { STAT_KNET, "rx_data_packets", offsetof(struct knet_link_status, stats.rx_data_packets), ICMAP_VALUETYPE_UINT64},
114  { STAT_KNET, "tx_data_bytes", offsetof(struct knet_link_status, stats.tx_data_bytes), ICMAP_VALUETYPE_UINT64},
115  { STAT_KNET, "rx_data_bytes", offsetof(struct knet_link_status, stats.rx_data_bytes), ICMAP_VALUETYPE_UINT64},
116  { STAT_KNET, "tx_ping_packets", offsetof(struct knet_link_status, stats.tx_ping_packets), ICMAP_VALUETYPE_UINT64},
117  { STAT_KNET, "rx_ping_packets", offsetof(struct knet_link_status, stats.rx_ping_packets), ICMAP_VALUETYPE_UINT64},
118  { STAT_KNET, "tx_ping_bytes", offsetof(struct knet_link_status, stats.tx_ping_bytes), ICMAP_VALUETYPE_UINT64},
119  { STAT_KNET, "rx_ping_bytes", offsetof(struct knet_link_status, stats.rx_ping_bytes), ICMAP_VALUETYPE_UINT64},
120  { STAT_KNET, "tx_pong_packets", offsetof(struct knet_link_status, stats.tx_pong_packets), ICMAP_VALUETYPE_UINT64},
121  { STAT_KNET, "rx_pong_packets", offsetof(struct knet_link_status, stats.rx_pong_packets), ICMAP_VALUETYPE_UINT64},
122  { STAT_KNET, "tx_pong_bytes", offsetof(struct knet_link_status, stats.tx_pong_bytes), ICMAP_VALUETYPE_UINT64},
123  { STAT_KNET, "rx_pong_bytes", offsetof(struct knet_link_status, stats.rx_pong_bytes), ICMAP_VALUETYPE_UINT64},
124  { STAT_KNET, "tx_pmtu_packets", offsetof(struct knet_link_status, stats.tx_pmtu_packets), ICMAP_VALUETYPE_UINT64},
125  { STAT_KNET, "rx_pmtu_packets", offsetof(struct knet_link_status, stats.rx_pmtu_packets), ICMAP_VALUETYPE_UINT64},
126  { STAT_KNET, "tx_pmtu_bytes", offsetof(struct knet_link_status, stats.tx_pmtu_bytes), ICMAP_VALUETYPE_UINT64},
127  { STAT_KNET, "rx_pmtu_bytes", offsetof(struct knet_link_status, stats.rx_pmtu_bytes), ICMAP_VALUETYPE_UINT64},
128  { STAT_KNET, "tx_total_packets", offsetof(struct knet_link_status, stats.tx_total_packets), ICMAP_VALUETYPE_UINT64},
129  { STAT_KNET, "rx_total_packets", offsetof(struct knet_link_status, stats.rx_total_packets), ICMAP_VALUETYPE_UINT64},
130  { STAT_KNET, "tx_total_bytes", offsetof(struct knet_link_status, stats.tx_total_bytes), ICMAP_VALUETYPE_UINT64},
131  { STAT_KNET, "rx_total_bytes", offsetof(struct knet_link_status, stats.rx_total_bytes), ICMAP_VALUETYPE_UINT64},
132  { STAT_KNET, "tx_total_errors", offsetof(struct knet_link_status, stats.tx_total_errors), ICMAP_VALUETYPE_UINT64},
133  { STAT_KNET, "rx_total_retries", offsetof(struct knet_link_status, stats.tx_total_retries), ICMAP_VALUETYPE_UINT64},
134  { STAT_KNET, "tx_pmtu_errors", offsetof(struct knet_link_status, stats.tx_pmtu_errors), ICMAP_VALUETYPE_UINT32},
135  { STAT_KNET, "tx_pmtu_retries", offsetof(struct knet_link_status, stats.tx_pmtu_retries), ICMAP_VALUETYPE_UINT32},
136  { STAT_KNET, "tx_ping_errors", offsetof(struct knet_link_status, stats.tx_ping_errors), ICMAP_VALUETYPE_UINT32},
137  { STAT_KNET, "tx_ping_retries", offsetof(struct knet_link_status, stats.tx_ping_retries), ICMAP_VALUETYPE_UINT32},
138  { STAT_KNET, "tx_pong_errors", offsetof(struct knet_link_status, stats.tx_pong_errors), ICMAP_VALUETYPE_UINT32},
139  { STAT_KNET, "tx_pong_retries", offsetof(struct knet_link_status, stats.tx_pong_retries), ICMAP_VALUETYPE_UINT32},
140  { STAT_KNET, "tx_data_errors", offsetof(struct knet_link_status, stats.tx_data_errors), ICMAP_VALUETYPE_UINT32},
141  { STAT_KNET, "tx_data_retries", offsetof(struct knet_link_status, stats.tx_data_retries), ICMAP_VALUETYPE_UINT32},
142  { STAT_KNET, "latency_min", offsetof(struct knet_link_status, stats.latency_min), ICMAP_VALUETYPE_UINT32},
143  { STAT_KNET, "latency_max", offsetof(struct knet_link_status, stats.latency_max), ICMAP_VALUETYPE_UINT32},
144  { STAT_KNET, "latency_ave", offsetof(struct knet_link_status, stats.latency_ave), ICMAP_VALUETYPE_UINT32},
145  { STAT_KNET, "latency_samples", offsetof(struct knet_link_status, stats.latency_samples), ICMAP_VALUETYPE_UINT32},
146  { STAT_KNET, "down_count", offsetof(struct knet_link_status, stats.down_count), ICMAP_VALUETYPE_UINT32},
147  { STAT_KNET, "up_count", offsetof(struct knet_link_status, stats.up_count), ICMAP_VALUETYPE_UINT32},
148 };
150  { STAT_KNET_HANDLE, "tx_uncompressed_packets", offsetof(struct knet_handle_stats, tx_uncompressed_packets), ICMAP_VALUETYPE_UINT64},
151  { STAT_KNET_HANDLE, "tx_compressed_packets", offsetof(struct knet_handle_stats, tx_compressed_packets), ICMAP_VALUETYPE_UINT64},
152  { STAT_KNET_HANDLE, "tx_compressed_original_bytes", offsetof(struct knet_handle_stats, tx_compressed_original_bytes), ICMAP_VALUETYPE_UINT64},
153  { STAT_KNET_HANDLE, "tx_compressed_size_bytes", offsetof(struct knet_handle_stats, tx_compressed_size_bytes), ICMAP_VALUETYPE_UINT64},
154  { STAT_KNET_HANDLE, "tx_compress_time_min", offsetof(struct knet_handle_stats, tx_compress_time_min), ICMAP_VALUETYPE_UINT64},
155  { STAT_KNET_HANDLE, "tx_compress_time_max", offsetof(struct knet_handle_stats, tx_compress_time_max), ICMAP_VALUETYPE_UINT64},
156  { STAT_KNET_HANDLE, "tx_compress_time_ave", offsetof(struct knet_handle_stats, tx_compress_time_ave), ICMAP_VALUETYPE_UINT64},
157  { STAT_KNET_HANDLE, "rx_compressed_packets", offsetof(struct knet_handle_stats, rx_compressed_packets), ICMAP_VALUETYPE_UINT64},
158  { STAT_KNET_HANDLE, "rx_compressed_original_bytes", offsetof(struct knet_handle_stats, rx_compressed_original_bytes), ICMAP_VALUETYPE_UINT64},
159  { STAT_KNET_HANDLE, "rx_compressed_size_bytes", offsetof(struct knet_handle_stats, rx_compressed_size_bytes), ICMAP_VALUETYPE_UINT64},
160  { STAT_KNET_HANDLE, "rx_compress_time_min", offsetof(struct knet_handle_stats, rx_compress_time_min), ICMAP_VALUETYPE_UINT64},
161  { STAT_KNET_HANDLE, "rx_compress_time_max", offsetof(struct knet_handle_stats, rx_compress_time_max), ICMAP_VALUETYPE_UINT64},
162  { STAT_KNET_HANDLE, "rx_compress_time_ave", offsetof(struct knet_handle_stats, rx_compress_time_ave), ICMAP_VALUETYPE_UINT64},
163  { STAT_KNET_HANDLE, "tx_crypt_time_min", offsetof(struct knet_handle_stats, tx_crypt_time_min), ICMAP_VALUETYPE_UINT64},
164  { STAT_KNET_HANDLE, "tx_crypt_time_max", offsetof(struct knet_handle_stats, tx_crypt_time_max), ICMAP_VALUETYPE_UINT64},
165  { STAT_KNET_HANDLE, "tx_crypt_time_ave", offsetof(struct knet_handle_stats, tx_crypt_time_ave), ICMAP_VALUETYPE_UINT64},
166  { STAT_KNET_HANDLE, "tx_crypt_byte_overhead", offsetof(struct knet_handle_stats, tx_crypt_byte_overhead), ICMAP_VALUETYPE_UINT64},
167  { STAT_KNET_HANDLE, "tx_crypt_packets", offsetof(struct knet_handle_stats, tx_crypt_packets), ICMAP_VALUETYPE_UINT64},
168  { STAT_KNET_HANDLE, "rx_crypt_time_min", offsetof(struct knet_handle_stats, rx_crypt_time_min), ICMAP_VALUETYPE_UINT64},
169  { STAT_KNET_HANDLE, "rx_crypt_time_max", offsetof(struct knet_handle_stats, rx_crypt_time_max), ICMAP_VALUETYPE_UINT64},
170  { STAT_KNET_HANDLE, "rx_crypt_time_ave", offsetof(struct knet_handle_stats, rx_crypt_time_ave), ICMAP_VALUETYPE_UINT64},
171  { STAT_KNET_HANDLE, "rx_crypt_packets", offsetof(struct knet_handle_stats, rx_crypt_packets), ICMAP_VALUETYPE_UINT64},
172 };
173 
175  { STAT_IPCSC, "queueing", offsetof(struct ipcs_conn_stats, cnx.queuing), ICMAP_VALUETYPE_INT32},
176  { STAT_IPCSC, "queued", offsetof(struct ipcs_conn_stats, cnx.queued), ICMAP_VALUETYPE_UINT32},
177  { STAT_IPCSC, "invalid_request", offsetof(struct ipcs_conn_stats, cnx.invalid_request), ICMAP_VALUETYPE_UINT64},
178  { STAT_IPCSC, "overload", offsetof(struct ipcs_conn_stats, cnx.overload), ICMAP_VALUETYPE_UINT64},
179  { STAT_IPCSC, "sent", offsetof(struct ipcs_conn_stats, cnx.sent), ICMAP_VALUETYPE_UINT32},
180  { STAT_IPCSC, "procname", offsetof(struct ipcs_conn_stats, cnx.proc_name), ICMAP_VALUETYPE_STRING},
181  { STAT_IPCSC, "requests", offsetof(struct ipcs_conn_stats, conn.requests), ICMAP_VALUETYPE_UINT64},
182  { STAT_IPCSC, "responses", offsetof(struct ipcs_conn_stats, conn.responses), ICMAP_VALUETYPE_UINT64},
183  { STAT_IPCSC, "dispatched", offsetof(struct ipcs_conn_stats, conn.events), ICMAP_VALUETYPE_UINT64},
184  { STAT_IPCSC, "send_retries", offsetof(struct ipcs_conn_stats, conn.send_retries), ICMAP_VALUETYPE_UINT64},
185  { STAT_IPCSC, "recv_retries", offsetof(struct ipcs_conn_stats, conn.recv_retries), ICMAP_VALUETYPE_UINT64},
186  { STAT_IPCSC, "flow_control", offsetof(struct ipcs_conn_stats, conn.flow_control_state), ICMAP_VALUETYPE_UINT32},
187  { STAT_IPCSC, "flow_control_count", offsetof(struct ipcs_conn_stats, conn.flow_control_count), ICMAP_VALUETYPE_UINT64},
188 };
190  { STAT_IPCSG, "global.active", offsetof(struct ipcs_global_stats, active), ICMAP_VALUETYPE_UINT64},
191  { STAT_IPCSG, "global.closed", offsetof(struct ipcs_global_stats, closed), ICMAP_VALUETYPE_UINT64},
192 };
193 
194 #define NUM_PG_STATS (sizeof(cs_pg_stats) / sizeof(struct cs_stats_conv))
195 #define NUM_SRP_STATS (sizeof(cs_srp_stats) / sizeof(struct cs_stats_conv))
196 #define NUM_KNET_STATS (sizeof(cs_knet_stats) / sizeof(struct cs_stats_conv))
197 #define NUM_KNET_HANDLE_STATS (sizeof(cs_knet_handle_stats) / sizeof(struct cs_stats_conv))
198 #define NUM_IPCSC_STATS (sizeof(cs_ipcs_conn_stats) / sizeof(struct cs_stats_conv))
199 #define NUM_IPCSG_STATS (sizeof(cs_ipcs_global_stats) / sizeof(struct cs_stats_conv))
200 
201 /* What goes in the trie */
202 struct stats_item {
203  char *key_name;
205 };
206 
207 /* One of these per tracker */
209 {
210  char *key_name;
211  void *user_data;
212  int32_t events;
214  uint64_t old_value;
215  struct qb_list_head list;
216 };
217 QB_LIST_DECLARE (stats_tracker_list_head);
218 static const struct corosync_api_v1 *api;
219 
220 static void stats_map_set_value(struct cs_stats_conv *conv,
221  void *stat_array,
222  void *value,
223  size_t *value_len,
225 {
226  if (value_len) {
227  *value_len = icmap_get_valuetype_len(conv->value_type);
228  }
229  if (type) {
230  *type = conv->value_type;
231  if ((*type == ICMAP_VALUETYPE_STRING) && value_len && stat_array) {
232  *value_len = strlen((char *)(stat_array) + conv->offset)+1;
233  }
234  }
235  if (value) {
236  memcpy(value, (char *)(stat_array) + conv->offset, *value_len);
237  }
238 }
239 
240 static void stats_add_entry(const char *key, struct cs_stats_conv *cs_conv)
241 {
242  struct stats_item *item = malloc(sizeof(struct stats_item));
243 
244  if (item) {
245  item->cs_conv = cs_conv;
246  item->key_name = strdup(key);
247  qb_map_put(stats_map, item->key_name, item);
248  }
249 }
250 static void stats_rm_entry(const char *key)
251 {
252  struct stats_item *item = qb_map_get(stats_map, key);
253 
254  if (item) {
255  qb_map_rm(stats_map, item->key_name);
256  free(item->key_name);
257  free(item);
258  }
259 }
260 
261 cs_error_t stats_map_init(const struct corosync_api_v1 *corosync_api)
262 {
263  int i;
265 
266  api = corosync_api;
267 
268  stats_map = qb_trie_create();
269  if (!stats_map) {
270  return CS_ERR_INIT;
271  }
272 
273  /* Populate the static portions of the trie */
274  for (i = 0; i<NUM_PG_STATS; i++) {
275  sprintf(param, "stats.pg.%s", cs_pg_stats[i].name);
276  stats_add_entry(param, &cs_pg_stats[i]);
277  }
278  for (i = 0; i<NUM_SRP_STATS; i++) {
279  sprintf(param, "stats.srp.%s", cs_srp_stats[i].name);
280  stats_add_entry(param, &cs_srp_stats[i]);
281  }
282  for (i = 0; i<NUM_IPCSG_STATS; i++) {
283  sprintf(param, "stats.ipcs.%s", cs_ipcs_global_stats[i].name);
284  stats_add_entry(param, &cs_ipcs_global_stats[i]);
285  }
286 
287  /* KNET and IPCS stats are added when appropriate */
288  return CS_OK;
289 }
290 
292  void *value,
293  size_t *value_len,
295 {
296  struct cs_stats_conv *statinfo;
297  struct stats_item *item;
298  totempg_stats_t *pg_stats;
299  struct knet_link_status link_status;
302  struct knet_handle_stats knet_handle_stats;
303  int res;
304  int nodeid;
305  int link_no;
306  int service_id;
307  uint32_t pid;
308  void *conn_ptr;
309 
310  item = qb_map_get(stats_map, key_name);
311  if (!item) {
312  return CS_ERR_NOT_EXIST;
313  }
314 
315  statinfo = item->cs_conv;
316  switch (statinfo->type) {
317  case STAT_PG:
318  pg_stats = api->totem_get_stats();
319  stats_map_set_value(statinfo, pg_stats, value, value_len, type);
320  break;
321  case STAT_SRP:
322  pg_stats = api->totem_get_stats();
323  stats_map_set_value(statinfo, pg_stats->srp, value, value_len, type);
324  break;
325  case STAT_KNET_HANDLE:
326  res = totemknet_handle_get_stats(&knet_handle_stats);
327  if (res) {
328  return res;
329  }
330  stats_map_set_value(statinfo, &knet_handle_stats, value, value_len, type);
331  break;
332  case STAT_KNET:
333  if (sscanf(key_name, "stats.knet.node%d.link%d", &nodeid, &link_no) != 2) {
334  return CS_ERR_NOT_EXIST;
335  }
336 
337  /* Validate node & link IDs */
338  if (nodeid <= 0 || nodeid > KNET_MAX_HOST ||
339  link_no < 0 || link_no > KNET_MAX_LINK) {
340  return CS_ERR_NOT_EXIST;
341  }
342 
343  /* Always get the latest stats */
344  res = totemknet_link_get_status((knet_node_id_t)nodeid, (uint8_t)link_no, &link_status);
345  if (res != CS_OK) {
346  return CS_ERR_LIBRARY;
347  }
348  stats_map_set_value(statinfo, &link_status, value, value_len, type);
349  break;
350  case STAT_IPCSC:
351  if (sscanf(key_name, "stats.ipcs.service%d.%d.%p", &service_id, &pid, &conn_ptr) != 3) {
352  return CS_ERR_NOT_EXIST;
353  }
354  res = cs_ipcs_get_conn_stats(service_id, pid, conn_ptr, &ipcs_conn_stats);
355  if (res != CS_OK) {
356  return res;
357  }
358  stats_map_set_value(statinfo, &ipcs_conn_stats, value, value_len, type);
359  break;
360  case STAT_IPCSG:
362  stats_map_set_value(statinfo, &ipcs_global_stats, value, value_len, type);
363  break;
364  default:
365  return CS_ERR_LIBRARY;
366  }
367  return CS_OK;
368 }
369 
370 #define STATS_CLEAR "stats.clear."
371 #define STATS_CLEAR_KNET "stats.clear.knet"
372 #define STATS_CLEAR_IPC "stats.clear.ipc"
373 #define STATS_CLEAR_TOTEM "stats.clear.totem"
374 #define STATS_CLEAR_ALL "stats.clear.all"
375 
376 cs_error_t stats_map_set(const char *key_name,
377  const void *value,
378  size_t value_len,
380 {
381  int cleared = 0;
382 
383  if (strncmp(key_name, STATS_CLEAR_KNET, strlen(STATS_CLEAR_KNET)) == 0) {
385  cleared = 1;
386  }
387  if (strncmp(key_name, STATS_CLEAR_IPC, strlen(STATS_CLEAR_IPC)) == 0) {
389  cleared = 1;
390  }
391  if (strncmp(key_name, STATS_CLEAR_TOTEM, strlen(STATS_CLEAR_TOTEM)) == 0) {
393  cleared = 1;
394  }
395  if (strncmp(key_name, STATS_CLEAR_ALL, strlen(STATS_CLEAR_ALL)) == 0) {
398  cleared = 1;
399  }
400  if (!cleared) {
401  return CS_ERR_NOT_SUPPORTED;
402  }
403  return CS_OK;
404 }
405 
406 cs_error_t stats_map_adjust_int(const char *key_name, int32_t step)
407 {
408  return CS_ERR_NOT_SUPPORTED;
409 }
410 
411 cs_error_t stats_map_delete(const char *key_name)
412 {
413  return CS_ERR_NOT_SUPPORTED;
414 }
415 
416 int stats_map_is_key_ro(const char *key_name)
417 {
418  /* It's all read-only apart from the 'clear' destinations */
419  if (strncmp(key_name, STATS_CLEAR, strlen(STATS_CLEAR)) == 0) {
420  return 0;
421  } else {
422  return 1;
423  }
424 }
425 
427 {
428  return (qb_map_pref_iter_create(stats_map, prefix));
429 }
430 
431 
432 const char *stats_map_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
433 {
434  const char *res;
435  struct stats_item *item;
436 
437  res = qb_map_iter_next(iter, (void **)&item);
438  if (res == NULL) {
439  return (res);
440  }
441  stats_map_set_value(item->cs_conv, NULL, NULL, value_len, type);
442 
443  return res;
444 }
445 
447 {
448  qb_map_iter_free(iter);
449 }
450 
451 
453 {
454  struct cs_stats_tracker *tracker;
455  struct qb_list_head *iter;
456  cs_error_t res;
457  size_t value_len;
459  uint64_t value;
460  struct icmap_notify_value new_val;
461  struct icmap_notify_value old_val;
462 
463  qb_list_for_each(iter, &stats_tracker_list_head) {
464 
465  tracker = qb_list_entry(iter, struct cs_stats_tracker, list);
466  if (tracker->events & ICMAP_TRACK_PREFIX || !tracker->key_name ) {
467  continue;
468  }
469 
470  res = stats_map_get(tracker->key_name,
471  &value, &value_len, &type);
472 
473  /* Check if it has changed */
474  if ((res == CS_OK) && (memcmp(&value, &tracker->old_value, value_len) != 0)) {
475 
476  old_val.type = new_val.type = type;
477  old_val.len = new_val.len = value_len;
478  old_val.data = new_val.data = &value;
479 
480  tracker->notify_fn(ICMAP_TRACK_MODIFY, tracker->key_name,
481  old_val, new_val, tracker->user_data);
482 
483  memcpy(&tracker->old_value, &value, value_len);
484  }
485  }
486 }
487 
488 
489 /* Callback from libqb when a key is added/removed */
490 static void stats_map_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
491 {
492  struct cs_stats_tracker *tracker = user_data;
493  struct icmap_notify_value new_val;
494  struct icmap_notify_value old_val;
495  char new_value[64];
496 
497  if (value == NULL && old_value == NULL) {
498  return ;
499  }
500 
501  new_val.data = new_value;
502  if (stats_map_get(key,
503  &new_value,
504  &new_val.len,
505  &new_val.type) != CS_OK) {
506  }
507 
508  /* We don't know what the old value was
509  but as this only tracks ADD & DELETE I'm not worried
510  about it */
511  memcpy(&old_val, &new_val, sizeof(new_val));
512 
513  tracker->notify_fn(icmap_qbtt_to_tt(event),
514  key,
515  new_val,
516  old_val,
517  tracker->user_data);
518 
519 }
520 
521 cs_error_t stats_map_track_add(const char *key_name,
522  int32_t track_type,
523  icmap_notify_fn_t notify_fn,
524  void *user_data,
526 {
527  struct cs_stats_tracker *tracker;
528  size_t value_len;
530  cs_error_t err;
531 
532  /* We can track adding or deleting a key under a prefix */
533  if ((track_type & ICMAP_TRACK_PREFIX) &&
534  (!(track_type & ICMAP_TRACK_DELETE) ||
535  !(track_type & ICMAP_TRACK_ADD))) {
536  return CS_ERR_NOT_SUPPORTED;
537  }
538 
539  tracker = malloc(sizeof(struct cs_stats_tracker));
540  if (!tracker) {
541  return CS_ERR_NO_MEMORY;
542  }
543 
544  tracker->notify_fn = notify_fn;
545  tracker->user_data = user_data;
546  tracker->events = track_type;
547  if (key_name) {
548  tracker->key_name = strdup(key_name);
549  if (!tracker->key_name) {
550  free(tracker);
551  return CS_ERR_NO_MEMORY;
552  }
553  /* Get initial value */
554  if (stats_map_get(tracker->key_name,
555  &tracker->old_value, &value_len, &type) == CS_OK) {
556  tracker->old_value = 0ULL;
557  }
558  } else {
559  tracker->key_name = NULL;
560  tracker->old_value = 0ULL;
561  }
562 
563  /* Add/delete trackers can use the qb_map tracking */
564  if ((track_type & ICMAP_TRACK_ADD) ||
565  (track_type & ICMAP_TRACK_DELETE)) {
566  err = qb_map_notify_add(stats_map, tracker->key_name,
567  stats_map_notify_fn,
568  icmap_tt_to_qbtt(track_type),
569  tracker);
570  if (err != 0) {
571  log_printf(LOGSYS_LEVEL_ERROR, "creating stats tracker %s failed. %d\n", tracker->key_name, err);
572  free(tracker->key_name);
573  free(tracker);
574  return (qb_to_cs_error(err));
575  }
576  }
577 
578  qb_list_add (&tracker->list, &stats_tracker_list_head);
579 
580  *icmap_track = (icmap_track_t)tracker;
581  return CS_OK;
582 }
583 
585 {
586  struct cs_stats_tracker *tracker = (struct cs_stats_tracker *)icmap_track;
587  int err;
588 
589  if ((tracker->events & ICMAP_TRACK_ADD) ||
590  (tracker->events & ICMAP_TRACK_DELETE)) {
591  err = qb_map_notify_del_2(stats_map,
592  tracker->key_name, stats_map_notify_fn,
593  icmap_tt_to_qbtt(tracker->events), tracker);
594  if (err) {
595  log_printf(LOGSYS_LEVEL_ERROR, "deleting tracker %s failed. %d\n", tracker->key_name, err);
596  }
597  }
598 
599  qb_list_del(&tracker->list);
600  free(tracker->key_name);
601  free(tracker);
602 
603  return CS_OK;
604 }
605 
607 {
608  struct cs_stats_tracker *tracker = (struct cs_stats_tracker *)icmap_track;
609 
610  return tracker->user_data;
611 }
612 
613 /* Called from totemknet to add/remove keys from our map */
614 void stats_knet_add_member(knet_node_id_t nodeid, uint8_t link_no)
615 {
616  int i;
618 
619  for (i = 0; i<NUM_KNET_STATS; i++) {
620  sprintf(param, "stats.knet.node%d.link%d.%s", nodeid, link_no, cs_knet_stats[i].name);
621  stats_add_entry(param, &cs_knet_stats[i]);
622  }
623 }
624 void stats_knet_del_member(knet_node_id_t nodeid, uint8_t link_no)
625 {
626  int i;
628 
629  for (i = 0; i<NUM_KNET_STATS; i++) {
630  sprintf(param, "stats.knet.node%d.link%d.%s", nodeid, link_no, cs_knet_stats[i].name);
631  stats_rm_entry(param);
632  }
633 }
634 
635 /* This is separated out from stats_map_init() because we don't know whether
636  knet is in use until much later in the startup */
638 {
639  int i;
641 
642  for (i = 0; i<NUM_KNET_HANDLE_STATS; i++) {
643  sprintf(param, "stats.knet.handle.%s", cs_knet_handle_stats[i].name);
644  stats_add_entry(param, &cs_knet_handle_stats[i]);
645  }
646 }
647 
648 /* Called from ipc_glue to add/remove keys from our map */
649 void stats_ipcs_add_connection(int service_id, uint32_t pid, void *ptr)
650 {
651  int i;
653 
654  for (i = 0; i<NUM_IPCSC_STATS; i++) {
655  sprintf(param, "stats.ipcs.service%d.%d.%p.%s", service_id, pid, ptr, cs_ipcs_conn_stats[i].name);
656  stats_add_entry(param, &cs_ipcs_conn_stats[i]);
657  }
658 }
659 void stats_ipcs_del_connection(int service_id, uint32_t pid, void *ptr)
660 {
661  int i;
663 
664  for (i = 0; i<NUM_IPCSC_STATS; i++) {
665  sprintf(param, "stats.ipcs.service%d.%d.%p.%s", service_id, pid, ptr, cs_ipcs_conn_stats[i].name);
666  stats_rm_entry(param);
667  }
668 }
corosync_api_v1
The corosync_api_v1 struct.
Definition: coroapi.h:225
stats_map
struct cmap_map stats_map
Definition: exec/cmap.c:112
cs_stats_conv::STAT_KNET
@ STAT_KNET
Definition: stats.c:65
cs_stats_conv::name
const char * name
Definition: stats.c:66
stats_map_init
cs_error_t stats_map_init(const struct corosync_api_v1 *corosync_api)
Definition: stats.c:261
value
uint32_t value
Definition: exec/votequorum.c:2
totempg_stats_t::srp
totemsrp_stats_t * srp
Definition: totemstats.h:96
log_printf
#define log_printf(level, format, args...)
Definition: logsys.h:323
cs_stats_conv
Definition: stats.c:64
icmap_notify_value::len
size_t len
Definition: icmap.h:93
ICMAP_VALUETYPE_UINT32
@ ICMAP_VALUETYPE_UINT32
Definition: icmap.h:64
coroapi.h
stats_map_is_key_ro
int stats_map_is_key_ro(const char *key_name)
Definition: stats.c:416
stats_ipcs_del_connection
void stats_ipcs_del_connection(int service_id, uint32_t pid, void *ptr)
Definition: stats.c:659
stats_ipcs_add_connection
void stats_ipcs_add_connection(int service_id, uint32_t pid, void *ptr)
Definition: stats.c:649
ICMAP_VALUETYPE_INT32
@ ICMAP_VALUETYPE_INT32
Definition: icmap.h:63
icmap_notify_value::data
const void * data
Definition: icmap.h:94
cs_stats_conv::STAT_IPCSG
@ STAT_IPCSG
Definition: stats.c:65
ipcs_stats.h
stats_map_set
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:376
CS_ERR_LIBRARY
@ CS_ERR_LIBRARY
Definition: corotypes.h:96
LOGSYS_LEVEL_ERROR
#define LOGSYS_LEVEL_ERROR
Definition: logsys.h:72
stats_trigger_trackers
void stats_trigger_trackers()
Definition: stats.c:452
totemsrp_stats_t
Definition: totemstats.h:53
STATS_CLEAR_IPC
#define STATS_CLEAR_IPC
Definition: stats.c:372
type
char type
Definition: totem.h:2
stats_map_iter_finalize
void stats_map_iter_finalize(icmap_iter_t iter)
Definition: stats.c:446
CS_ERR_NOT_EXIST
@ CS_ERR_NOT_EXIST
Definition: corotypes.h:106
ICMAP_TRACK_PREFIX
#define ICMAP_TRACK_PREFIX
Whole prefix is tracked, instead of key only (so "totem." tracking means that "totem....
Definition: icmap.h:85
cs_stats_tracker
Definition: stats.c:209
cs_stats_conv::STAT_SRP
@ STAT_SRP
Definition: stats.c:65
cs_stats_tracker::old_value
uint64_t old_value
Definition: stats.c:214
totempg_stats_t
Definition: totemstats.h:94
STATS_CLEAR_KNET
#define STATS_CLEAR_KNET
Definition: stats.c:371
cs_stats_conv::type
enum cs_stats_conv::@8 type
stats_knet_add_handle
void stats_knet_add_handle(void)
Definition: stats.c:637
cs_stats_tracker::events
int32_t events
Definition: stats.c:212
cs_stats_conv::STAT_IPCSC
@ STAT_IPCSC
Definition: stats.c:65
ipcs_global_stats
Definition: ipcs_stats.h:47
STATS_CLEAR_TOTEM
#define STATS_CLEAR_TOTEM
Definition: stats.c:373
ICMAP_TRACK_ADD
#define ICMAP_TRACK_ADD
Definition: icmap.h:76
stats_map_track_add
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:521
icmap.h
LOGSYS_DECLARE_SUBSYS
LOGSYS_DECLARE_SUBSYS("STATS")
param
uint8_t param
Definition: exec/votequorum.c:3
CS_ERR_NOT_SUPPORTED
@ CS_ERR_NOT_SUPPORTED
Definition: corotypes.h:113
CS_ERR_INIT
@ CS_ERR_INIT
Definition: corotypes.h:98
cs_stats_conv::value_type
const icmap_value_types_t value_type
Definition: stats.c:68
cs_srp_stats
struct cs_stats_conv cs_srp_stats[]
Definition: stats.c:75
corosync_api_v1::totem_get_stats
void *(* totem_get_stats)(void)
Definition: coroapi.h:435
icmap_track_t
struct icmap_track * icmap_track_t
Track type.
Definition: icmap.h:128
stats.h
totempg_stats_clear
void totempg_stats_clear(int flags)
Definition: totempg.c:1534
totemknet_link_get_status
int totemknet_link_get_status(knet_node_id_t node, uint8_t link, struct knet_link_status *status)
Definition: totemknet.c:1350
CS_OK
@ CS_OK
Definition: corotypes.h:95
STATS_CLEAR
#define STATS_CLEAR
Definition: stats.c:370
icmap_notify_value::type
icmap_value_types_t type
Definition: icmap.h:92
TOTEMPG_STATS_CLEAR_TRANSPORT
#define TOTEMPG_STATS_CLEAR_TRANSPORT
Definition: totemstats.h:116
stats_knet_add_member
void stats_knet_add_member(knet_node_id_t nodeid, uint8_t link_no)
Definition: stats.c:614
stats_map_track_delete
cs_error_t stats_map_track_delete(icmap_track_t icmap_track)
Definition: stats.c:584
ICMAP_KEYNAME_MAXLEN
#define ICMAP_KEYNAME_MAXLEN
Maximum length of key in icmap.
Definition: icmap.h:48
stats_map_get
cs_error_t stats_map_get(const char *key_name, void *value, size_t *value_len, icmap_value_types_t *type)
Definition: stats.c:291
NUM_IPCSC_STATS
#define NUM_IPCSC_STATS
Definition: stats.c:198
cs_error_t
cs_error_t
The cs_error_t enum.
Definition: corotypes.h:94
cs_stats_conv::STAT_KNET_HANDLE
@ STAT_KNET_HANDLE
Definition: stats.c:65
ipcs_conn_stats
Definition: ipcs_stats.h:53
cs_knet_stats
struct cs_stats_conv cs_knet_stats[]
Definition: stats.c:108
STATS_CLEAR_ALL
#define STATS_CLEAR_ALL
Definition: stats.c:374
qb_to_cs_error
cs_error_t qb_to_cs_error(int result)
qb_to_cs_error
icmap_qbtt_to_tt
int32_t icmap_qbtt_to_tt(int32_t track_type)
Definition: icmap.c:150
icmap_notify_fn_t
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
NUM_KNET_HANDLE_STATS
#define NUM_KNET_HANDLE_STATS
Definition: stats.c:197
icmap_value_types_t
icmap_value_types_t
Possible types of value.
Definition: icmap.h:58
stats_map_track_get_user_data
void * stats_map_track_get_user_data(icmap_track_t icmap_track)
Definition: stats.c:606
cs_stats_conv::STAT_PG
@ STAT_PG
Definition: stats.c:65
cs_ipcs_clear_stats
void cs_ipcs_clear_stats()
Definition: ipc_glue.c:709
cs_stats_tracker::notify_fn
icmap_notify_fn_t notify_fn
Definition: stats.c:213
ICMAP_TRACK_DELETE
#define ICMAP_TRACK_DELETE
Definition: icmap.h:77
user_data
void * user_data
Definition: sam.c:127
icmap_tt_to_qbtt
int32_t icmap_tt_to_qbtt(int32_t track_type)
Definition: icmap.c:127
ICMAP_TRACK_MODIFY
#define ICMAP_TRACK_MODIFY
Definition: icmap.h:78
NUM_PG_STATS
#define NUM_PG_STATS
Definition: stats.c:194
cs_knet_handle_stats
struct cs_stats_conv cs_knet_handle_stats[]
Definition: stats.c:149
cs_stats_tracker::key_name
char * key_name
Definition: stats.c:210
NUM_KNET_STATS
#define NUM_KNET_STATS
Definition: stats.c:196
cs_ipcs_global_stats
struct cs_stats_conv cs_ipcs_global_stats[]
Definition: stats.c:189
util.h
cs_ipcs_conn_stats
struct cs_stats_conv cs_ipcs_conn_stats[]
Definition: stats.c:174
stats_item::cs_conv
struct cs_stats_conv * cs_conv
Definition: stats.c:204
icmap_get_valuetype_len
size_t icmap_get_valuetype_len(icmap_value_types_t type)
Definition: icmap.c:304
nodeid
unsigned int nodeid
Definition: coroapi.h:0
NUM_SRP_STATS
#define NUM_SRP_STATS
Definition: stats.c:195
stats_map_delete
cs_error_t stats_map_delete(const char *key_name)
Definition: stats.c:411
cs_stats_tracker::list
struct qb_list_head list
Definition: stats.c:215
ICMAP_VALUETYPE_UINT64
@ ICMAP_VALUETYPE_UINT64
Definition: icmap.h:66
config.h
stats_knet_del_member
void stats_knet_del_member(knet_node_id_t nodeid, uint8_t link_no)
Definition: stats.c:624
cs_ipcs_get_global_stats
void cs_ipcs_get_global_stats(struct ipcs_global_stats *ipcs_stats)
Definition: ipc_glue.c:670
totemknet_handle_get_stats
int totemknet_handle_get_stats(struct knet_handle_stats *stats)
Definition: totemknet.c:1387
cs_pg_stats
struct cs_stats_conv cs_pg_stats[]
Definition: stats.c:71
cs_stats_conv::offset
const size_t offset
Definition: stats.c:67
ICMAP_VALUETYPE_STRING
@ ICMAP_VALUETYPE_STRING
Definition: icmap.h:69
logsys.h
ICMAP_VALUETYPE_UINT8
@ ICMAP_VALUETYPE_UINT8
Definition: icmap.h:60
NUM_IPCSG_STATS
#define NUM_IPCSG_STATS
Definition: stats.c:199
icmap_track
Definition: icmap.c:61
stats_map_iter_next
const char * stats_map_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
Definition: stats.c:432
cs_ipcs_get_conn_stats
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
stats_map_iter_init
icmap_iter_t stats_map_iter_init(const char *prefix)
Definition: stats.c:426
QB_LIST_DECLARE
QB_LIST_DECLARE(stats_tracker_list_head)
stats_map_adjust_int
cs_error_t stats_map_adjust_int(const char *key_name, int32_t step)
Definition: stats.c:406
icmap_notify_value
Structure passed as new_value and old_value in change callback.
Definition: icmap.h:91
CS_ERR_NO_MEMORY
@ CS_ERR_NO_MEMORY
Definition: corotypes.h:102
icmap_iter_t
qb_map_iter_t * icmap_iter_t
Itterator type.
Definition: icmap.h:123
totemstats.h
cs_stats_tracker::user_data
void * user_data
Definition: stats.c:211
TOTEMPG_STATS_CLEAR_TOTEM
#define TOTEMPG_STATS_CLEAR_TOTEM
Definition: totemstats.h:115
stats_item::key_name
char * key_name
Definition: stats.c:203
corodefs.h
stats_item
Definition: stats.c:202