]> git.ipfire.org Git - fireperf.git/commitdiff
server: Add a timer that triggers printing the statistics one a second
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 28 Jan 2021 18:56:49 +0000 (18:56 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 28 Jan 2021 18:56:49 +0000 (18:56 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/server.c

index 67eeb273b1a2b93f6b92d4ce99ebb8597cd5fb76..6725389f8c75be3719e0042c6f0bdfca7cc9f200 100644 (file)
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/epoll.h>
+#include <sys/timerfd.h>
 #include <unistd.h>
 
 #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;
 }