10 #include "mutexlock.h"
15 AccessLogThread::AccessLogThread()
17 pthread_mutex_init(&mutex, NULL);
20 AccessLogThread::AccessLogThread(const string &filename)
21 : filename(filename) {
22 pthread_mutex_init(&mutex, NULL);
25 void AccessLogThread::write(const ClientStats& client)
28 MutexLock lock(&mutex);
29 pending_writes.push_back(client);
34 void AccessLogThread::do_work()
37 if (filename.empty()) {
40 logfp = fopen(filename.c_str(), "a+");
42 log_perror(filename.c_str());
43 // Continue as before.
47 while (!should_stop()) {
49 vector<ClientStats> writes;
51 MutexLock lock(&mutex);
52 swap(pending_writes, writes);
56 // Do the actual writes.
57 timespec now_monotonic;
58 timespec now_realtime;
59 if (clock_gettime(CLOCK_MONOTONIC_COARSE, &now_monotonic) == -1) {
60 log_perror("clock_gettime(CLOCK_MONOTONIC_COARSE)");
61 } else if (clock_gettime(CLOCK_REALTIME, &now_realtime) == -1) {
62 log_perror("clock_gettime(CLOCK_REALTIME)");
64 timespec realtime_offset = clock_diff(now_monotonic, now_realtime);
65 for (size_t i = 0; i < writes.size(); ++i) {
66 timespec connect_time_realtime = clock_add(writes[i].connect_time, realtime_offset);
67 timespec time_since_connect = clock_diff(writes[i].connect_time, now_monotonic);
68 fprintf(logfp, "%llu %s %s %d %llu %llu %llu \"%s\" \"%s\"\n",
69 (long long unsigned)(connect_time_realtime.tv_sec),
70 writes[i].remote_addr.c_str(),
71 writes[i].url.c_str(),
72 int(time_since_connect.tv_sec),
73 (long long unsigned)(writes[i].bytes_sent),
74 (long long unsigned)(writes[i].bytes_lost),
75 (long long unsigned)(writes[i].num_loss_events),
76 writes[i].referer.c_str(),
77 writes[i].user_agent.c_str());
83 // Wait until we are being woken up, either to quit or because
84 // there is material in pending_writes.
85 wait_for_wakeup(NULL);
89 if (fclose(logfp) == EOF) {