diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/dialer.c | 224 | ||||
| -rw-r--r-- | src/core/listener.c | 214 | ||||
| -rw-r--r-- | src/core/pipe.c | 156 | ||||
| -rw-r--r-- | src/core/socket.c | 301 | ||||
| -rw-r--r-- | src/core/sockimpl.h | 107 | ||||
| -rw-r--r-- | src/core/stats.c | 363 | ||||
| -rw-r--r-- | src/core/stats.h | 73 |
7 files changed, 865 insertions, 573 deletions
diff --git a/src/core/dialer.c b/src/core/dialer.c index 80b93dc0..3efbcabd 100644 --- a/src/core/dialer.c +++ b/src/core/dialer.c @@ -23,8 +23,6 @@ static void dialer_timer_cb(void *); static nni_id_map dialers; static nni_mtx dialers_lk; -#define BUMP_STAT(x) nni_stat_inc_atomic(x, 1) - int nni_dialer_sys_init(void) { @@ -65,59 +63,129 @@ nni_dialer_destroy(nni_dialer *d) NNI_FREE_STRUCT(d); } +#if NNG_ENABLE_STATS static void -dialer_stats_init(nni_dialer *d) +dialer_stat_init(nni_dialer *d, nni_stat_item *item, const nni_stat_info *info) { - nni_dialer_stats *st = &d->d_stats; - nni_stat_item * root = &st->s_root; - - nni_stat_init_scope(root, st->s_scope, "dialer statistics"); - - nni_stat_init_id(&st->s_id, "id", "dialer id", d->d_id); - nni_stat_add(root, &st->s_id); - - nni_stat_init_id(&st->s_sock, "socket", "socket for dialer", - nni_sock_id(d->d_sock)); - nni_stat_add(root, &st->s_sock); - - nni_stat_init_string( - &st->s_url, "url", "dialer url", d->d_url->u_rawurl); - nni_stat_add(root, &st->s_url); - - nni_stat_init_atomic(&st->s_npipes, "npipes", "open pipes"); - nni_stat_add(root, &st->s_npipes); - - nni_stat_init_atomic( - &st->s_connok, "connect", "connections established"); - nni_stat_add(root, &st->s_connok); - - nni_stat_init_atomic(&st->s_refused, "refused", "connections refused"); - nni_stat_add(root, &st->s_refused); - - nni_stat_init_atomic(&st->s_discon, "discon", "remote disconnects"); - nni_stat_add(root, &st->s_discon); - - nni_stat_init_atomic(&st->s_canceled, "canceled", "canceled"); - nni_stat_add(root, &st->s_canceled); - - nni_stat_init_atomic(&st->s_othererr, "othererr", "other errors"); - nni_stat_add(root, &st->s_othererr); - - nni_stat_init_atomic(&st->s_etimedout, "timedout", "timed out"); - nni_stat_add(root, &st->s_etimedout); - - nni_stat_init_atomic(&st->s_eproto, "protoerr", "protocol errors"); - nni_stat_add(root, &st->s_eproto); - - nni_stat_init_atomic(&st->s_eauth, "autherr", "auth errors"); - nni_stat_add(root, &st->s_eauth); - - nni_stat_init_atomic(&st->s_enomem, "nomem", "out of memory"); - nni_stat_add(root, &st->s_enomem); + nni_stat_init(item, info); + nni_stat_add(&d->st_root, item); +} - nni_stat_init_atomic(&st->s_reject, "reject", "pipes rejected"); - nni_stat_add(root, &st->s_reject); +static void +dialer_stats_init(nni_dialer *d) +{ + static const nni_stat_info root_info = { + .si_name = "dialer", + .si_desc = "dialer statistics", + .si_type = NNG_STAT_SCOPE, + }; + static const nni_stat_info id_info = { + .si_name = "id", + .si_desc = "dialer id", + .si_type = NNG_STAT_ID, + }; + static const nni_stat_info socket_info = { + .si_name = "socket", + .si_desc = "socket for dialer", + .si_type = NNG_STAT_ID, + }; + static const nni_stat_info url_info = { + .si_name = "url", + .si_desc = "dialer url", + .si_type = NNG_STAT_STRING, + .si_alloc = true, + }; + static const nni_stat_info pipes_info = { + .si_name = "pipes", + .si_desc = "open pipes", + .si_type = NNG_STAT_LEVEL, + .si_atomic = true, + }; + static const nni_stat_info connect_info = { + .si_name = "connect", + .si_desc = "connections established", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info refused_info = { + .si_name = "refused", + .si_desc = "connections refused", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info disconnect_info = { + .si_name = "disconnect", + .si_desc = "remote disconnects", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info canceled_info = { + .si_name = "canceled", + .si_desc = "canceled connections", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info other_info = { + .si_name = "other", + .si_desc = "other errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info timeout_info = { + .si_name = "timeout", + .si_desc = "timeout errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info proto_info = { + .si_name = "proto", + .si_desc = "protocol errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info auth_info = { + .si_name = "auth", + .si_desc = "auth errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info oom_info = { + .si_name = "oom", + .si_desc = "allocation failures", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info reject_info = { + .si_name = "reject", + .si_desc = "rejected pipes", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + + nni_stat_init(&d->st_root, &root_info); + + dialer_stat_init(d, &d->st_id, &id_info); + dialer_stat_init(d, &d->st_sock, &socket_info); + dialer_stat_init(d, &d->st_url, &url_info); + dialer_stat_init(d, &d->st_pipes, &pipes_info); + dialer_stat_init(d, &d->st_connect, &connect_info); + dialer_stat_init(d, &d->st_refused, &refused_info); + dialer_stat_init(d, &d->st_disconnect, &disconnect_info); + dialer_stat_init(d, &d->st_canceled, &canceled_info); + dialer_stat_init(d, &d->st_other, &other_info); + dialer_stat_init(d, &d->st_timeout, &timeout_info); + dialer_stat_init(d, &d->st_proto, &proto_info); + dialer_stat_init(d, &d->st_auth, &auth_info); + dialer_stat_init(d, &d->st_oom, &oom_info); + dialer_stat_init(d, &d->st_reject, &reject_info); + + nni_stat_set_id(&d->st_root, d->d_id); + nni_stat_set_id(&d->st_id, d->d_id); + nni_stat_set_id(&d->st_sock, nni_sock_id(d->d_sock)); + nni_stat_set_string(&d->st_url, d->d_url->u_rawurl); + nni_stat_register(&d->st_root); } +#endif // NNG_ENABLE_STATS void nni_dialer_bump_error(nni_dialer *d, int err) @@ -126,34 +194,31 @@ nni_dialer_bump_error(nni_dialer *d, int err) switch (err) { case NNG_ECONNABORTED: case NNG_ECONNRESET: - BUMP_STAT(&d->d_stats.s_discon); + nni_stat_inc(&d->st_disconnect, 1); break; case NNG_ECONNREFUSED: - BUMP_STAT(&d->d_stats.s_refused); + nni_stat_inc(&d->st_refused, 1); break; case NNG_ECANCELED: - BUMP_STAT(&d->d_stats.s_canceled); + nni_stat_inc(&d->st_canceled, 1); break; case NNG_ETIMEDOUT: - BUMP_STAT(&d->d_stats.s_etimedout); + nni_stat_inc(&d->st_timeout, 1); break; case NNG_EPROTO: - BUMP_STAT(&d->d_stats.s_eproto); + nni_stat_inc(&d->st_proto, 1); break; case NNG_EPEERAUTH: case NNG_ECRYPTO: - BUMP_STAT(&d->d_stats.s_eauth); + nni_stat_inc(&d->st_auth, 1); break; case NNG_ENOMEM: - BUMP_STAT(&d->d_stats.s_enomem); + nni_stat_inc(&d->st_oom, 1); break; default: - BUMP_STAT(&d->d_stats.s_othererr); + nni_stat_inc(&d->st_other, 1); break; } -#else - NNI_ARG_UNUSED(d); - NNI_ARG_UNUSED(err); #endif } @@ -182,7 +247,7 @@ nni_dialer_create(nni_dialer **dp, nni_sock *s, const char *urlstr) d->d_closed = false; d->d_closing = false; d->d_data = NULL; - d->d_refcnt = 1; + d->d_ref = 1; d->d_sock = s; d->d_tran = tran; nni_atomic_flag_reset(&d->d_started); @@ -197,7 +262,6 @@ nni_dialer_create(nni_dialer **dp, nni_sock *s, const char *urlstr) nni_mtx_init(&d->d_mtx); - dialer_stats_init(d); nni_aio_init(&d->d_con_aio, dialer_connect_cb, d); nni_aio_init(&d->d_tmo_aio, dialer_timer_cb, d); @@ -205,19 +269,22 @@ nni_dialer_create(nni_dialer **dp, nni_sock *s, const char *urlstr) rv = nni_id_alloc(&dialers, &d->d_id, d); nni_mtx_unlock(&dialers_lk); +#ifdef NNG_ENABLE_STATS + dialer_stats_init(d); +#endif + if ((rv != 0) || ((rv = d->d_ops.d_init(&d->d_data, url, d)) != 0) || ((rv = nni_sock_add_dialer(s, d)) != 0)) { nni_mtx_lock(&dialers_lk); nni_id_remove(&dialers, d->d_id); nni_mtx_unlock(&dialers_lk); +#ifdef NNG_ENABLE_STATS + nni_stat_unregister(&d->st_root); +#endif nni_dialer_destroy(d); return (rv); } - snprintf(d->d_stats.s_scope, sizeof(d->d_stats.s_scope), "dialer%u", - d->d_id); - nni_stat_set_value(&d->d_stats.s_id, d->d_id); - nni_stat_register(&d->d_stats.s_root); *dp = d; return (0); } @@ -234,7 +301,7 @@ nni_dialer_find(nni_dialer **dp, uint32_t id) nni_mtx_lock(&dialers_lk); if ((d = nni_id_get(&dialers, id)) != NULL) { - d->d_refcnt++; + d->d_ref++; *dp = d; } nni_mtx_unlock(&dialers_lk); @@ -249,7 +316,7 @@ nni_dialer_hold(nni_dialer *d) if (d->d_closed) { rv = NNG_ECLOSED; } else { - d->d_refcnt++; + d->d_ref++; rv = 0; } nni_mtx_unlock(&dialers_lk); @@ -260,8 +327,8 @@ void nni_dialer_rele(nni_dialer *d) { nni_mtx_lock(&dialers_lk); - d->d_refcnt--; - if ((d->d_refcnt == 0) && (d->d_closed)) { + d->d_ref--; + if ((d->d_ref == 0) && (d->d_closed)) { nni_reap(&d->d_reap, (nni_cb) nni_dialer_reap, d); } nni_mtx_unlock(&dialers_lk); @@ -326,7 +393,9 @@ dialer_connect_cb(void *arg) switch ((rv = nni_aio_result(aio))) { case 0: - BUMP_STAT(&d->d_stats.s_connok); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&d->st_connect, 1); +#endif nni_dialer_add_pipe(d, nni_aio_get_output(aio, 0)); break; case NNG_ECLOSED: // No further action. @@ -491,7 +560,12 @@ nni_dialer_getopt( } void -nni_dialer_add_stat(nni_dialer *d, nni_stat_item *stat) +nni_dialer_add_stat(nni_dialer *d, nni_stat_item *item) { - nni_stat_add(&d->d_stats.s_root, stat); +#ifdef NNG_ENABLE_STATS + nni_stat_add(&d->st_root, item); +#else + NNI_ARG_UNUSED(d); + NNI_ARG_UNUSED(item); +#endif } diff --git a/src/core/listener.c b/src/core/listener.c index 56850649..83882389 100644 --- a/src/core/listener.c +++ b/src/core/listener.c @@ -24,8 +24,6 @@ static void listener_timer_cb(void *); static nni_id_map listeners; static nni_mtx listeners_lk; -#define BUMP_STAT(x) nni_stat_inc_atomic(x, 1) - int nni_listener_sys_init(void) { @@ -65,56 +63,122 @@ nni_listener_destroy(nni_listener *l) NNI_FREE_STRUCT(l); } +#ifdef NNG_ENABLE_STATS static void -listener_stats_init(nni_listener *l) +listener_stat_init( + nni_listener *l, nni_stat_item *item, const nni_stat_info *info) { - nni_listener_stats *st = &l->l_stats; - nni_stat_item * root = &st->s_root; - - nni_stat_init_scope(root, st->s_scope, "listener statistics"); - - // NB: This will be updated later. - nni_stat_init_id(&st->s_id, "id", "listener id", l->l_id); - nni_stat_add(root, &st->s_id); - - nni_stat_init_id(&st->s_sock, "socket", "socket for listener", - nni_sock_id(l->l_sock)); - nni_stat_add(root, &st->s_sock); - - nni_stat_init_string( - &st->s_url, "url", "listener url", l->l_url->u_rawurl); - nni_stat_add(root, &st->s_url); - - nni_stat_init_atomic(&st->s_npipes, "npipes", "open pipes"); - nni_stat_add(root, &st->s_npipes); - - nni_stat_init_atomic(&st->s_accept, "accept", "connections accepted"); - nni_stat_add(root, &st->s_accept); - - nni_stat_init_atomic(&st->s_discon, "discon", "remote disconnects"); - nni_stat_add(root, &st->s_discon); - - nni_stat_init_atomic(&st->s_canceled, "canceled", "canceled"); - nni_stat_add(root, &st->s_canceled); - - nni_stat_init_atomic(&st->s_othererr, "othererr", "other errors"); - nni_stat_add(root, &st->s_othererr); - - nni_stat_init_atomic(&st->s_etimedout, "timedout", "timed out"); - nni_stat_add(root, &st->s_etimedout); - - nni_stat_init_atomic(&st->s_eproto, "protoerr", "protocol errors"); - nni_stat_add(root, &st->s_eproto); - - nni_stat_init_atomic(&st->s_eauth, "autherr", "auth errors"); - nni_stat_add(root, &st->s_eauth); - - nni_stat_init_atomic(&st->s_enomem, "nomem", "out of memory"); - nni_stat_add(root, &st->s_enomem); + nni_stat_init(item, info); + nni_stat_add(&l->st_root, item); +} - nni_stat_init_atomic(&st->s_reject, "reject", "pipes rejected"); - nni_stat_add(root, &st->s_reject); +static void +listener_stats_init(nni_listener *l) +{ + static const nni_stat_info root_info = { + .si_name = "listener", + .si_desc = "listener statistics", + .si_type = NNG_STAT_SCOPE, + }; + static const nni_stat_info id_info = { + .si_name = "id", + .si_desc = "listener id", + .si_type = NNG_STAT_ID, + }; + static const nni_stat_info sock_info = { + .si_name = "socket", + .si_desc = "socket id", + .si_type = NNG_STAT_ID, + }; + static const nni_stat_info url_info = { + .si_name = "url", + .si_desc = "listener url", + .si_type = NNG_STAT_STRING, + .si_alloc = true, + }; + static const nni_stat_info pipes_info = { + .si_name = "pipes", + .si_desc = "open pipes", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info accept_info = { + .si_name = "accept", + .si_desc = "connections accepted", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info disconnect_info = { + .si_name = "disconnect", + .si_desc = "remote disconnects", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info canceled_info = { + .si_name = "canceled", + .si_desc = "canceled connections", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info other_info = { + .si_name = "other", + .si_desc = "other errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info timeout_info = { + .si_name = "timeout", + .si_desc = "timeout errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info proto_info = { + .si_name = "proto", + .si_desc = "protocol errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info auth_info = { + .si_name = "auth", + .si_desc = "auth errors", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info oom_info = { + .si_name = "oom", + .si_desc = "allocation failures", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info reject_info = { + .si_name = "reject", + .si_desc = "rejected pipes", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + + nni_stat_init(&l->st_root, &root_info); + + listener_stat_init(l, &l->st_id, &id_info); + listener_stat_init(l, &l->st_sock, &sock_info); + listener_stat_init(l, &l->st_url, &url_info); + listener_stat_init(l, &l->st_pipes, &pipes_info); + listener_stat_init(l, &l->st_accept, &accept_info); + listener_stat_init(l, &l->st_disconnect, &disconnect_info); + listener_stat_init(l, &l->st_canceled, &canceled_info); + listener_stat_init(l, &l->st_other, &other_info); + listener_stat_init(l, &l->st_timeout, &timeout_info); + listener_stat_init(l, &l->st_proto, &proto_info); + listener_stat_init(l, &l->st_auth, &auth_info); + listener_stat_init(l, &l->st_oom, &oom_info); + listener_stat_init(l, &l->st_reject, &reject_info); + + nni_stat_set_id(&l->st_root, l->l_id); + nni_stat_set_id(&l->st_id, l->l_id); + nni_stat_set_string(&l->st_url, l->l_url->u_rawurl); + nni_stat_register(&l->st_root); } +#endif // NNG_ENABLE_STATS void nni_listener_bump_error(nni_listener *l, int err) @@ -123,31 +187,28 @@ nni_listener_bump_error(nni_listener *l, int err) switch (err) { case NNG_ECONNABORTED: case NNG_ECONNRESET: - BUMP_STAT(&l->l_stats.s_discon); + nni_stat_inc(&l->st_disconnect, 1); break; case NNG_ECANCELED: - BUMP_STAT(&l->l_stats.s_canceled); + nni_stat_inc(&l->st_canceled, 1); break; case NNG_ETIMEDOUT: - BUMP_STAT(&l->l_stats.s_etimedout); + nni_stat_inc(&l->st_timeout, 1); break; case NNG_EPROTO: - BUMP_STAT(&l->l_stats.s_eproto); + nni_stat_inc(&l->st_proto, 1); break; case NNG_EPEERAUTH: case NNG_ECRYPTO: - BUMP_STAT(&l->l_stats.s_eauth); + nni_stat_inc(&l->st_auth, 1); break; case NNG_ENOMEM: - BUMP_STAT(&l->l_stats.s_enomem); + nni_stat_inc(&l->st_oom, 1); break; default: - BUMP_STAT(&l->l_stats.s_othererr); + nni_stat_inc(&l->st_other, 1); break; } -#else - NNI_ARG_UNUSED(l); - NNI_ARG_UNUSED(err); #endif } @@ -176,7 +237,7 @@ nni_listener_create(nni_listener **lp, nni_sock *s, const char *url_str) l->l_closed = false; l->l_closing = false; l->l_data = NULL; - l->l_refcnt = 1; + l->l_ref = 1; l->l_sock = s; l->l_tran = tran; nni_atomic_flag_reset(&l->l_started); @@ -188,7 +249,6 @@ nni_listener_create(nni_listener **lp, nni_sock *s, const char *url_str) NNI_LIST_NODE_INIT(&l->l_node); NNI_LIST_INIT(&l->l_pipes, nni_pipe, p_ep_node); - listener_stats_init(l); nni_aio_init(&l->l_acc_aio, listener_accept_cb, l); nni_aio_init(&l->l_tmo_aio, listener_timer_cb, l); @@ -197,21 +257,22 @@ nni_listener_create(nni_listener **lp, nni_sock *s, const char *url_str) rv = nni_id_alloc(&listeners, &l->l_id, l); nni_mtx_unlock(&listeners_lk); +#ifdef NNG_ENABLE_STATS + listener_stats_init(l); +#endif + if ((rv != 0) || ((rv = l->l_ops.l_init(&l->l_data, url, l)) != 0) || ((rv = nni_sock_add_listener(s, l)) != 0)) { nni_mtx_lock(&listeners_lk); nni_id_remove(&listeners, l->l_id); nni_mtx_unlock(&listeners_lk); +#ifdef NNG_ENABLE_STATS + nni_stat_unregister(&l->st_root); +#endif nni_listener_destroy(l); return (rv); } - // Update a few stat bits, and register them. - snprintf(l->l_stats.s_scope, sizeof(l->l_stats.s_scope), "listener%u", - l->l_id); - nni_stat_set_value(&l->l_stats.s_id, l->l_id); - nni_stat_register(&l->l_stats.s_root); - *lp = l; return (0); } @@ -228,7 +289,7 @@ nni_listener_find(nni_listener **lp, uint32_t id) nni_mtx_lock(&listeners_lk); if ((l = nni_id_get(&listeners, id)) != NULL) { - l->l_refcnt++; + l->l_ref++; *lp = l; } nni_mtx_unlock(&listeners_lk); @@ -243,7 +304,7 @@ nni_listener_hold(nni_listener *l) if (l->l_closed) { rv = NNG_ECLOSED; } else { - l->l_refcnt++; + l->l_ref++; rv = 0; } nni_mtx_unlock(&listeners_lk); @@ -254,8 +315,8 @@ void nni_listener_rele(nni_listener *l) { nni_mtx_lock(&listeners_lk); - l->l_refcnt--; - if ((l->l_refcnt == 0) && (l->l_closed)) { + l->l_ref--; + if ((l->l_ref == 0) && (l->l_closed)) { nni_reap(&l->l_reap, (nni_cb) nni_listener_reap, l); } nni_mtx_unlock(&listeners_lk); @@ -315,7 +376,9 @@ listener_accept_cb(void *arg) switch ((rv = nni_aio_result(aio))) { case 0: - BUMP_STAT(&l->l_stats.s_accept); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&l->st_accept, 1); +#endif nni_listener_add_pipe(l, nni_aio_get_output(aio, 0)); listener_accept_start(l); break; @@ -441,7 +504,12 @@ nni_listener_getopt( } void -nni_listener_add_stat(nni_listener *l, nni_stat_item *stat) +nni_listener_add_stat(nni_listener *l, nni_stat_item *item) { - nni_stat_add(&l->l_stats.s_root, stat); +#if NNG_ENABLE_STATS + nni_stat_add(&l->st_root, item); +#else + NNI_ARG_UNUSED(l); + NNI_ARG_UNUSED(item); +#endif } diff --git a/src/core/pipe.c b/src/core/pipe.c index b93d9f64..8ba35b2b 100644 --- a/src/core/pipe.c +++ b/src/core/pipe.c @@ -58,7 +58,7 @@ pipe_destroy(nni_pipe *p) nni_id_remove(&pipes, p->p_id); } // This wait guarantees that all callers are done with us. - while (p->p_refcnt != 0) { + while (p->p_ref != 0) { nni_cv_wait(&p->p_cv); } nni_mtx_unlock(&pipes_lk); @@ -70,7 +70,9 @@ pipe_destroy(nni_pipe *p) p->p_tran_ops.p_stop(p->p_tran_data); } - nni_stat_unregister(&p->p_stats.s_root); +#ifdef NNG_ENABLE_STATS + nni_stat_unregister(&p->st_root); +#endif nni_pipe_remove(p); if (p->p_proto_data != NULL) { @@ -93,9 +95,9 @@ nni_pipe_find(nni_pipe **pp, uint32_t id) // access to the pipe in order to obtain properties (which may // be retried during the post-close notification callback) or to // close the pipe. - nni_mtx_lock(&pipes_lk); + nni_mtx_lock(&pipes_lk); if ((p = nni_id_get(&pipes, id)) != NULL) { - p->p_refcnt++; + p->p_ref++; *pp = p; } nni_mtx_unlock(&pipes_lk); @@ -106,8 +108,8 @@ void nni_pipe_rele(nni_pipe *p) { nni_mtx_lock(&pipes_lk); - p->p_refcnt--; - if (p->p_refcnt == 0) { + p->p_ref--; + if (p->p_ref == 0) { nni_cv_wake(&p->p_cv); } nni_mtx_unlock(&pipes_lk); @@ -165,6 +167,75 @@ nni_pipe_peer(nni_pipe *p) return (p->p_tran_ops.p_peer(p->p_tran_data)); } +#ifdef NNG_ENABLE_STATS +static void +pipe_stat_init(nni_pipe *p, nni_stat_item *item, const nni_stat_info *info) +{ + nni_stat_init(item, info); + nni_stat_add(&p->st_root, item); +} + +static void +pipe_stats_init(nni_pipe *p) +{ + static const nni_stat_info root_info = { + .si_name = "pipe", + .si_desc = "pipe statistics", + .si_type = NNG_STAT_SCOPE, + }; + static const nni_stat_info id_info = { + .si_name = "id", + .si_desc = "pipe id", + .si_type = NNG_STAT_ID, + }; + static const nni_stat_info socket_info = { + .si_name = "socket", + .si_desc = "socket for pipe", + .si_type = NNG_STAT_ID, + }; + static const nni_stat_info rx_msgs_info = { + .si_name = "rx_msgs", + .si_desc = "messages received", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_MESSAGES, + .si_atomic = true, + }; + static const nni_stat_info tx_msgs_info = { + .si_name = "tx_msgs", + .si_desc = "messages sent", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_MESSAGES, + .si_atomic = true, + }; + static const nni_stat_info rx_bytes_info = { + .si_name = "rx_bytes", + .si_desc = "bytes received", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_BYTES, + .si_atomic = true, + }; + static const nni_stat_info tx_bytes_info = { + .si_name = "tx_bytes", + .si_desc = "bytes sent", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_BYTES, + .si_atomic = true, + }; + + nni_stat_init(&p->st_root, &root_info); + pipe_stat_init(p, &p->st_id, &id_info); + pipe_stat_init(p, &p->st_sock_id, &socket_info); + pipe_stat_init(p, &p->st_rx_msgs, &rx_msgs_info); + pipe_stat_init(p, &p->st_tx_msgs, &tx_msgs_info); + pipe_stat_init(p, &p->st_rx_bytes, &rx_bytes_info); + pipe_stat_init(p, &p->st_tx_bytes, &tx_bytes_info); + + nni_stat_set_id(&p->st_root, p->p_id); + nni_stat_set_id(&p->st_id, p->p_id); + nni_stat_set_id(&p->st_sock_id, nni_sock_id(p->p_sock)); +} +#endif // NNG_ENABLE_STATS + static int pipe_create(nni_pipe **pp, nni_sock *sock, nni_tran *tran, void *tdata) { @@ -172,7 +243,6 @@ pipe_create(nni_pipe **pp, nni_sock *sock, nni_tran *tran, void *tdata) int rv; void * sdata = nni_sock_proto_data(sock); nni_proto_pipe_ops *pops = nni_sock_proto_pipe_ops(sock); - nni_pipe_stats * st; size_t sz; sz = NNI_ALIGN_UP(sizeof(*p)) + pops->pipe_size; @@ -191,8 +261,7 @@ pipe_create(nni_pipe **pp, nni_sock *sock, nni_tran *tran, void *tdata) p->p_sock = sock; p->p_closed = false; p->p_cbs = false; - p->p_refcnt = 0; - st = &p->p_stats; + p->p_ref = 0; nni_atomic_flag_reset(&p->p_stop); NNI_LIST_NODE_INIT(&p->p_sock_node); @@ -203,32 +272,13 @@ pipe_create(nni_pipe **pp, nni_sock *sock, nni_tran *tran, void *tdata) nni_mtx_lock(&pipes_lk); if ((rv = nni_id_alloc(&pipes, &p->p_id, p)) == 0) { - p->p_refcnt = 1; + p->p_ref = 1; } nni_mtx_unlock(&pipes_lk); - snprintf(st->s_scope, sizeof(st->s_scope), "pipe%u", p->p_id); - - nni_stat_init_scope(&st->s_root, st->s_scope, "pipe statistics"); - - nni_stat_init_id(&st->s_id, "id", "pipe id", p->p_id); - nni_stat_add(&st->s_root, &st->s_id); - - nni_stat_init_id(&st->s_sock_id, "socket", "socket for pipe", - nni_sock_id(p->p_sock)); - nni_stat_add(&st->s_root, &st->s_sock_id); - nni_stat_init_atomic(&st->s_rxmsgs, "rxmsgs", "messages received"); - nni_stat_set_unit(&st->s_rxmsgs, NNG_UNIT_MESSAGES); - nni_stat_add(&st->s_root, &st->s_rxmsgs); - nni_stat_init_atomic(&st->s_txmsgs, "txmsgs", "messages sent"); - nni_stat_set_unit(&st->s_txmsgs, NNG_UNIT_MESSAGES); - nni_stat_add(&st->s_root, &st->s_txmsgs); - nni_stat_init_atomic(&st->s_rxbytes, "rxbytes", "bytes received"); - nni_stat_set_unit(&st->s_rxbytes, NNG_UNIT_BYTES); - nni_stat_add(&st->s_root, &st->s_rxbytes); - nni_stat_init_atomic(&st->s_txbytes, "txbytes", "bytes sent"); - nni_stat_set_unit(&st->s_txbytes, NNG_UNIT_BYTES); - nni_stat_add(&st->s_root, &st->s_txbytes); +#ifdef NNG_ENABLE_STATS + pipe_stats_init(p); +#endif if ((rv != 0) || ((rv = p->p_tran_ops.p_init(tdata, p)) != 0) || ((rv = pops->pipe_init(p->p_proto_data, p, sdata)) != 0)) { @@ -247,18 +297,20 @@ nni_pipe_create_dialer(nni_pipe **pp, nni_dialer *d, void *tdata) int rv; nni_tran * tran = d->d_tran; nni_pipe * p; - nni_stat_item *st; -#ifdef NNG_ENABLE_STATS - uint64_t id = nni_dialer_id(d); -#endif if ((rv = pipe_create(&p, d->d_sock, tran, tdata)) != 0) { return (rv); } - st = &p->p_stats.s_ep_id; p->p_dialer = d; - nni_stat_init_id(st, "dialer", "dialer for pipe", id); - nni_pipe_add_stat(p, st); +#ifdef NNG_ENABLE_STATS + static const nni_stat_info dialer_info = { + .si_name = "dialer", + .si_desc = "dialer for pipe", + .si_type = NNG_STAT_ID, + }; + pipe_stat_init(p, &p->st_ep_id, &dialer_info); + nni_stat_set_id(&p->st_ep_id, nni_dialer_id(d)); +#endif *pp = p; return (0); } @@ -269,18 +321,20 @@ nni_pipe_create_listener(nni_pipe **pp, nni_listener *l, void *tdata) int rv; nni_tran * tran = l->l_tran; nni_pipe * p; - nni_stat_item *st; -#ifdef NNG_ENABLE_STATS - uint64_t id = nni_listener_id(l); -#endif if ((rv = pipe_create(&p, l->l_sock, tran, tdata)) != 0) { return (rv); } - st = &p->p_stats.s_ep_id; p->p_listener = l; - nni_stat_init_id(st, "listener", "listener for pipe", id); - nni_pipe_add_stat(p, st); +#if NNG_ENABLE_STATS + static const nni_stat_info listener_info = { + .si_name = "listener", + .si_desc = "listener for pipe", + .si_type = NNG_STAT_ID, + }; + pipe_stat_init(p, &p->st_ep_id, &listener_info); + nni_stat_set_id(&p->st_ep_id, nni_listener_id(l)); +#endif *pp = p; return (0); } @@ -334,15 +388,15 @@ nni_pipe_dialer_id(nni_pipe *p) void nni_pipe_add_stat(nni_pipe *p, nni_stat_item *item) { - nni_stat_add(&p->p_stats.s_root, item); + nni_stat_add(&p->st_root, item); } void nni_pipe_bump_rx(nni_pipe *p, size_t nbytes) { #ifdef NNG_ENABLE_STATS - nni_stat_inc_atomic(&p->p_stats.s_rxbytes, nbytes); - nni_stat_inc_atomic(&p->p_stats.s_rxmsgs, 1); + nni_stat_inc(&p->st_rx_bytes, nbytes); + nni_stat_inc(&p->st_rx_msgs, 1); #else NNI_ARG_UNUSED(p); NNI_ARG_UNUSED(nbytes); @@ -353,8 +407,8 @@ void nni_pipe_bump_tx(nni_pipe *p, size_t nbytes) { #ifdef NNG_ENABLE_STATS - nni_stat_inc_atomic(&p->p_stats.s_txbytes, nbytes); - nni_stat_inc_atomic(&p->p_stats.s_txmsgs, 1); + nni_stat_inc(&p->st_tx_bytes, nbytes); + nni_stat_inc(&p->st_tx_msgs, 1); #else NNI_ARG_UNUSED(p); NNI_ARG_UNUSED(nbytes); diff --git a/src/core/socket.c b/src/core/socket.c index 66130d4a..11b1371e 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -29,7 +29,7 @@ struct nni_ctx { void * c_data; size_t c_size; bool c_closed; - unsigned c_refcnt; // protected by global lock + unsigned c_ref; // protected by global lock uint32_t c_id; nng_duration c_sndtimeo; nng_duration c_rcvtimeo; @@ -48,21 +48,6 @@ typedef struct nni_sock_pipe_cb { void * cb_arg; } nni_sock_pipe_cb; -typedef struct sock_stats { - nni_stat_item s_root; // socket scope - nni_stat_item s_id; // socket id - nni_stat_item s_name; // socket name - nni_stat_item s_protocol; // socket protocol - nni_stat_item s_ndialers; // number of dialers - nni_stat_item s_nlisteners; // number of listeners - nni_stat_item s_npipes; // number of pipes - nni_stat_item s_rxbytes; // number of bytes received - nni_stat_item s_txbytes; // number of bytes received - nni_stat_item s_rxmsgs; // number of msgs received - nni_stat_item s_txmsgs; // number of msgs sent - nni_stat_item s_reject; // pipes rejected -} sock_stats; - struct nni_socket { nni_list_node s_node; nni_mtx s_mx; @@ -71,8 +56,8 @@ struct nni_socket { uint32_t s_id; uint32_t s_flags; - unsigned s_refcnt; // protected by global lock - void * s_data; // Protocol private + unsigned s_ref; // protected by global lock + void * s_data; // Protocol private size_t s_size; nni_msgq *s_uwq; // Upper write queue @@ -93,7 +78,6 @@ struct nni_socket { size_t s_rcvmaxsz; // max receive size nni_list s_options; // opts not handled by sock/proto char s_name[64]; // socket name (legacy compat) - char s_scope[24]; // socket scope ("socket%u", 32 bits max) nni_list s_listeners; // active listeners nni_list s_dialers; // active dialers @@ -107,7 +91,20 @@ struct nni_socket { nni_mtx s_pipe_cbs_mtx; nni_sock_pipe_cb s_pipe_cbs[NNG_PIPE_EV_NUM]; - sock_stats s_stats; +#ifdef NNG_ENABLE_STATS + nni_stat_item st_root; // socket scope + nni_stat_item st_id; // socket id + nni_stat_item st_name; // socket name + nni_stat_item st_protocol; // socket protocol + nni_stat_item st_dialers; // number of dialers + nni_stat_item st_listeners; // number of listeners + nni_stat_item st_pipes; // number of pipes + nni_stat_item st_rx_bytes; // number of bytes received + nni_stat_item st_tx_bytes; // number of bytes received + nni_stat_item st_rx_msgs; // number of msgs received + nni_stat_item st_tx_msgs; // number of msgs sent + nni_stat_item st_rejects; // pipes rejected +#endif }; static void nni_ctx_destroy(nni_ctx *); @@ -379,7 +376,7 @@ nni_sock_find(nni_sock **sockp, uint32_t id) if (s->s_closed) { rv = NNG_ECLOSED; } else { - s->s_refcnt++; + s->s_ref++; *sockp = s; } } else { @@ -394,88 +391,129 @@ void nni_sock_rele(nni_sock *s) { nni_mtx_lock(&sock_lk); - s->s_refcnt--; - if (s->s_closed && (s->s_refcnt < 2)) { + s->s_ref--; + if (s->s_closed && (s->s_ref < 2)) { nni_cv_wake(&s->s_close_cv); } nni_mtx_unlock(&sock_lk); } +#ifdef NNG_ENABLE_STATS static void -sock_stats_fini(nni_sock *s) +sock_stat_init(nni_sock *s, nni_stat_item *item, const nni_stat_info *info) { -#ifdef NNG_ENABLE_STATS - sock_stats *st = &s->s_stats; - nni_stat_unregister(&st->s_root); -#else - NNI_ARG_UNUSED(s); -#endif + nni_stat_init(item, info); + nni_stat_add(&s->st_root, item); } static void sock_stats_init(nni_sock *s) { -#ifdef NNG_ENABLE_STATS - sock_stats * st = &s->s_stats; - nni_stat_item *root = &s->s_stats.s_root; + static const nni_stat_info root_info = { + .si_name = "socket", + .si_desc = "socket statistics", + .si_type = NNG_STAT_SCOPE, + }; + static const nni_stat_info id_info = { + .si_name = "id", + .si_desc = "socket identifier", + .si_type = NNG_STAT_ID, + }; + static const nni_stat_info name_info = { + .si_name = "name", + .si_desc = "socket name", + .si_type = NNG_STAT_STRING, + .si_alloc = true, + }; + static const nni_stat_info protocol_info = { + .si_name = "protocol", + .si_desc = "socket protocol", + .si_type = NNG_STAT_STRING, + }; + static const nni_stat_info dialers_info = { + .si_name = "dialers", + .si_desc = "open dialers", + .si_type = NNG_STAT_LEVEL, + .si_atomic = true, + }; + static const nni_stat_info listeners_info = { + .si_name = "listeners", + .si_desc = "open listeners", + .si_type = NNG_STAT_LEVEL, + .si_atomic = true, + }; + static const nni_stat_info pipes_info = { + .si_name = "pipes", + .si_desc = "open pipes", + .si_type = NNG_STAT_LEVEL, + .si_atomic = true, + }; + static const nni_stat_info reject_info = { + .si_name = "reject", + .si_desc = "rejected pipes", + .si_type = NNG_STAT_COUNTER, + .si_atomic = true, + }; + static const nni_stat_info tx_msgs_info = { + .si_name = "tx_msgs", + .si_desc = "sent messages", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_MESSAGES, + .si_atomic = true, + }; + static const nni_stat_info rx_msgs_info = { + .si_name = "rx_msgs", + .si_desc = "received messages", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_MESSAGES, + .si_atomic = true, + }; + static const nni_stat_info tx_bytes_info = { + .si_name = "tx_bytes", + .si_desc = "sent bytes", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_BYTES, + .si_atomic = true, + }; + static const nni_stat_info rx_bytes_info = { + .si_name = "rx_bytes", + .si_desc = "received messages", + .si_type = NNG_STAT_COUNTER, + .si_unit = NNG_UNIT_BYTES, + .si_atomic = true, + }; // To make collection cheap and atomic for the socket, // we just use a single lock for the entire chain. - nni_stat_init_scope(root, s->s_scope, "socket statistics"); - - nni_stat_init_id(&st->s_id, "id", "socket id", s->s_id); - nni_stat_add(root, &st->s_id); - - nni_stat_init_string(&st->s_name, "name", "socket name", s->s_name); - nni_stat_set_lock(&st->s_name, &s->s_mx); - nni_stat_add(root, &st->s_name); - - nni_stat_init_string(&st->s_protocol, "protocol", "socket protocol", - nni_sock_proto_name(s)); - nni_stat_add(root, &st->s_protocol); - - nni_stat_init_atomic(&st->s_ndialers, "ndialers", "open dialers"); - nni_stat_set_type(&st->s_ndialers, NNG_STAT_LEVEL); - nni_stat_add(root, &st->s_ndialers); - - nni_stat_init_atomic( - &st->s_nlisteners, "nlisteners", "open listeners"); - nni_stat_set_type(&st->s_nlisteners, NNG_STAT_LEVEL); - nni_stat_add(root, &st->s_nlisteners); - - nni_stat_init_atomic(&st->s_npipes, "npipes", "open pipes"); - nni_stat_set_type(&st->s_npipes, NNG_STAT_LEVEL); - nni_stat_add(root, &st->s_npipes); - - nni_stat_init_atomic(&st->s_rxbytes, "rxbytes", "bytes received"); - nni_stat_set_unit(&st->s_rxbytes, NNG_UNIT_BYTES); - nni_stat_add(root, &st->s_rxbytes); - - nni_stat_init_atomic(&st->s_txbytes, "txbytes", "bytes sent"); - nni_stat_set_unit(&st->s_txbytes, NNG_UNIT_BYTES); - nni_stat_add(root, &st->s_txbytes); - - nni_stat_init_atomic(&st->s_rxmsgs, "rxmsgs", "messages received"); - nni_stat_set_unit(&st->s_rxmsgs, NNG_UNIT_MESSAGES); - nni_stat_add(root, &st->s_rxmsgs); - - nni_stat_init_atomic(&st->s_txmsgs, "txmsgs", "messages sent"); - nni_stat_set_unit(&st->s_txmsgs, NNG_UNIT_MESSAGES); - nni_stat_add(root, &st->s_txmsgs); - - nni_stat_init_atomic(&st->s_reject, "reject", "pipes rejected"); - nni_stat_add(root, &st->s_reject); -#else - NNI_ARG_UNUSED(s); -#endif + nni_stat_init(&s->st_root, &root_info); + sock_stat_init(s, &s->st_id, &id_info); + sock_stat_init(s, &s->st_name, &name_info); + sock_stat_init(s, &s->st_protocol, &protocol_info); + sock_stat_init(s, &s->st_dialers, &dialers_info); + sock_stat_init(s, &s->st_listeners, &listeners_info); + sock_stat_init(s, &s->st_pipes, &pipes_info); + sock_stat_init(s, &s->st_rejects, &reject_info); + sock_stat_init(s, &s->st_tx_msgs, &tx_msgs_info); + sock_stat_init(s, &s->st_rx_msgs, &rx_msgs_info); + sock_stat_init(s, &s->st_tx_bytes, &tx_bytes_info); + sock_stat_init(s, &s->st_rx_bytes, &rx_bytes_info); + + nni_stat_set_id(&s->st_id, s->s_id); + nni_stat_set_string(&s->st_name, s->s_name); + nni_stat_set_string(&s->st_protocol, nni_sock_proto_name(s)); } +#endif static void sock_destroy(nni_sock *s) { nni_sockopt *sopt; +#ifdef NNG_ENABLE_STATS + nni_stat_unregister(&s->st_root); +#endif + // The protocol needs to clean up its state. if (s->s_data != NULL) { s->s_sock_ops.sock_fini(s->s_data); @@ -490,7 +528,6 @@ sock_destroy(nni_sock *s) nni_mtx_lock(&s->s_mx); nni_mtx_unlock(&s->s_mx); - sock_stats_fini(s); nni_msgq_fini(s->s_urq); nni_msgq_fini(s->s_uwq); nni_cv_fini(&s->s_close_cv); @@ -519,7 +556,7 @@ nni_sock_create(nni_sock **sp, const nni_proto *proto) s->s_reconnmax = 0; s->s_rcvmaxsz = 0; // unlimited by default s->s_id = 0; - s->s_refcnt = 0; + s->s_ref = 0; s->s_self_id = proto->proto_self; s->s_peer_id = proto->proto_peer; s->s_flags = proto->proto_flags; @@ -545,7 +582,10 @@ nni_sock_create(nni_sock **sp, const nni_proto *proto) nni_mtx_init(&s->s_pipe_cbs_mtx); nni_cv_init(&s->s_cv, &s->s_mx); nni_cv_init(&s->s_close_cv, &sock_lk); + +#ifdef NNG_ENABLE_STATS sock_stats_init(s); +#endif if (((rv = nni_msgq_init(&s->s_uwq, 0)) != 0) || ((rv = nni_msgq_init(&s->s_urq, 1)) != 0) || @@ -629,11 +669,10 @@ nni_sock_open(nni_sock **sockp, const nni_proto *proto) (void) snprintf(s->s_name, sizeof(s->s_name), "%u", s->s_id); // Set up basic stat values. - (void) snprintf(s->s_scope, sizeof(s->s_scope), "socket%u", s->s_id); - nni_stat_set_value(&s->s_stats.s_id, s->s_id); + nni_stat_set_id(&s->st_id, s->s_id); // Add our stats chain. - nni_stat_register(&s->s_stats.s_root); + nni_stat_register(&s->st_root); return (0); } @@ -677,7 +716,7 @@ nni_sock_shutdown(nni_sock *sock) while ((ctx = nctx) != NULL) { nctx = nni_list_next(&sock->s_ctxs, ctx); ctx->c_closed = true; - if (ctx->c_refcnt == 0) { + if (ctx->c_ref == 0) { // No open operations. So close it. nni_id_remove(&ctx_ids, ctx->c_id); nni_list_remove(&sock->s_ctxs, ctx); @@ -767,8 +806,6 @@ nni_sock_close(nni_sock *s) // is idempotent. nni_sock_shutdown(s); - nni_stat_unregister(&s->s_stats.s_root); - nni_mtx_lock(&sock_lk); if (s->s_closed) { // Some other thread called close. All we need to do @@ -787,7 +824,7 @@ nni_sock_close(nni_sock *s) // Wait for all other references to drop. Note that we // have a reference already (from our caller). s->s_ctxwait = true; - while ((s->s_refcnt > 1) || (!nni_list_empty(&s->s_ctxs))) { + while ((s->s_ref > 1) || (!nni_list_empty(&s->s_ctxs))) { nni_cv_wait(&s->s_close_cv); } nni_mtx_unlock(&sock_lk); @@ -819,7 +856,7 @@ nni_sock_closeall(void) } // Bump the reference count. The close call below // will drop it. - s->s_refcnt++; + s->s_ref++; nni_list_node_remove(&s->s_node); nni_mtx_unlock(&sock_lk); nni_sock_close(s); @@ -901,7 +938,9 @@ nni_sock_add_listener(nni_sock *s, nni_listener *l) nni_list_append(&s->s_listeners, l); - nni_stat_inc_atomic(&s->s_stats.s_nlisteners, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&s->st_listeners, 1); +#endif nni_mtx_unlock(&s->s_mx); return (0); @@ -930,7 +969,9 @@ nni_sock_add_dialer(nni_sock *s, nni_dialer *d) nni_list_append(&s->s_dialers, d); - nni_stat_inc_atomic(&s->s_stats.s_ndialers, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&s->st_dialers, 1); +#endif nni_mtx_unlock(&s->s_mx); return (0); @@ -1159,7 +1200,7 @@ nni_ctx_find(nni_ctx **cp, uint32_t id, bool closing) if (ctx->c_closed || ((!closing) && ctx->c_sock->s_closed)) { rv = NNG_ECLOSED; } else { - ctx->c_refcnt++; + ctx->c_ref++; *cp = ctx; } } else { @@ -1186,8 +1227,8 @@ nni_ctx_rele(nni_ctx *ctx) { nni_sock *sock = ctx->c_sock; nni_mtx_lock(&sock_lk); - ctx->c_refcnt--; - if ((ctx->c_refcnt > 0) || (!ctx->c_closed)) { + ctx->c_ref--; + if ((ctx->c_ref > 0) || (!ctx->c_closed)) { // Either still have an active reference, or not // actually closing yet. nni_mtx_unlock(&sock_lk); @@ -1225,7 +1266,7 @@ nni_ctx_open(nni_ctx **ctxp, nni_sock *sock) ctx->c_size = sz; ctx->c_data = ctx + 1; ctx->c_closed = false; - ctx->c_refcnt = 1; // Caller implicitly gets a reference. + ctx->c_ref = 1; // Caller implicitly gets a reference. ctx->c_sock = sock; ctx->c_ops = sock->s_ctx_ops; ctx->c_rcvtimeo = sock->s_rcvtimeo; @@ -1413,29 +1454,37 @@ nni_dialer_add_pipe(nni_dialer *d, void *tpipe) d->d_pipe = p; d->d_currtime = d->d_inirtime; nni_mtx_unlock(&s->s_mx); - nni_stat_inc_atomic(&s->s_stats.s_npipes, 1); - nni_stat_inc_atomic(&d->d_stats.s_npipes, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&s->st_pipes, 1); + nni_stat_inc(&d->st_pipes, 1); +#endif nni_pipe_run_cb(p, NNG_PIPE_EV_ADD_PRE); nni_mtx_lock(&s->s_mx); if (p->p_closed) { nni_mtx_unlock(&s->s_mx); - nni_stat_inc_atomic(&d->d_stats.s_reject, 1); - nni_stat_inc_atomic(&s->s_stats.s_reject, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&d->st_reject, 1); + nni_stat_inc(&s->st_rejects, 1); +#endif nni_pipe_rele(p); return; } if (p->p_proto_ops.pipe_start(p->p_proto_data) != 0) { nni_mtx_unlock(&s->s_mx); - nni_stat_inc_atomic(&d->d_stats.s_reject, 1); - nni_stat_inc_atomic(&s->s_stats.s_reject, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&d->st_reject, 1); + nni_stat_inc(&s->st_rejects, 1); +#endif nni_pipe_close(p); nni_pipe_rele(p); return; } nni_mtx_unlock(&s->s_mx); - nni_stat_register(&p->p_stats.s_root); +#ifdef NNG_ENABLE_STATS + nni_stat_register(&p->st_root); +#endif nni_pipe_run_cb(p, NNG_PIPE_EV_ADD_POST); nni_pipe_rele(p); } @@ -1483,7 +1532,9 @@ nni_dialer_reap(nni_dialer *d) nni_aio_stop(&d->d_tmo_aio); nni_aio_stop(&d->d_con_aio); - nni_stat_unregister(&d->d_stats.s_root); +#ifdef NNG_ENABLE_STATS + nni_stat_unregister(&d->st_root); +#endif nni_mtx_lock(&s->s_mx); if (!nni_list_empty(&d->d_pipes)) { @@ -1524,29 +1575,35 @@ nni_listener_add_pipe(nni_listener *l, void *tpipe) nni_list_append(&l->l_pipes, p); nni_list_append(&s->s_pipes, p); nni_mtx_unlock(&s->s_mx); - nni_stat_inc_atomic(&l->l_stats.s_npipes, 1); - nni_stat_inc_atomic(&s->s_stats.s_npipes, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&l->st_pipes, 1); + nni_stat_inc(&s->st_pipes, 1); +#endif nni_pipe_run_cb(p, NNG_PIPE_EV_ADD_PRE); nni_mtx_lock(&s->s_mx); if (p->p_closed) { nni_mtx_unlock(&s->s_mx); - nni_stat_inc_atomic(&l->l_stats.s_reject, 1); - nni_stat_inc_atomic(&s->s_stats.s_reject, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&l->st_reject, 1); + nni_stat_inc(&s->st_rejects, 1); +#endif nni_pipe_rele(p); return; } if (p->p_proto_ops.pipe_start(p->p_proto_data) != 0) { nni_mtx_unlock(&s->s_mx); - nni_stat_inc_atomic(&l->l_stats.s_reject, 1); - nni_stat_inc_atomic(&s->s_stats.s_reject, 1); +#ifdef NNG_ENABLE_STATS + nni_stat_inc(&l->st_reject, 1); + nni_stat_inc(&s->st_rejects, 1); +#endif nni_pipe_close(p); nni_pipe_rele(p); return; } nni_mtx_unlock(&s->s_mx); - nni_stat_register(&p->p_stats.s_root); + nni_stat_register(&p->st_root); nni_pipe_run_cb(p, NNG_PIPE_EV_ADD_POST); nni_pipe_rele(p); } @@ -1595,7 +1652,9 @@ nni_listener_reap(nni_listener *l) nni_aio_stop(&l->l_tmo_aio); nni_aio_stop(&l->l_acc_aio); - nni_stat_unregister(&l->l_stats.s_root); +#ifdef NNG_ENABLE_STATS + nni_stat_unregister(&l->st_root); +#endif nni_mtx_lock(&s->s_mx); if (!nni_list_empty(&l->l_pipes)) { @@ -1655,15 +1714,17 @@ nni_pipe_remove(nni_pipe *p) nni_dialer *d = p->p_dialer; nni_mtx_lock(&s->s_mx); +#ifdef NNG_ENABLE_STATS if (nni_list_node_active(&p->p_sock_node)) { - nni_stat_dec_atomic(&s->s_stats.s_npipes, 1); + nni_stat_dec(&s->st_pipes, 1); } if (p->p_listener != NULL) { - nni_stat_dec_atomic(&p->p_listener->l_stats.s_npipes, 1); + nni_stat_dec(&p->p_listener->st_pipes, 1); } if (p->p_dialer != NULL) { - nni_stat_dec_atomic(&p->p_dialer->d_stats.s_npipes, 1); + nni_stat_dec(&p->p_dialer->st_pipes, 1); } +#endif nni_list_node_remove(&p->p_sock_node); nni_list_node_remove(&p->p_ep_node); p->p_listener = NULL; @@ -1682,7 +1743,7 @@ void nni_sock_add_stat(nni_sock *s, nni_stat_item *stat) { #ifdef NNG_ENABLE_STATS - nni_stat_add(&s->s_stats.s_root, stat); + nni_stat_add(&s->st_root, stat); #else NNI_ARG_UNUSED(s); NNI_ARG_UNUSED(stat); @@ -1693,8 +1754,8 @@ void nni_sock_bump_tx(nni_sock *s, uint64_t sz) { #ifdef NNG_ENABLE_STATS - nni_stat_inc_atomic(&s->s_stats.s_txmsgs, 1); - nni_stat_inc_atomic(&s->s_stats.s_txbytes, sz); + nni_stat_inc(&s->st_tx_msgs, 1); + nni_stat_inc(&s->st_tx_bytes, sz); #else NNI_ARG_UNUSED(s); NNI_ARG_UNUSED(sz); @@ -1705,8 +1766,8 @@ void nni_sock_bump_rx(nni_sock *s, uint64_t sz) { #ifdef NNG_ENABLE_STATS - nni_stat_inc_atomic(&s->s_stats.s_rxmsgs, 1); - nni_stat_inc_atomic(&s->s_stats.s_rxbytes, sz); + nni_stat_inc(&s->st_rx_msgs, 1); + nni_stat_inc(&s->st_rx_bytes, sz); #else NNI_ARG_UNUSED(s); NNI_ARG_UNUSED(sz); diff --git a/src/core/sockimpl.h b/src/core/sockimpl.h index 732e2285..804fa00c 100644 --- a/src/core/sockimpl.h +++ b/src/core/sockimpl.h @@ -15,25 +15,6 @@ // and pipes. This must not be exposed to other subsystems -- these internals // are subject to change at any time. -typedef struct nni_dialer_stats { - nni_stat_item s_root; - nni_stat_item s_id; - nni_stat_item s_sock; - nni_stat_item s_url; - nni_stat_item s_npipes; - nni_stat_item s_connok; - nni_stat_item s_refused; - nni_stat_item s_discon; - nni_stat_item s_canceled; - nni_stat_item s_othererr; - nni_stat_item s_etimedout; - nni_stat_item s_eproto; // protocol error - nni_stat_item s_eauth; - nni_stat_item s_enomem; - nni_stat_item s_reject; - char s_scope[24]; // scope name for stats -} nni_dialer_stats; - struct nni_dialer { nni_tran_dialer_ops d_ops; // transport ops nni_tran * d_tran; // transport pointer @@ -42,8 +23,8 @@ struct nni_dialer { nni_list_node d_node; // per socket list nni_sock * d_sock; nni_url * d_url; - nni_pipe * d_pipe; // active pipe (for redialer) - int d_refcnt; + nni_pipe * d_pipe; // active pipe (for re-dialer) + int d_ref; bool d_closed; // full shutdown bool d_closing; nni_atomic_flag d_started; @@ -57,26 +38,25 @@ struct nni_dialer { nni_duration d_inirtime; // initial time for reconnect nni_time d_conntime; // time of last good connect nni_reap_item d_reap; - nni_dialer_stats d_stats; -}; -typedef struct nni_listener_stats { - nni_stat_item s_root; - nni_stat_item s_id; - nni_stat_item s_sock; - nni_stat_item s_url; - nni_stat_item s_npipes; - nni_stat_item s_accept; - nni_stat_item s_discon; // aborted remotely - nni_stat_item s_canceled; - nni_stat_item s_othererr; - nni_stat_item s_etimedout; - nni_stat_item s_eproto; // protocol error - nni_stat_item s_eauth; - nni_stat_item s_enomem; - nni_stat_item s_reject; - char s_scope[24]; // scope name for stats -} nni_listener_stats; +#ifdef NNG_ENABLE_STATS + nni_stat_item st_root; + nni_stat_item st_id; + nni_stat_item st_sock; + nni_stat_item st_url; + nni_stat_item st_pipes; + nni_stat_item st_connect; + nni_stat_item st_refused; + nni_stat_item st_disconnect; // aborted remotely + nni_stat_item st_canceled; + nni_stat_item st_other; + nni_stat_item st_timeout; + nni_stat_item st_proto; // protocol error + nni_stat_item st_auth; + nni_stat_item st_oom; + nni_stat_item st_reject; +#endif +}; struct nni_listener { nni_tran_listener_ops l_ops; // transport ops @@ -86,7 +66,7 @@ struct nni_listener { nni_list_node l_node; // per socket list nni_sock * l_sock; nni_url * l_url; - int l_refcnt; + int l_ref; bool l_closed; // full shutdown bool l_closing; // close started (shutdown) nni_atomic_flag l_started; @@ -94,20 +74,24 @@ struct nni_listener { nni_aio l_acc_aio; nni_aio l_tmo_aio; nni_reap_item l_reap; - nni_listener_stats l_stats; -}; -typedef struct nni_pipe_stats { - nni_stat_item s_root; - nni_stat_item s_id; - nni_stat_item s_ep_id; - nni_stat_item s_sock_id; - nni_stat_item s_rxmsgs; - nni_stat_item s_txmsgs; - nni_stat_item s_rxbytes; - nni_stat_item s_txbytes; - char s_scope[16]; // scope name for stats ("pipe" is short) -} nni_pipe_stats; +#ifdef NNG_ENABLE_STATS + nni_stat_item st_root; + nni_stat_item st_id; + nni_stat_item st_sock; + nni_stat_item st_url; + nni_stat_item st_pipes; + nni_stat_item st_accept; + nni_stat_item st_disconnect; // aborted remotely + nni_stat_item st_canceled; + nni_stat_item st_other; + nni_stat_item st_timeout; + nni_stat_item st_proto; // protocol error + nni_stat_item st_auth; + nni_stat_item st_oom; + nni_stat_item st_reject; +#endif +}; struct nni_pipe { uint32_t p_id; @@ -124,11 +108,22 @@ struct nni_pipe { bool p_closed; nni_atomic_flag p_stop; bool p_cbs; - int p_refcnt; + int p_ref; nni_mtx p_mtx; nni_cv p_cv; nni_reap_item p_reap; - nni_pipe_stats p_stats; + +#ifdef NNG_ENABLE_STATS + nni_stat_item st_root; + nni_stat_item st_id; + nni_stat_item st_ep_id; + nni_stat_item st_sock_id; + nni_stat_item st_rx_msgs; + nni_stat_item st_tx_msgs; + nni_stat_item st_rx_bytes; + nni_stat_item st_tx_bytes; + +#endif }; extern int nni_sock_add_dialer(nni_sock *, nni_dialer *); diff --git a/src/core/stats.c b/src/core/stats.c index d6f98e3e..14cf7978 100644 --- a/src/core/stats.c +++ b/src/core/stats.c @@ -16,23 +16,24 @@ typedef struct nng_stat nni_stat; struct nng_stat { - char * s_name; - char * s_desc; - char * s_string; - uint64_t s_value; - nni_time s_time; - nni_stat_type s_type; - nni_stat_unit s_unit; - nni_stat_item *s_item; // Used during snapshot collection - nni_list s_children; - nni_stat * s_parent; - nni_list_node s_node; + const nni_stat_info *s_info; + const nni_stat_item *s_item; // Used during snapshot collection + nni_list s_children; + nni_stat * s_parent; + nni_list_node s_node; + nni_time s_timestamp; + union { + int sv_id; + bool sv_bool; + uint64_t sv_value; + char * sv_string; + } s_val; }; #ifdef NNG_ENABLE_STATS static nni_stat_item stats_root; static nni_mtx stats_lock; -static nni_mtx * stats_held = NULL; +static nni_mtx stats_val_lock; #endif void @@ -68,135 +69,149 @@ nni_stat_register(nni_stat_item *child) #endif } +#ifdef NNG_ENABLE_STATS +void +stat_unregister(nni_stat_item *item) +{ + nni_stat_item *child; + while ((child = nni_list_first(&item->si_children)) != NULL) { + stat_unregister(child); + } + if ((item->si_info->si_alloc) && + (item->si_info->si_type == NNG_STAT_STRING)) { + nni_strfree(item->si_value.sv_string); + item->si_value.sv_string = NULL; + } + nni_list_node_remove(&item->si_node); +} +#endif + void -nni_stat_unregister(nni_stat_item *stat) +nni_stat_unregister(nni_stat_item *item) { #ifdef NNG_ENABLE_STATS nni_mtx_lock(&stats_lock); - nni_list_node_remove(&stat->si_node); + stat_unregister(item); nni_mtx_unlock(&stats_lock); #else - NNI_ARG_UNUSED(child); + NNI_ARG_UNUSED(item); #endif } -#ifdef NNG_ENABLE_STATS void -nni_stat_init(nni_stat_item *stat, const char *name, const char *desc) +nni_stat_init(nni_stat_item *item, const nni_stat_info *info) { - NNI_LIST_INIT(&stat->si_children, nni_stat_item, si_node); - stat->si_name = name; - stat->si_desc = desc; - stat->si_lock = NULL; - stat->si_update = NULL; - stat->si_string = NULL; - stat->si_number = 0; - stat->si_type = NNG_STAT_COUNTER; - stat->si_unit = NNG_UNIT_NONE; +#ifdef NNG_ENABLE_STATS + memset(item, 0, sizeof(*item)); + NNI_LIST_INIT(&item->si_children, nni_stat_item, si_node); + item->si_info = info; +#else + NNI_ARG_UNUSED(item); + NNI_ARG_UNUSED(info); +#endif } void -nni_stat_init_scope(nni_stat_item *stat, const char *name, const char *desc) +nni_stat_inc(nni_stat_item *item, uint64_t inc) { - nni_stat_init(stat, name, desc); - stat->si_type = NNG_STAT_SCOPE; - stat->si_unit = NNG_UNIT_NONE; +#ifdef NNG_ENABLE_STATS + if (item->si_info->si_atomic) { + nni_atomic_add64(&item->si_value.sv_atomic, inc); + } else { + item->si_value.sv_number += inc; + } +#else + NNI_ARG_UNUSED(item); + NNI_ARG_UNUSED(inc); +#endif } void -nni_stat_init_string( - nni_stat_item *stat, const char *name, const char *desc, const char *str) +nni_stat_dec(nni_stat_item *item, uint64_t inc) { - nni_stat_init(stat, name, desc); - stat->si_string = str; - stat->si_type = NNG_STAT_STRING; - stat->si_unit = NNG_UNIT_NONE; -} +#ifdef NNG_ENABLE_STATS -void -nni_stat_init_id( - nni_stat_item *stat, const char *name, const char *desc, uint64_t id) -{ - nni_stat_init(stat, name, desc); - stat->si_number = id; - stat->si_type = NNG_STAT_ID; - stat->si_unit = NNG_UNIT_NONE; + if (item->si_info->si_atomic) { + nni_atomic_sub64(&item->si_value.sv_atomic, inc); + } else { + item->si_value.sv_number -= inc; + } +#else + NNI_ARG_UNUSED(item); + NNI_ARG_UNUSED(inc); +#endif } void -nni_stat_init_bool( - nni_stat_item *stat, const char *name, const char *desc, bool v) +nni_stat_set_id(nni_stat_item *item, int id) { - nni_stat_init(stat, name, desc); - stat->si_number = v ? 1 : 0; - stat->si_type = NNG_STAT_BOOLEAN; - stat->si_unit = NNG_UNIT_NONE; -} - -static void -stat_atomic_update(nni_stat_item *stat) -{ - stat->si_number = nni_atomic_get64(&stat->si_atomic); +#ifdef NNG_ENABLE_STATS + // IDs don't change, so just set it. + item->si_value.sv_id = id; +#else + NNI_ARG_UNUSED(item); + NNI_ARG_UNUSED(id); +#endif } void -nni_stat_init_atomic(nni_stat_item *stat, const char *name, const char *desc) +nni_stat_set_bool(nni_stat_item *item, bool b) { - nni_stat_init(stat, name, desc); - stat->si_number = 0; - stat->si_update = stat_atomic_update; - nni_atomic_init64(&stat->si_atomic); +#ifdef NNG_ENABLE_STATS + // bool is atomic by definitions. + item->si_value.sv_bool = b; +#else + NNI_ARG_UNUSED(item); + NNI_ARG_UNUSED(id); +#endif } void -nni_stat_inc_atomic(nni_stat_item *stat, uint64_t inc) +nni_stat_set_string(nni_stat_item *item, const char *s) { - nni_atomic_add64(&stat->si_atomic, inc); -} +#ifdef NNG_ENABLE_STATS + const nni_stat_info *info = item->si_info; + char * old = item->si_value.sv_string; + + nni_mtx_lock(&stats_val_lock); + if ((s != NULL) && (old != NULL) && (strcmp(s, old) == 0)) { + // no change + nni_mtx_unlock(&stats_val_lock); + return; + } -void -nni_stat_dec_atomic(nni_stat_item *stat, uint64_t inc) -{ - nni_atomic_sub64(&stat->si_atomic, inc); -} -#endif + if (!info->si_alloc) { + // no allocation, just set it. + item->si_value.sv_string = (char *) s; + nni_mtx_unlock(&stats_val_lock); + return; + } -void -nni_stat_set_value(nni_stat_item *stat, uint64_t v) -{ -#ifdef NNG_ENABLE_STATS - stat->si_number = v; + item->si_value.sv_string = nni_strdup(s); + nni_mtx_unlock(&stats_val_lock); + + nni_strfree(old); #else - NNI_ARG_UNUSED(stat); - NNI_ARG_UNUSED(v); + NNG_ARG_UNUSED(item); + NNG_ARG_UNUSED(s); #endif } void -nni_stat_set_lock(nni_stat_item *stat, nni_mtx *mtx) +nni_stat_set_value(nni_stat_item *item, uint64_t v) { #ifdef NNG_ENABLE_STATS - stat->si_lock = mtx; + if (item->si_info->si_atomic) { + nni_atomic_set64(&item->si_value.sv_atomic, v); + } else { + item->si_value.sv_number = v; + } #else NNI_ARG_UNUSED(stat); - NNI_ARG_UNUSED(mtx); + NNI_ARG_UNUSED(v); #endif } -#ifdef NNG_ENABLE_STATS -void -nni_stat_set_type(nni_stat_item *stat, int type) -{ - stat->si_type = type; -} - -void -nni_stat_set_unit(nni_stat_item *stat, int unit) -{ - stat->si_unit = unit; -} -#endif - void nng_stats_free(nni_stat *st) { @@ -207,9 +222,9 @@ nng_stats_free(nni_stat *st) nni_list_remove(&st->s_children, child); nng_stats_free(child); } - nni_strfree(st->s_name); - nni_strfree(st->s_desc); - nni_strfree(st->s_string); + if (st->s_info->si_alloc) { + nni_strfree(st->s_val.sv_string); + } NNI_FREE_STRUCT(st); #else NNI_ARG_UNUSED(st); @@ -228,19 +243,8 @@ stat_make_tree(nni_stat_item *item, nni_stat **sp) } NNI_LIST_INIT(&stat->s_children, nni_stat, s_node); - if (((stat->s_name = nni_strdup(item->si_name)) == NULL) || - ((stat->s_desc = nni_strdup(item->si_desc)) == NULL)) { - nng_stats_free(stat); - return (NNG_ENOMEM); - } - if ((item->si_type == NNG_STAT_STRING) && - ((stat->s_string = nni_strdup(item->si_string)) == NULL)) { - nng_stats_free(stat); - return (NNG_ENOMEM); - } + stat->s_info = item->si_info; stat->s_item = item; - stat->s_type = item->si_type; - stat->s_unit = item->si_unit; stat->s_parent = NULL; NNI_LIST_FOREACH (&item->si_children, child) { @@ -260,23 +264,52 @@ stat_make_tree(nni_stat_item *item, nni_stat **sp) static void stat_update(nni_stat *stat) { - nni_stat_item *item = stat->s_item; + const nni_stat_item *item = stat->s_item; + const nni_stat_info *info = item->si_info; + char * old; + char * str; - if (item->si_lock != stats_held) { - if (stats_held != NULL) { - nni_mtx_unlock(stats_held); - stats_held = NULL; + switch (info->si_type) { + case NNG_STAT_SCOPE: + case NNG_STAT_ID: + stat->s_val.sv_id = item->si_value.sv_id; + break; + case NNG_STAT_BOOLEAN: + stat->s_val.sv_bool = item->si_value.sv_bool; + break; + case NNG_STAT_COUNTER: + case NNG_STAT_LEVEL: + if (info->si_atomic) { + stat->s_val.sv_value = nni_atomic_get64( + (nni_atomic_u64 *) &item->si_value.sv_atomic); + } else { + stat->s_val.sv_value = item->si_value.sv_number; } - if (item->si_lock != NULL) { - nni_mtx_lock(item->si_lock); - stats_held = item->si_lock; + break; + case NNG_STAT_STRING: + nni_mtx_lock(&stats_val_lock); + old = stat->s_val.sv_string; + str = item->si_value.sv_string; + + // If we have to allocate a new string, do so. But + // only do it if new string is different. + if ((info->si_alloc) && (str != NULL) && + ((old == NULL) || (strcmp(str, old) != 0))) { + + stat->s_val.sv_string = nni_strdup(str); + nni_strfree(old); + + } else if (info->si_alloc) { + nni_strfree(stat->s_val.sv_string); + stat->s_val.sv_string = NULL; + + } else { + stat->s_val.sv_string = str; } + nni_mtx_unlock(&stats_val_lock); + break; } - if (item->si_update != NULL) { - item->si_update(item); - } - stat->s_value = item->si_number; - stat->s_time = nni_clock(); + stat->s_timestamp = nni_clock(); } static void @@ -304,10 +337,6 @@ nni_stat_snapshot(nni_stat **statp, nni_stat_item *item) return (rv); } stat_update_tree(stat); - if (stats_held != NULL) { - nni_mtx_unlock(stats_held); - stats_held = NULL; - } nni_mtx_unlock(&stats_lock); *statp = stat; return (0); @@ -353,43 +382,53 @@ nng_stat_child(nng_stat *stat) const char * nng_stat_name(nni_stat *stat) { - return (stat->s_name); + return (stat->s_info->si_name); } uint64_t nng_stat_value(nni_stat *stat) { - return (stat->s_value); + return (stat->s_val.sv_value); +} + +bool +nng_stat_bool(nni_stat *stat) +{ + return (stat->s_val.sv_bool); } + const char * nng_stat_string(nng_stat *stat) { - return (stat->s_string); + if (stat->s_info->si_type != NNG_STAT_STRING) { + return (""); + } + return (stat->s_val.sv_string); } uint64_t nng_stat_timestamp(nng_stat *stat) { - return ((uint64_t) stat->s_time); + return ((uint64_t) stat->s_timestamp); } int nng_stat_type(nng_stat *stat) { - return (stat->s_type); + return (stat->s_info->si_type); } int nng_stat_unit(nng_stat *stat) { - return (stat->s_unit); + return (stat->s_info->si_unit); } const char * nng_stat_desc(nng_stat *stat) { - return (stat->s_desc); + return (stat->s_info->si_desc); } nng_stat * @@ -399,7 +438,28 @@ nng_stat_find(nng_stat *stat, const char *name) if (stat == NULL) { return (NULL); } - if (strcmp(name, stat->s_name) == 0) { + if (strcmp(name, stat->s_info->si_name) == 0) { + return (stat); + } + NNI_LIST_FOREACH (&stat->s_children, child) { + nng_stat *result; + if ((result = nng_stat_find(child, name)) != NULL) { + return (result); + } + } + return (NULL); +} + +nng_stat * +nng_stat_find_scope(nng_stat *stat, const char *name, int id) +{ + nng_stat *child; + if (stat == NULL) { + return (NULL); + } + if ((stat->s_val.sv_id == id) && + (stat->s_info->si_type == NNG_STAT_SCOPE) && + (strcmp(name, stat->s_info->si_name) == 0)) { return (stat); } NNI_LIST_FOREACH (&stat->s_children, child) { @@ -414,35 +474,33 @@ nng_stat_find(nng_stat *stat, const char *name) nng_stat * nng_stat_find_socket(nng_stat *stat, nng_socket s) { - char name[16]; - (void) snprintf(name, sizeof(name), "socket%d", nng_socket_id(s)); - return (nng_stat_find(stat, name)); + return (nng_stat_find_scope(stat, "socket", nng_socket_id(s))); } nng_stat * nng_stat_find_dialer(nng_stat *stat, nng_dialer d) { - char name[16]; - (void) snprintf(name, sizeof(name), "dialer%d", nng_dialer_id(d)); - return (nng_stat_find(stat, name)); + return (nng_stat_find_scope(stat, "dialer", nng_dialer_id(d))); } nng_stat * nng_stat_find_listener(nng_stat *stat, nng_listener l) { - char name[16]; - (void) snprintf(name, sizeof(name), "listener%d", nng_listener_id(l)); - return (nng_stat_find(stat, name)); + return (nng_stat_find_scope(stat, "listener", nng_listener_id(l))); } int nni_stat_sys_init(void) { #ifdef NNG_ENABLE_STATS + static const nni_stat_info root = { + .si_name = "", + .si_desc = "all statistics", + .si_type = NNG_STAT_SCOPE, + }; nni_mtx_init(&stats_lock); - NNI_LIST_INIT(&stats_root.si_children, nni_stat_item, si_node); - stats_root.si_name = ""; - stats_root.si_desc = "all statistics"; + nni_mtx_init(&stats_val_lock); + nni_stat_init(&stats_root, &root); #endif return (0); } @@ -452,6 +510,7 @@ nni_stat_sys_fini(void) { #ifdef NNG_ENABLE_STATS nni_mtx_fini(&stats_lock); + nni_mtx_fini(&stats_val_lock); #endif } @@ -462,8 +521,9 @@ stat_sprint_scope(nni_stat *stat, char **scope, int *lenp) if (stat->s_parent != NULL) { stat_sprint_scope(stat->s_parent, scope, lenp); } - if (strlen(stat->s_name) > 0) { - snprintf(*scope, *lenp, "%s.", stat->s_name); + if (strlen(stat->s_info->si_name) > 0) { + snprintf(*scope, *lenp, "%s#%d.", stat->s_info->si_name, + stat->s_val.sv_id); } else { (*scope)[0] = '\0'; } @@ -503,9 +563,8 @@ nng_stats_dump(nng_stat *stat) nng_stat_string(stat)); break; case NNG_STAT_BOOLEAN: - val = nng_stat_value(stat); nni_plat_printf("%s%-32s%s\n", indent, nng_stat_name(stat), - val != 0 ? "true" : "false"); + nng_stat_bool(stat) ? "true" : "false"); break; case NNG_STAT_LEVEL: case NNG_STAT_COUNTER: @@ -520,7 +579,7 @@ nng_stats_dump(nng_stat *stat) nni_plat_printf(" msgs\n"); break; case NNG_UNIT_MILLIS: - nni_plat_printf(" msec\n"); + nni_plat_printf(" ms\n"); break; case NNG_UNIT_NONE: case NNG_UNIT_EVENTS: diff --git a/src/core/stats.h b/src/core/stats.h index 0375979e..950df78f 100644 --- a/src/core/stats.h +++ b/src/core/stats.h @@ -24,6 +24,7 @@ // acquire the lock on the stat first though. typedef struct nni_stat_item nni_stat_item; +typedef struct nni_stat_info nni_stat_info; typedef void (*nni_stat_update)(nni_stat_item *); typedef enum nng_stat_type_enum nni_stat_type; @@ -35,21 +36,26 @@ typedef enum nng_unit_enum nni_stat_unit; // avoid having to spend dereference costs or (worse) to have to include // extra conditionals on hot code paths. struct nni_stat_item { -#ifdef NNG_ENABLE_STATS - nni_list_node si_node; // list node, framework use only - nni_list si_children; // children, framework use only - const char * si_name; // name of statistic - const char * si_desc; // description of statistic (English) - nni_mtx * si_lock; // lock for accessing, can be NULL - nni_stat_type si_type; // type of stat, e.g. NNG_STAT_LEVEL - nni_stat_unit si_unit; // units, e.g. NNG_UNIT_MILLIS - nni_stat_update si_update; // update function (can be NULL) - const char * si_string; // string value (NULL for numerics) - uint64_t si_number; // numeric value - nni_atomic_u64 si_atomic; // atomic value -#else - char si_disabled; // place holder, cannot be empty in C -#endif + nni_list_node si_node; // list node, framework use only + nni_list si_children; // children, framework use only + const nni_stat_info *si_info; // statistic description + union { + uint64_t sv_number; + nni_atomic_u64 sv_atomic; + char * sv_string; + bool sv_bool; + int sv_id; + } si_value; +}; + +struct nni_stat_info { + const char * si_name; // name of statistic + const char * si_desc; // description of statistic (English) + nni_stat_type si_type; // statistic type, e.g. NNG_STAT_LEVEL + nni_stat_unit si_unit; // statistic unit, e.g. NNG_UNIT_MILLIS + nni_stat_update si_update; // update function (can be NULL) + bool si_atomic : 1; // stat is atomic + bool si_alloc : 1; // stat string is allocated }; // nni_stat_add adds a statistic, but the operation is unlocked, and the @@ -64,37 +70,12 @@ void nni_stat_register(nni_stat_item *); void nni_stat_unregister(nni_stat_item *); void nni_stat_set_value(nni_stat_item *, uint64_t); -void nni_stat_set_lock(nni_stat_item *, nni_mtx *); - -#ifdef NNG_ENABLE_STATS -void nni_stat_init(nni_stat_item *, const char *, const char *); -void nni_stat_init_scope(nni_stat_item *, const char *, const char *); -void nni_stat_init_string( - nni_stat_item *, const char *, const char *, const char *); -void nni_stat_init_id(nni_stat_item *, const char *, const char *, uint64_t); -void nni_stat_init_bool(nni_stat_item *, const char *, const char *, bool); -void nni_stat_init_atomic(nni_stat_item *, const char *, const char *); -void nni_stat_inc_atomic(nni_stat_item *, uint64_t); -void nni_stat_dec_atomic(nni_stat_item *, uint64_t); -void nni_stat_set_type(nni_stat_item *, int); -void nni_stat_set_unit(nni_stat_item *, int); -#else -// We override initialization so that we can avoid compiling static strings -// into the binary. Presumably if stats are disabled, we are trying to save -// space for constrained environments. We do evaluate an unused arg to -// prevent the compiler from bitching about unused values. -#define nni_stat_init(a, b, c) ((void) (a)) -#define nni_stat_init_scope(a, b, c) ((void) (a)) -#define nni_stat_init_atomic(a, b, c) ((void) (a)) -#define nni_stat_init_id(a, b, c, d) ((void) (a)) -#define nni_stat_init_bool(a, b, c, d) ((void) (a)) -#define nni_stat_init_string(a, b, c, d) ((void) (a)) -#define nni_stat_set_unit(a, b) ((void) (a)) -#define nni_stat_set_type(a, b) ((void) (a)) -#define nni_stat_inc_atomic(stat, inc) -#define nni_stat_dec_atomic(stat, inc) -#endif - +void nni_stat_set_id(nni_stat_item *, int); +void nni_stat_set_bool(nni_stat_item *, bool); +void nni_stat_set_string(nni_stat_item *, const char *); +void nni_stat_init(nni_stat_item *, const nni_stat_info *); +void nni_stat_inc(nni_stat_item *, uint64_t); +void nni_stat_dec(nni_stat_item *, uint64_t); int nni_stat_sys_init(void); void nni_stat_sys_fini(void); |
