]> git.sesse.net Git - cubemap/blobdiff - accesslog.cpp
Log all finished accesses to an access log.
[cubemap] / accesslog.cpp
diff --git a/accesslog.cpp b/accesslog.cpp
new file mode 100644 (file)
index 0000000..b666f27
--- /dev/null
@@ -0,0 +1,93 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <errno.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "accesslog.h"
+#include "client.h"
+#include "log.h"
+#include "mutexlock.h"
+
+using namespace std;
+
+AccessLogThread::AccessLogThread() {}
+
+AccessLogThread::AccessLogThread(const string &filename)
+       : filename(filename) {}
+
+void AccessLogThread::write(const ClientStats& client)
+{
+       MutexLock lock(&mutex);
+       pending_writes.push_back(client);
+}
+
+void AccessLogThread::do_work()
+{
+       // Open the file.
+       if (filename.empty()) {
+               logfp = NULL;
+       } else {
+               logfp = fopen(filename.c_str(), "a+");
+               if (logfp == NULL) {
+                       log_perror(filename.c_str());
+                       // Continue as before.
+               }
+       }
+
+       while (!should_stop) {
+               // Empty the queue.
+               vector<ClientStats> writes;
+               {
+                       MutexLock lock(&mutex);
+                       swap(pending_writes, writes);
+               }
+
+               if (logfp == NULL) {
+                       continue;
+               }
+
+               // Do the actual writes.
+               time_t now = time(NULL);
+               for (size_t i = 0; i < writes.size(); ++i) {
+                       fprintf(logfp, "%llu %s %s %d %llu %llu %llu\n",
+                               (long long unsigned)(writes[i].connect_time),
+                               writes[i].remote_addr.c_str(),
+                               writes[i].stream_id.c_str(),
+                               int(now - writes[i].connect_time),
+                               (long long unsigned)(writes[i].bytes_sent),
+                               (long long unsigned)(writes[i].bytes_lost),
+                               (long long unsigned)(writes[i].num_loss_events));
+               }
+               fflush(logfp);
+               
+               // Wait until the stop_fd pipe is closed, one second has passed.
+               // or a spurious signal arrives.
+               pollfd pfd;
+               pfd.fd = stop_fd_read;
+               pfd.events = POLLIN | POLLRDHUP;
+
+               int nfds = poll(&pfd, 1, 1000);
+               if (nfds == 0 || (nfds == -1 && errno == EINTR)) {
+                       continue;
+               }
+               if (nfds == 1) {
+                       // Should stop.
+                       break;
+               }
+               if (nfds == -1) {
+                       log_perror("poll");
+                       usleep(100000);
+                       continue;
+               }
+       }
+       
+       if (fclose(logfp) == EOF) {
+               log_perror("fclose");
+       }
+
+       logfp = NULL;
+}