Do not crash on re-exec if we do not have an access log.
[cubemap] / accesslog.cpp
1 #include <errno.h>
2 #include <poll.h>
3 #include <stddef.h>
4 #include <stdio.h>
5 #include <time.h>
6 #include <unistd.h>
7 #include <string>
8 #include <vector>
9
10 #include "accesslog.h"
11 #include "client.h"
12 #include "log.h"
13 #include "mutexlock.h"
14
15 using namespace std;
16
17 AccessLogThread::AccessLogThread()
18 {
19         pthread_mutex_init(&mutex, NULL);
20 }
21
22 AccessLogThread::AccessLogThread(const string &filename)
23         : filename(filename) {
24         pthread_mutex_init(&mutex, NULL);
25 }
26
27 void AccessLogThread::write(const ClientStats& client)
28 {
29         MutexLock lock(&mutex);
30         pending_writes.push_back(client);
31 }
32
33 void AccessLogThread::do_work()
34 {
35         // Open the file.
36         if (filename.empty()) {
37                 logfp = NULL;
38         } else {
39                 logfp = fopen(filename.c_str(), "a+");
40                 if (logfp == NULL) {
41                         log_perror(filename.c_str());
42                         // Continue as before.
43                 }
44         }
45
46         while (!should_stop) {
47                 // Empty the queue.
48                 vector<ClientStats> writes;
49                 {
50                         MutexLock lock(&mutex);
51                         swap(pending_writes, writes);
52                 }
53
54                 if (logfp == NULL) {
55                         continue;
56                 }
57
58                 // Do the actual writes.
59                 time_t now = time(NULL);
60                 for (size_t i = 0; i < writes.size(); ++i) {
61                         fprintf(logfp, "%llu %s %s %d %llu %llu %llu\n",
62                                 (long long unsigned)(writes[i].connect_time),
63                                 writes[i].remote_addr.c_str(),
64                                 writes[i].stream_id.c_str(),
65                                 int(now - writes[i].connect_time),
66                                 (long long unsigned)(writes[i].bytes_sent),
67                                 (long long unsigned)(writes[i].bytes_lost),
68                                 (long long unsigned)(writes[i].num_loss_events));
69                 }
70                 fflush(logfp);
71                 
72                 // Wait until the stop_fd pipe is closed, one second has passed.
73                 // or a spurious signal arrives.
74                 pollfd pfd;
75                 pfd.fd = stop_fd_read;
76                 pfd.events = POLLIN | POLLRDHUP;
77
78                 int nfds = poll(&pfd, 1, 1000);
79                 if (nfds == 0 || (nfds == -1 && errno == EINTR)) {
80                         continue;
81                 }
82                 if (nfds == 1) {
83                         // Should stop.
84                         break;
85                 }
86                 if (nfds == -1) {
87                         log_perror("poll");
88                         usleep(100000);
89                         continue;
90                 }
91         }
92
93         if (logfp != NULL) {    
94                 if (fclose(logfp) == EOF) {
95                         log_perror("fclose");
96                 }
97         }
98
99         logfp = NULL;
100 }