10 #include "mutexlock.h"
14 AccessLogThread::AccessLogThread()
16 pthread_mutex_init(&mutex, NULL);
19 AccessLogThread::AccessLogThread(const string &filename)
20 : filename(filename) {
21 pthread_mutex_init(&mutex, NULL);
24 void AccessLogThread::write(const ClientStats& client)
27 MutexLock lock(&mutex);
28 pending_writes.push_back(client);
33 void AccessLogThread::do_work()
36 if (filename.empty()) {
39 logfp = fopen(filename.c_str(), "a+");
41 log_perror(filename.c_str());
42 // Continue as before.
46 while (!should_stop()) {
48 vector<ClientStats> writes;
50 MutexLock lock(&mutex);
51 swap(pending_writes, writes);
55 // Do the actual writes.
57 if (clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == -1) {
58 log_perror("clock_gettime(CLOCK_MONOTONIC_COARSE)");
60 for (size_t i = 0; i < writes.size(); ++i) {
61 fprintf(logfp, "%llu %s %s %d %llu %llu %llu \"%s\" \"%s\"\n",
62 (long long unsigned)(writes[i].connect_time.tv_sec),
63 writes[i].remote_addr.c_str(),
64 writes[i].url.c_str(),
65 int(now.tv_sec - writes[i].connect_time.tv_sec), // Rather coarse.
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 writes[i].referer.c_str(),
70 writes[i].user_agent.c_str());
76 // Wait until we are being woken up, either to quit or because
77 // there is material in pending_writes.
78 wait_for_wakeup(NULL);
82 if (fclose(logfp) == EOF) {