--- /dev/null
+#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;
+}