corosync  3.0.3
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  assert(value_len != NULL);
237 
238  memcpy(value, (char *)(stat_array) + conv->offset, *value_len);
239  }
240 }
241 
242 static void stats_add_entry(const char *key, struct cs_stats_conv *cs_conv)
243 {
244  struct stats_item *item = malloc(sizeof(struct stats_item));
245 
246  if (item) {
247  item->cs_conv = cs_conv;
248  item->key_name = strdup(key);
249  qb_map_put(stats_map, item->key_name, item);
250  }
251 }
252 static void stats_rm_entry(const char *key)
253 {
254  struct stats_item *item = qb_map_get(stats_map, key);
255 
256  if (item) {
257  qb_map_rm(stats_map, item->key_name);
258  free(item->key_name);
259  free(item);
260  }
261 }
262 
263 cs_error_t stats_map_init(const struct corosync_api_v1 *corosync_api)
264 {
265  int i;
267 
268  api = corosync_api;
269 
270  stats_map = qb_trie_create();
271  if (!stats_map) {
272  return CS_ERR_INIT;
273  }
274 
275  /* Populate the static portions of the trie */
276  for (i = 0; i<NUM_PG_STATS; i++) {
277  sprintf(param, "stats.pg.%s", cs_pg_stats[i].name);
278  stats_add_entry(param, &cs_pg_stats[i]);
279  }
280  for (i = 0; i<NUM_SRP_STATS; i++) {
281  sprintf(param, "stats.srp.%s", cs_srp_stats[i].name);
282  stats_add_entry(param, &cs_srp_stats[i]);
283  }
284  for (i = 0; i<NUM_IPCSG_STATS; i++) {
285  sprintf(param, "stats.ipcs.%s", cs_ipcs_global_stats[i].name);
286  stats_add_entry(param, &cs_ipcs_global_stats[i]);
287  }
288 
289  /* KNET and IPCS stats are added when appropriate */
290  return CS_OK;
291 }
292 
294  void *value,
295  size_t *value_len,
297 {
298  struct cs_stats_conv *statinfo;
299  struct stats_item *item;
300  totempg_stats_t *pg_stats;
301  struct knet_link_status link_status;
304  struct knet_handle_stats knet_handle_stats;
305  int res;
306  int nodeid;
307  int link_no;
308  int service_id;
309  uint32_t pid;
310  void *conn_ptr;
311 
312  item = qb_map_get(stats_map, key_name);
313  if (!item) {
314  return CS_ERR_NOT_EXIST;
315  }
316 
317  statinfo = item->cs_conv;
318  switch (statinfo->type) {
319  case STAT_PG:
320  pg_stats = api->totem_get_stats();
321  stats_map_set_value(statinfo, pg_stats, value, value_len, type);
322  break;
323  case STAT_SRP:
324  pg_stats = api->totem_get_stats();
325  stats_map_set_value(statinfo, pg_stats->srp, value, value_len, type);
326  break;
327  case STAT_KNET_HANDLE:
328  res = totemknet_handle_get_stats(&knet_handle_stats);
329  if (res != CS_OK) {
330  return res;
331  }
332  stats_map_set_value(statinfo, &knet_handle_stats, value, value_len, type);
333  break;
334  case STAT_KNET:
335  if (sscanf(key_name, "stats.knet.node%d.link%d", &nodeid, &link_no) != 2) {
336  return CS_ERR_NOT_EXIST;
337  }
338 
339  /* Validate node & link IDs */
340  if (nodeid <= 0 || nodeid > KNET_MAX_HOST ||
341  link_no < 0 || link_no > KNET_MAX_LINK) {
342  return CS_ERR_NOT_EXIST;
343  }
344 
345  /* Always get the latest stats */
346  res = totemknet_link_get_status((knet_node_id_t)nodeid, (uint8_t)link_no, &link_status);
347  if (res != CS_OK) {
348  return CS_ERR_LIBRARY;
349  }
350  stats_map_set_value(statinfo, &link_status, value, value_len, type);
351  break;
352  case STAT_IPCSC:
353  if (sscanf(key_name, "stats.ipcs.service%d.%d.%p", &service_id, &pid, &conn_ptr) != 3) {
354  return CS_ERR_NOT_EXIST;
355  }
356  res = cs_ipcs_get_conn_stats(service_id, pid, conn_ptr, &ipcs_conn_stats);
357  if (res != CS_OK) {
358  return res;
359  }
360  stats_map_set_value(statinfo, &ipcs_conn_stats, value, value_len, type);
361  break;
362  case STAT_IPCSG:
364  stats_map_set_value(statinfo, &ipcs_global_stats, value, value_len, type);
365  break;
366  default:
367  return CS_ERR_LIBRARY;
368  }
369  return CS_OK;
370 }
371 
372 #define STATS_CLEAR "stats.clear."
373 #define STATS_CLEAR_KNET "stats.clear.knet"
374 #define STATS_CLEAR_IPC "stats.clear.ipc"
375 #define STATS_CLEAR_TOTEM "stats.clear.totem"
376 #define STATS_CLEAR_ALL "stats.clear.all"
377 
378 cs_error_t stats_map_set(const char *key_name,
379  const void *value,
380  size_t value_len,
382 {
383  int cleared = 0;
384 
385  if (strncmp(key_name, STATS_CLEAR_KNET, strlen(STATS_CLEAR_KNET)) == 0) {
387  cleared = 1;
388  }
389  if (strncmp(key_name, STATS_CLEAR_IPC, strlen(STATS_CLEAR_IPC)) == 0) {
391  cleared = 1;
392  }
393  if (strncmp(key_name, STATS_CLEAR_TOTEM, strlen(STATS_CLEAR_TOTEM)) == 0) {
395  cleared = 1;
396  }
397  if (strncmp(key_name, STATS_CLEAR_ALL, strlen(STATS_CLEAR_ALL)) == 0) {
400  cleared = 1;
401  }
402  if (!cleared) {
403  return CS_ERR_NOT_SUPPORTED;
404  }
405  return CS_OK;
406 }
407 
408 cs_error_t stats_map_adjust_int(const char *key_name, int32_t step)
409 {
410  return CS_ERR_NOT_SUPPORTED;
411 }
412 
413 cs_error_t stats_map_delete(const char *key_name)
414 {
415  return CS_ERR_NOT_SUPPORTED;
416 }
417 
418 int stats_map_is_key_ro(const char *key_name)
419 {
420  /* It's all read-only apart from the 'clear' destinations */
421  if (strncmp(key_name, STATS_CLEAR, strlen(STATS_CLEAR)) == 0) {
422  return 0;
423  } else {
424  return 1;
425  }
426 }
427 
429 {
430  return (qb_map_pref_iter_create(stats_map, prefix));
431 }
432 
433 
434 const char *stats_map_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
435 {
436  const char *res;
437  struct stats_item *item;
438 
439  res = qb_map_iter_next(iter, (void **)&item);
440  if (res == NULL) {
441  return (res);
442  }
443  stats_map_set_value(item->cs_conv, NULL, NULL, value_len, type);
444 
445  return res;
446 }
447 
449 {
450  qb_map_iter_free(iter);
451 }
452 
453 
455 {
456  struct cs_stats_tracker *tracker;
457  struct qb_list_head *iter;
458  cs_error_t res;
459  size_t value_len;
461  uint64_t value;
462  struct icmap_notify_value new_val;
463  struct icmap_notify_value old_val;
464 
465  qb_list_for_each(iter, &stats_tracker_list_head) {
466 
467  tracker = qb_list_entry(iter, struct cs_stats_tracker, list);
468  if (tracker->events & ICMAP_TRACK_PREFIX || !tracker->key_name ) {
469  continue;
470  }
471 
472  res = stats_map_get(tracker->key_name,
473  &value, &value_len, &type);
474 
475  /* Check if it has changed */
476  if ((res == CS_OK) && (memcmp(&value, &tracker->old_value, value_len) != 0)) {
477 
478  old_val.type = new_val.type = type;
479  old_val.len = new_val.len = value_len;
480  old_val.data = new_val.data = &value;
481 
482  tracker->notify_fn(ICMAP_TRACK_MODIFY, tracker->key_name,
483  old_val, new_val, tracker->user_data);
484 
485  memcpy(&tracker->old_value, &value, value_len);
486  }
487  }
488 }
489 
490 
491 /* Callback from libqb when a key is added/removed */
492 static void stats_map_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
493 {
494  struct cs_stats_tracker *tracker = user_data;
495  struct icmap_notify_value new_val;
496  struct icmap_notify_value old_val;
497  char new_value[64];
498 
499  if (value == NULL && old_value == NULL) {
500  return ;
501  }
502 
503  new_val.data = new_value;
504  if (stats_map_get(key,
505  &new_value,
506  &new_val.len,
507  &new_val.type) != CS_OK) {
508  log_printf(LOGSYS_LEVEL_WARNING, "get value of notified key %s failed", key);
509  return ;
510  }
511 
512  /* We don't know what the old value was
513  but as this only tracks ADD & DELETE I'm not worried
514  about it */
515  memcpy(&old_val, &new_val, sizeof(new_val));
516 
517  tracker->notify_fn(icmap_qbtt_to_tt(event),
518  key,
519  new_val,
520  old_val,
521  tracker->user_data);
522 
523 }
524 
525 cs_error_t stats_map_track_add(const char *key_name,
526  int32_t track_type,
527  icmap_notify_fn_t notify_fn,
528  void *user_data,
530 {
531  struct cs_stats_tracker *tracker;
532  size_t value_len;
534  cs_error_t err;
535 
536  /* We can track adding or deleting a key under a prefix */
537  if ((track_type & ICMAP_TRACK_PREFIX) &&
538  (!(track_type & ICMAP_TRACK_DELETE) ||
539  !(track_type & ICMAP_TRACK_ADD))) {
540  return CS_ERR_NOT_SUPPORTED;
541  }
542 
543  tracker = malloc(sizeof(struct cs_stats_tracker));
544  if (!tracker) {
545  return CS_ERR_NO_MEMORY;
546  }
547 
548  tracker->notify_fn = notify_fn;
549  tracker->user_data = user_data;
550  tracker->events = track_type;
551  if (key_name) {
552  tracker->key_name = strdup(key_name);
553  if (!tracker->key_name) {
554  free(tracker);
555  return CS_ERR_NO_MEMORY;
556  }
557  /* Get initial value */
558  if (stats_map_get(tracker->key_name,
559  &tracker->old_value, &value_len, &type) == CS_OK) {
560  tracker->old_value = 0ULL;
561  }
562  } else {
563  tracker->key_name = NULL;
564  tracker->old_value = 0ULL;
565  }
566 
567  /* Add/delete trackers can use the qb_map tracking */
568  if ((track_type & ICMAP_TRACK_ADD) ||
569  (track_type & ICMAP_TRACK_DELETE)) {
570  err = qb_map_notify_add(stats_map, tracker->key_name,
571  stats_map_notify_fn,
572  icmap_tt_to_qbtt(track_type),
573  tracker);
574  if (err != 0) {
575  log_printf(LOGSYS_LEVEL_ERROR, "creating stats tracker %s failed. %d\n", tracker->key_name, err);
576  free(tracker->key_name);
577  free(tracker);
578  return (qb_to_cs_error(err));
579  }
580  }
581 
582  qb_list_add (&tracker->list, &stats_tracker_list_head);
583 
584  *icmap_track = (icmap_track_t)tracker;
585  return CS_OK;
586 }
587 
589 {
590  struct cs_stats_tracker *tracker = (struct cs_stats_tracker *)icmap_track;
591  int err;
592 
593  if ((tracker->events & ICMAP_TRACK_ADD) ||
594  (tracker->events & ICMAP_TRACK_DELETE)) {
595  err = qb_map_notify_del_2(stats_map,
596  tracker->key_name, stats_map_notify_fn,
597  icmap_tt_to_qbtt(tracker->events), tracker);
598  if (err) {
599  log_printf(LOGSYS_LEVEL_ERROR, "deleting tracker %s failed. %d\n", tracker->key_name, err);
600  }
601  }
602 
603  qb_list_del(&tracker->list);
604  free(tracker->key_name);
605  free(tracker);
606 
607  return CS_OK;
608 }
609 
611 {
612  struct cs_stats_tracker *tracker = (struct cs_stats_tracker *)icmap_track;
613 
614  return tracker->user_data;
615 }
616 
617 /* Called from totemknet to add/remove keys from our map */
618 void stats_knet_add_member(knet_node_id_t nodeid, uint8_t link_no)
619 {
620  int i;
622 
623  for (i = 0; i<NUM_KNET_STATS; i++) {
624  sprintf(param, "stats.knet.node%d.link%d.%s", nodeid, link_no, cs_knet_stats[i].name);
625  stats_add_entry(param, &cs_knet_stats[i]);
626  }
627 }
628 void stats_knet_del_member(knet_node_id_t nodeid, uint8_t link_no)
629 {
630  int i;
632 
633  for (i = 0; i<NUM_KNET_STATS; i++) {
634  sprintf(param, "stats.knet.node%d.link%d.%s", nodeid, link_no, cs_knet_stats[i].name);
635  stats_rm_entry(param);
636  }
637 }
638 
639 /* This is separated out from stats_map_init() because we don't know whether
640  knet is in use until much later in the startup */
642 {
643  int i;
645 
646  for (i = 0; i<NUM_KNET_HANDLE_STATS; i++) {
647  sprintf(param, "stats.knet.handle.%s", cs_knet_handle_stats[i].name);
648  stats_add_entry(param, &cs_knet_handle_stats[i]);
649  }
650 }
651 
652 /* Called from ipc_glue to add/remove keys from our map */
653 void stats_ipcs_add_connection(int service_id, uint32_t pid, void *ptr)
654 {
655  int i;
657 
658  for (i = 0; i<NUM_IPCSC_STATS; i++) {
659  sprintf(param, "stats.ipcs.service%d.%d.%p.%s", service_id, pid, ptr, cs_ipcs_conn_stats[i].name);
660  stats_add_entry(param, &cs_ipcs_conn_stats[i]);
661  }
662 }
663 void stats_ipcs_del_connection(int service_id, uint32_t pid, void *ptr)
664 {
665  int i;
667 
668  for (i = 0; i<NUM_IPCSC_STATS; i++) {
669  sprintf(param, "stats.ipcs.service%d.%d.%p.%s", service_id, pid, ptr, cs_ipcs_conn_stats[i].name);
670  stats_rm_entry(param);
671  }
672 }
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:263
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:418
stats_ipcs_del_connection
void stats_ipcs_del_connection(int service_id, uint32_t pid, void *ptr)
Definition: stats.c:663
stats_ipcs_add_connection
void stats_ipcs_add_connection(int service_id, uint32_t pid, void *ptr)
Definition: stats.c:653
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:378
CS_ERR_LIBRARY
@ CS_ERR_LIBRARY
Definition: corotypes.h:99
LOGSYS_LEVEL_ERROR
#define LOGSYS_LEVEL_ERROR
Definition: logsys.h:72
stats_trigger_trackers
void stats_trigger_trackers()
Definition: stats.c:454
totemsrp_stats_t
Definition: totemstats.h:53
STATS_CLEAR_IPC
#define STATS_CLEAR_IPC
Definition: stats.c:374
type
char type
Definition: totem.h:2
stats_map_iter_finalize
void stats_map_iter_finalize(icmap_iter_t iter)
Definition: stats.c:448
CS_ERR_NOT_EXIST
@ CS_ERR_NOT_EXIST
Definition: corotypes.h:109
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:373
cs_stats_conv::type
enum cs_stats_conv::@8 type
stats_knet_add_handle
void stats_knet_add_handle(void)
Definition: stats.c:641
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:375
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:525
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:116
CS_ERR_INIT
@ CS_ERR_INIT
Definition: corotypes.h:101
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:1564
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:1499
CS_OK
@ CS_OK
Definition: corotypes.h:98
STATS_CLEAR
#define STATS_CLEAR
Definition: stats.c:372
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:618
stats_map_track_delete
cs_error_t stats_map_track_delete(icmap_track_t icmap_track)
Definition: stats.c:588
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:293
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:97
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:376
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:610
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:306
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:413
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:628
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:1536
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
LOGSYS_LEVEL_WARNING
#define LOGSYS_LEVEL_WARNING
Definition: logsys.h:73
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:434
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:428
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:408
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:105
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