X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=stats.cpp;h=661a17bf9100b1ea4c044e89ddeba667942f7894;hp=94cd4e71c5c9fa0c7794f1f40e80d26707d6bfb4;hb=b757a4a2ce9d24835b52a185134835762af2f50c;hpb=f87901a18647fb66d766a1db55589fc753f46008 diff --git a/stats.cpp b/stats.cpp index 94cd4e7..661a17b 100644 --- a/stats.cpp +++ b/stats.cpp @@ -1,19 +1,23 @@ +#include +#include #include -#include #include +#include +#include #include -#include -#include -#include +#include +#include "client.h" +#include "log.h" #include "serverpool.h" #include "stats.h" +#include "util.h" using namespace std; extern ServerPool *servers; -StatsThread::StatsThread(const std::string &stats_file, int stats_interval) +StatsThread::StatsThread(const string &stats_file, int stats_interval) : stats_file(stats_file), stats_interval(stats_interval) { @@ -21,55 +25,76 @@ StatsThread::StatsThread(const std::string &stats_file, int stats_interval) void StatsThread::do_work() { - while (!should_stop) { + while (!should_stop()) { int fd; + char *filename; FILE *fp; - time_t now; + timespec now; vector client_stats; + if (clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == -1) { + log_perror("clock_gettime(CLOCK_MONOTONIC_COARSE)"); + goto sleep; + } + // Open a new, temporary file. - char *filename = strdup((stats_file + ".new.XXXXXX").c_str()); + filename = strdup((stats_file + ".new.XXXXXX").c_str()); fd = mkostemp(filename, O_WRONLY); if (fd == -1) { - perror(filename); + log_perror(filename); free(filename); goto sleep; } fp = fdopen(fd, "w"); if (fp == NULL) { - perror("fdopen"); - close(fd); - unlink(filename); + log_perror("fdopen"); + safe_close(fd); + if (unlink(filename) == -1) { + log_perror(filename); + } free(filename); goto sleep; } - now = time(NULL); client_stats = servers->get_client_stats(); for (size_t i = 0; i < client_stats.size(); ++i) { - fprintf(fp, "%s %s %d %llu\n", + fprintf(fp, "%s %d %d %s %d %llu %llu %llu \"%s\" \"%s\"\n", client_stats[i].remote_addr.c_str(), - client_stats[i].stream_id.c_str(), - int(now - client_stats[i].connect_time), - (long long unsigned)(client_stats[i].bytes_sent)); + client_stats[i].sock, + 0, // Used to be fwmark. + client_stats[i].url.c_str(), + int(now.tv_sec - client_stats[i].connect_time.tv_sec), // Rather coarse. + (long long unsigned)(client_stats[i].bytes_sent), + (long long unsigned)(client_stats[i].bytes_lost), + (long long unsigned)(client_stats[i].num_loss_events), + client_stats[i].referer.c_str(), + client_stats[i].user_agent.c_str()); } if (fclose(fp) == EOF) { - perror("fclose"); - unlink(filename); + log_perror("fclose"); + if (unlink(filename) == -1) { + log_perror(filename); + } free(filename); goto sleep; } if (rename(filename, stats_file.c_str()) == -1) { - perror("rename"); - unlink(filename); + log_perror("rename"); + if (unlink(filename) == -1) { + log_perror(filename); + } } + free(filename); sleep: - int left_to_sleep = stats_interval; - do { - left_to_sleep = sleep(left_to_sleep); - } while (left_to_sleep > 0 && !should_stop); + // Wait until we are asked to quit, stats_interval timeout, + // or a spurious signal. (The latter will cause us to write stats + // too often, but that's okay.) + timespec timeout_ts; + timeout_ts.tv_sec = stats_interval; + timeout_ts.tv_nsec = 0; + wait_for_wakeup(&timeout_ts); } }