+#include <fcntl.h>
+#include <stddef.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <pthread.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <vector>
+#include "client.h"
+#include "log.h"
#include "serverpool.h"
#include "stats.h"
+#include "util.h"
using namespace std;
{
}
-void StatsThread::run()
-{
- should_stop = false;
- pthread_create(&worker_thread, NULL, do_work_thunk, this);
-}
-
-void StatsThread::stop()
-{
- should_stop = true;
- pthread_kill(worker_thread, SIGHUP);
- if (pthread_join(worker_thread, NULL) == -1) {
- perror("pthread_join");
- exit(1);
- }
-}
-
-void *StatsThread::do_work_thunk(void *arg)
-{
- StatsThread *stats_thread = reinterpret_cast<StatsThread *>(arg);
- stats_thread->do_work();
- return NULL;
-}
-
void StatsThread::do_work()
{
- while (!should_stop) {
+ while (!should_stop()) {
int fd;
FILE *fp;
time_t now;
char *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\n",
client_stats[i].remote_addr.c_str(),
- client_stats[i].stream_id.c_str(),
+ client_stats[i].sock,
+ client_stats[i].fwmark,
+ client_stats[i].url.c_str(),
int(now - client_stats[i].connect_time),
- (long long unsigned)(client_stats[i].bytes_sent));
+ (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));
}
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);
}
}