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 
61 static 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
69 static struct schedmiss_entry schedmiss_event[MAX_SCHEDMISS_EVENTS];
70 static unsigned int highest_schedmiss_event;
71 
72 #define SCHEDMISS_PREFIX "stats.schedmiss"
73 
74 /* Convert iterator number to text and a stats pointer */
75 struct cs_stats_conv {
77  const char *name;
78  const size_t offset;
80 };
81 
82 struct cs_stats_conv cs_pg_stats[] = {
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 };
86 struct cs_stats_conv cs_srp_stats[] = {
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 
119 struct cs_stats_conv cs_knet_stats[] = {
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 */
217 struct stats_item {
218  char *key_name;
220 };
221 
222 /* One of these per tracker */
224 {
225  char *key_name;
226  void *user_data;
227  int32_t events;
229  uint64_t old_value;
230  struct qb_list_head list;
231 };
232 QB_LIST_DECLARE (stats_tracker_list_head);
233 static const struct corosync_api_v1 *api;
234 
235 static 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 
257 static 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 }
267 static 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 
277 static 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 
289 cs_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 
428 static 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 */
447 void 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 
480 cs_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) {
510  return CS_ERR_NOT_SUPPORTED;
511  }
512  return CS_OK;
513 }
514 
515 cs_error_t stats_map_adjust_int(const char *key_name, int32_t step)
516 {
517  return CS_ERR_NOT_SUPPORTED;
518 }
519 
520 cs_error_t stats_map_delete(const char *key_name)
521 {
522  return CS_ERR_NOT_SUPPORTED;
523 }
524 
525 int 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 
541 const 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 */
599 static 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 
637 cs_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))) {
652  return CS_ERR_NOT_SUPPORTED;
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 */
730 void 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 }
740 void 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 */
765 void 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 }
775 void 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
QB_LIST_DECLARE(stats_tracker_list_head)
void * stats_map_track_get_user_data(icmap_track_t icmap_track)
Definition: stats.c:722
#define STATS_CLEAR_TOTEM
Definition: stats.c:476
void stats_add_schedmiss_event(uint64_t timestamp, float delay)
Definition: stats.c:447
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
const char * stats_map_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
Definition: stats.c:541
#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