From ebfb2151d806864b921b32d14f26e2b9a3930822 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Thu, 28 Jan 2021 18:56:49 +0000 Subject: [PATCH] server: Add a timer that triggers printing the statistics one a second Signed-off-by: Michael Tremer --- src/server.c | 95 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/src/server.c b/src/server.c index 67eeb27..6725389 100644 --- a/src/server.c +++ b/src/server.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "logging.h" @@ -35,6 +36,12 @@ struct fireperf_server_stats { unsigned int connections; }; +static int dump_stats(struct fireperf_config* conf, const struct fireperf_server_stats* stats) { + DEBUG(conf, "Printing statistics...\n"); + + return 0; +} + static int create_socket(struct fireperf_config* conf) { // Open a new socket int fd = socket(AF_INET6, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); @@ -149,6 +156,34 @@ int fireperf_server(struct fireperf_config* conf) { goto ERROR; } + // Create timerfd() to print statistics + int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC); + if (timerfd < 0) { + ERROR(conf, "timerfd_create() failed: %s\n", strerror(errno)); + goto ERROR; + } + + ev.events = EPOLLIN; + ev.data.fd = timerfd; + + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev)) { + ERROR(conf, "Could not add timerfd to epoll(): %s\n", + strerror(errno)); + goto ERROR; + } + + // Let the timer ping us once a second + struct itimerspec timer = { + .it_interval.tv_sec = 1, + .it_value.tv_sec = 1, + }; + + r = timerfd_settime(timerfd, 0, &timer, NULL); + if (r) { + ERROR(conf, "Could not set timer: %s\n", strerror(errno)); + return 1; + } + DEBUG(conf, "Entering main loop...\n"); while (!conf->terminated) { @@ -183,34 +218,49 @@ int fireperf_server(struct fireperf_config* conf) { // A connection has been opened stats.connections++; - continue; - } - // Handle any connection events (like disconnects) - if (ev.events & EPOLLHUP) { - DEBUG(conf, "Connection %d has closed\n", fd); + // Handle timer events + } else if (fd == timerfd) { + uint64_t expirations; - // Remove the file descriptor from epoll() - if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL)) { - ERROR(conf, "Could not remove socket file descriptfor from epoll(): %s\n", - strerror(errno)); + // Read from the timer to disarm it + ssize_t bytes_read = read(timerfd, &expirations, sizeof(expirations)); + if (bytes_read <= 0) { + ERROR(conf, "Could not read from timerfd: %s\n", strerror(errno)); + goto ERROR; } - // Free up any resources - close(fd); + r = dump_stats(conf, &stats); + if (r) + goto ERROR; - // This connection is now closed - stats.connections--; + // Handle any connection events + } else { + if (ev.events & EPOLLHUP) { + DEBUG(conf, "Connection %d has closed\n", fd); - // Skip processing anything else, because it would be pointless - continue; - } + // Remove the file descriptor from epoll() + if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL)) { + ERROR(conf, "Could not remove socket file descriptfor from epoll(): %s\n", + strerror(errno)); + } - // One of the connections had IO - if (ev.events & EPOLLIN) { - r = handle_io_on_connection(conf, fd); - if (r < 0) - goto ERROR; + // Free up any resources + close(fd); + + // This connection is now closed + stats.connections--; + + // Skip processing anything else, because it would be pointless + continue; + } + + // One of the connections had IO + if (ev.events & EPOLLIN) { + r = handle_io_on_connection(conf, fd); + if (r < 0) + goto ERROR; + } } } } @@ -222,5 +272,8 @@ ERROR: if (epollfd > 0) close(epollfd); + if (timerfd > 0) + close(timerfd); + return r; } -- 2.47.2