Factor all the common thread starting/stopping into a common Thread class.
[cubemap] / stats.cpp
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <fcntl.h>
5 #include <signal.h>
6 #include <pthread.h>
7
8 #include "serverpool.h"
9 #include "stats.h"
10
11 using namespace std;
12
13 extern ServerPool *servers;
14
15 StatsThread::StatsThread(const std::string &stats_file, int stats_interval)
16         : stats_file(stats_file),
17           stats_interval(stats_interval)
18 {
19 }
20
21 void StatsThread::do_work()
22 {
23         while (!should_stop) {
24                 int fd;
25                 FILE *fp;
26                 time_t now;
27                 vector<ClientStats> client_stats;
28
29                 // Open a new, temporary file.
30                 char *filename = strdup((stats_file + ".new.XXXXXX").c_str());
31                 fd = mkostemp(filename, O_WRONLY);
32                 if (fd == -1) {
33                         perror(filename);
34                         free(filename);
35                         goto sleep;
36                 }
37
38                 fp = fdopen(fd, "w");
39                 if (fp == NULL) {
40                         perror("fdopen");
41                         close(fd);
42                         unlink(filename);
43                         free(filename);
44                         goto sleep;
45                 }
46
47                 now = time(NULL);
48                 client_stats = servers->get_client_stats();
49                 for (size_t i = 0; i < client_stats.size(); ++i) {
50                         fprintf(fp, "%s %s %d %llu\n",
51                                 client_stats[i].remote_addr.c_str(),
52                                 client_stats[i].stream_id.c_str(),
53                                 int(now - client_stats[i].connect_time),
54                                 (long long unsigned)(client_stats[i].bytes_sent));
55                 }
56                 if (fclose(fp) == EOF) {
57                         perror("fclose");
58                         unlink(filename);
59                         free(filename);
60                         goto sleep;
61                 }
62                 
63                 if (rename(filename, stats_file.c_str()) == -1) {
64                         perror("rename");
65                         unlink(filename);
66                 }
67
68 sleep:
69                 int left_to_sleep = stats_interval;
70                 do {
71                         left_to_sleep = sleep(left_to_sleep);
72                 } while (left_to_sleep > 0 && !should_stop);
73         }
74 }