From f5bdef4efd35b53f5472bf39037614088166fa8b Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Sat, 9 May 2020 01:57:51 +0300 Subject: stats: Change timer to timerfd to make it a true interval timer. Previously the interval between stats flushes would slowly increase which would lead to reporting time jitter and confuse a timescale database. Change-Id: I23d8b5157ef8a9833ba16a81d9b28a126f303c30 --- src/stats.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/stats.c b/src/stats.c index 5954167a..a5a4d4bc 100644 --- a/src/stats.c +++ b/src/stats.c @@ -74,6 +74,7 @@ #include #include #include +#include #ifdef HAVE_SYS_SOCKET_H #include @@ -85,7 +86,7 @@ #include #include #include -#include +#include #include #include @@ -102,7 +103,7 @@ static struct osmo_stats_config s_stats_config = { }; struct osmo_stats_config *osmo_stats_config = &s_stats_config; -static struct osmo_timer_list osmo_stats_timer; +static struct osmo_fd osmo_stats_timer = { .fd = -1 }; static int osmo_stats_reporter_log_send_counter(struct osmo_stats_reporter *srep, const struct rate_ctr_group *ctrg, @@ -140,23 +141,52 @@ static int update_srep_config(struct osmo_stats_reporter *srep) return rc; } -static void osmo_stats_timer_cb(void *data) +static int osmo_stats_timer_cb(struct osmo_fd *ofd, unsigned int what) { - int interval = osmo_stats_config->interval; + uint64_t expire_count; + int rc; + + /* check that the timer has actually expired */ + if (!(what & OSMO_FD_READ)) + return 0; + + /* read from timerfd: number of expirations of periodic timer */ + rc = read(ofd->fd, (void *) &expire_count, sizeof(expire_count)); + if (rc < 0 && errno == EAGAIN) + return 0; + OSMO_ASSERT(rc == sizeof(expire_count)); + + if (expire_count > 1) + LOGP(DLSTATS, LOGL_NOTICE, "Stats timer expire_count=%" PRIu64 ": We missed %" PRIu64 " timers\n", + expire_count, expire_count-1); if (!llist_empty(&osmo_stats_reporter_list)) osmo_stats_report(); - osmo_timer_schedule(&osmo_stats_timer, interval, 0); + return 0; } static int start_timer() { + int rc; + int interval = osmo_stats_config->interval; + if (!is_initialised) return -ESRCH; - osmo_timer_setup(&osmo_stats_timer, osmo_stats_timer_cb, NULL); - osmo_timer_schedule(&osmo_stats_timer, 0, 1); + struct timespec ts_first = {.tv_sec=0, .tv_nsec=1000}; + struct timespec ts_interval = {.tv_sec=interval, .tv_nsec=0}; + + rc = osmo_timerfd_setup(&osmo_stats_timer, osmo_stats_timer_cb, NULL); + if (rc < 0) + LOGP(DLSTATS, LOGL_ERROR, "Failed to setup the timer with error code %d (fd=%d)\n", + rc, osmo_stats_timer.fd); + rc = osmo_timerfd_schedule(&osmo_stats_timer, &ts_first, &ts_interval); + if (rc < 0) + LOGP(DLSTATS, LOGL_ERROR, "Failed to schedule the timer with error code %d (fd=%d, interval %d sec)\n", + rc, osmo_stats_timer.fd, interval); + + LOGP(DLSTATS, LOGL_INFO, "Stats timer started with interval %d sec\n", interval); return 0; } -- cgit v1.2.3