diff --git a/exec/ipc_glue.c b/exec/ipc_glue.c index d32e5cd1..a1d53742 100644 --- a/exec/ipc_glue.c +++ b/exec/ipc_glue.c @@ -706,6 +706,38 @@ cs_error_t cs_ipcs_get_conn_stats(int service_id, uint32_t pid, void *conn_ptr, return CS_OK; } +void cs_ipcs_clear_stats() +{ + struct cs_ipcs_conn_context *cnx; + struct ipcs_conn_stats ipcs_stats; + qb_ipcs_connection_t *c, *prev; + int service_id; + + /* Global stats are easy */ + memset(&global_stats, 0, sizeof(global_stats)); + + for (service_id = 0; service_id < SERVICES_COUNT_MAX; service_id++) { + if (!ipcs_mapper[service_id].inst) { + continue; + } + + for (c = qb_ipcs_connection_first_get(ipcs_mapper[service_id].inst); + c; + prev = c, c = qb_ipcs_connection_next_get(ipcs_mapper[service_id].inst, prev), qb_ipcs_connection_unref(prev)) { + /* Get stats with 'clear_after_read' set */ + qb_ipcs_connection_stats_get(c, &ipcs_stats.conn, QB_TRUE); + + /* Our own stats */ + cnx = qb_ipcs_context_get(c); + if (cnx == NULL) continue; + cnx->invalid_request = 0; + cnx->overload = 0; + cnx->sent = 0; + + } + } +} + static enum qb_ipc_type cs_get_ipc_type (void) { char *str; diff --git a/exec/ipcs_stats.h b/exec/ipcs_stats.h index e73363e5..a8047b30 100644 --- a/exec/ipcs_stats.h +++ b/exec/ipcs_stats.h @@ -58,3 +58,4 @@ struct ipcs_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); void cs_ipcs_get_global_stats(struct ipcs_global_stats *ipcs_stats); +void cs_ipcs_clear_stats(void); diff --git a/exec/stats.c b/exec/stats.c index 19aea79f..0da30a3d 100644 --- a/exec/stats.c +++ b/exec/stats.c @@ -368,12 +368,40 @@ cs_error_t stats_map_get(const char *key_name, return CS_OK; } +#define STATS_CLEAR "stats.clear." +#define STATS_CLEAR_KNET "stats.clear.knet" +#define STATS_CLEAR_IPC "stats.clear.ipc" +#define STATS_CLEAR_TOTEM "stats.clear.totem" +#define STATS_CLEAR_ALL "stats.clear.all" + cs_error_t stats_map_set(const char *key_name, const void *value, size_t value_len, icmap_value_types_t type) { - return CS_ERR_NOT_SUPPORTED; + int cleared = 0; + + if (strncmp(key_name, STATS_CLEAR_KNET, strlen(STATS_CLEAR_KNET)) == 0) { + totempg_stats_clear(TOTEMPG_STATS_CLEAR_TRANSPORT); + cleared = 1; + } + if (strncmp(key_name, STATS_CLEAR_IPC, strlen(STATS_CLEAR_IPC)) == 0) { + cs_ipcs_clear_stats(); + cleared = 1; + } + if (strncmp(key_name, STATS_CLEAR_TOTEM, strlen(STATS_CLEAR_TOTEM)) == 0) { + totempg_stats_clear(TOTEMPG_STATS_CLEAR_TOTEM); + cleared = 1; + } + if (strncmp(key_name, STATS_CLEAR_ALL, strlen(STATS_CLEAR_ALL)) == 0) { + totempg_stats_clear(TOTEMPG_STATS_CLEAR_TRANSPORT | TOTEMPG_STATS_CLEAR_TOTEM); + cs_ipcs_clear_stats(); + cleared = 1; + } + if (!cleared) { + return CS_ERR_NOT_SUPPORTED; + } + return CS_OK; } cs_error_t stats_map_adjust_int(const char *key_name, int32_t step) @@ -388,8 +416,12 @@ cs_error_t stats_map_delete(const char *key_name) int stats_map_is_key_ro(const char *key_name) { - /* It's all read-only */ - return 1; + /* It's all read-only apart from the 'clear' destinations */ + if (strncmp(key_name, STATS_CLEAR, strlen(STATS_CLEAR)) == 0) { + return 0; + } else { + return 1; + } } icmap_iter_t stats_map_iter_init(const char *prefix) diff --git a/exec/totemknet.c b/exec/totemknet.c index 0e02d980..68983a97 100644 --- a/exec/totemknet.c +++ b/exec/totemknet.c @@ -1289,6 +1289,14 @@ int totemknet_reconfigure ( } +void totemknet_stats_clear ( + void *knet_context) +{ + struct totemknet_instance *instance = (struct totemknet_instance *)knet_context; + + (void) knet_handle_clear_stats(instance->knet_handle, KNET_CLEARSTATS_HANDLE_AND_LINK); +} + /* For the stats module */ int totemknet_link_get_status ( knet_node_id_t node, uint8_t link_no, diff --git a/exec/totemknet.h b/exec/totemknet.h index c0c176ff..22a77918 100644 --- a/exec/totemknet.h +++ b/exec/totemknet.h @@ -142,4 +142,7 @@ extern int totemknet_reconfigure ( void *knet_context, struct totem_config *totem_config); +extern void totemknet_stats_clear ( + void *knet_context); + #endif /* TOTEMKNET_H_DEFINED */ diff --git a/exec/totemnet.c b/exec/totemnet.c index e5f779d0..46276f3e 100644 --- a/exec/totemnet.c +++ b/exec/totemnet.c @@ -154,6 +154,9 @@ struct transport { int (*reconfigure) ( void *net_context, struct totem_config *totem_config); + + void (*stats_clear) ( + void *net_context); }; struct transport transport_entries[] = { @@ -222,7 +225,8 @@ struct transport transport_entries[] = { .recv_mcast_empty = totemknet_recv_mcast_empty, .member_add = totemknet_member_add, .member_remove = totemknet_member_remove, - .reconfigure = totemknet_reconfigure + .reconfigure = totemknet_reconfigure, + .stats_clear = totemknet_stats_clear } }; @@ -565,3 +569,14 @@ int totemnet_reconfigure ( return (res); } + +void totemnet_stats_clear ( + void *net_context) +{ + struct totemnet_instance *instance = (struct totemnet_instance *)net_context; + + if (instance->transport->stats_clear) { + instance->transport->stats_clear ( + instance->transport_context); + } +} diff --git a/exec/totemnet.h b/exec/totemnet.h index 9a3902dc..17a3d9a8 100644 --- a/exec/totemnet.h +++ b/exec/totemnet.h @@ -118,6 +118,8 @@ extern int totemnet_net_mtu_adjust (void *net_context, struct totem_config *tote extern int totemnet_reconfigure (void *net_context, struct totem_config *totem_config); +extern void totemnet_stats_clear (void *net_context); + extern const char *totemnet_iface_print (void *net_context); extern int totemnet_ifaces_get ( diff --git a/exec/totempg.c b/exec/totempg.c index 3d66b69b..a40b195b 100644 --- a/exec/totempg.c +++ b/exec/totempg.c @@ -1526,6 +1526,15 @@ extern int totempg_reconfigure (void) return totemsrp_reconfigure (totemsrp_context, totempg_totem_config); } +extern void totempg_stats_clear (int flags) +{ + if (flags & TOTEMPG_STATS_CLEAR_TOTEM) { + totempg_stats.msg_reserved = 0; + totempg_stats.msg_queue_avail = 0; + } + return totemsrp_stats_clear (totemsrp_context, flags); +} + void totempg_threaded_mode_enable (void) { totempg_threaded_mode = 1; diff --git a/exec/totemsrp.c b/exec/totemsrp.c index 0229a02c..78b158d3 100644 --- a/exec/totemsrp.c +++ b/exec/totemsrp.c @@ -4788,3 +4788,13 @@ int totemsrp_reconfigure (void *context, struct totem_config *totem_config) res = totemnet_reconfigure (instance->totemnet_context, totem_config); return (res); } + +void totemsrp_stats_clear (void *context, int flags) +{ + struct totemsrp_instance *instance = (struct totemsrp_instance *)context; + + memset(&instance->stats, 0, sizeof(totemsrp_stats_t)); + if (flags & TOTEMPG_STATS_CLEAR_TRANSPORT) { + totemnet_stats_clear (instance->totemnet_context); + } +} diff --git a/exec/totemsrp.h b/exec/totemsrp.h index 5fa5b7a7..1b80be89 100644 --- a/exec/totemsrp.h +++ b/exec/totemsrp.h @@ -150,4 +150,7 @@ int totemsrp_reconfigure ( void *context, struct totem_config *totem_config); +void totemsrp_stats_clear ( + void *srp_context, int flags); + #endif /* TOTEMSRP_H_DEFINED */ diff --git a/include/corosync/totem/totemstats.h b/include/corosync/totem/totemstats.h index c7d3557e..70672bea 100644 --- a/include/corosync/totem/totemstats.h +++ b/include/corosync/totem/totemstats.h @@ -109,5 +109,9 @@ void stats_knet_add_member(knet_node_id_t nodeid, uint8_t link); void stats_knet_del_member(knet_node_id_t nodeid, uint8_t link); +#define TOTEMPG_STATS_CLEAR_TOTEM 1 +#define TOTEMPG_STATS_CLEAR_TRANSPORT 2 + +extern void totempg_stats_clear (int flags); #endif /* TOTEMSTATS_H_DEFINED */