12 #include "serverpool.h"
18 extern ServerPool *servers;
20 StatsThread::StatsThread(const string &stats_file, int stats_interval)
21 : stats_file(stats_file),
22 stats_interval(stats_interval)
26 void StatsThread::do_work()
28 while (!should_stop()) {
33 vector<ClientStats> client_stats;
35 if (clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == -1) {
36 log_perror("clock_gettime(CLOCK_MONOTONIC_COARSE)");
40 // Open a new, temporary file.
41 filename = strdup((stats_file + ".new.XXXXXX").c_str());
42 fd = mkostemp(filename, O_WRONLY);
53 if (unlink(filename) == -1) {
60 client_stats = servers->get_client_stats();
61 for (size_t i = 0; i < client_stats.size(); ++i) {
62 fprintf(fp, "%s %d %d %s %d %llu %llu %llu \"%s\" \"%s\"\n",
63 client_stats[i].remote_addr.c_str(),
65 0, // Used to be fwmark.
66 client_stats[i].url.c_str(),
67 int(now.tv_sec - client_stats[i].connect_time.tv_sec), // Rather coarse.
68 (long long unsigned)(client_stats[i].bytes_sent),
69 (long long unsigned)(client_stats[i].bytes_lost),
70 (long long unsigned)(client_stats[i].num_loss_events),
71 client_stats[i].referer.c_str(),
72 client_stats[i].user_agent.c_str());
74 if (fclose(fp) == EOF) {
76 if (unlink(filename) == -1) {
83 if (rename(filename, stats_file.c_str()) == -1) {
85 if (unlink(filename) == -1) {
92 // Wait until we are asked to quit, stats_interval timeout,
93 // or a spurious signal. (The latter will cause us to write stats
94 // too often, but that's okay.)
96 timeout_ts.tv_sec = stats_interval;
97 timeout_ts.tv_nsec = 0;
98 wait_for_wakeup(&timeout_ts);