]> git.sesse.net Git - cubemap/blob - input_stats.cpp
Release Cubemap 1.1.1.
[cubemap] / input_stats.cpp
1 #include <fcntl.h>
2 #include <stddef.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <time.h>
7 #include <unistd.h>
8 #include <vector>
9
10 #include "input.h"
11 #include "input_stats.h"
12 #include "log.h"
13 #include "util.h"
14
15 using namespace std;
16
17 InputStatsThread::InputStatsThread(const string &stats_file, int stats_interval, const vector<Input*> &inputs)
18         : stats_file(stats_file),
19           stats_interval(stats_interval),
20           inputs(inputs)
21 {
22 }
23
24 void InputStatsThread::do_work()
25 {
26         while (!should_stop()) {
27                 int fd;
28                 FILE *fp;
29                 time_t now;
30
31                 // Open a new, temporary file.
32                 char *filename = strdup((stats_file + ".new.XXXXXX").c_str());
33                 fd = mkostemp(filename, O_WRONLY);
34                 if (fd == -1) {
35                         log_perror(filename);
36                         free(filename);
37                         goto sleep;
38                 }
39
40                 fp = fdopen(fd, "w");
41                 if (fp == NULL) {
42                         log_perror("fdopen");
43                         safe_close(fd);
44                         if (unlink(filename) == -1) {
45                                 log_perror(filename);
46                         }
47                         free(filename);
48                         goto sleep;
49                 }
50
51                 now = time(NULL);
52                 for (size_t i = 0; i < inputs.size(); ++i) {
53                         InputStats stats = inputs[i]->get_stats();
54                         if (stats.connect_time == -1) {
55                                 fprintf(fp, "%s %llu %llu -\n", stats.url.c_str(),
56                                         (long long unsigned)(stats.bytes_received),
57                                         (long long unsigned)(stats.data_bytes_received));
58                         } else {
59                                 fprintf(fp, "%s %llu %llu %d\n", stats.url.c_str(),
60                                         (long long unsigned)(stats.bytes_received),
61                                         (long long unsigned)(stats.data_bytes_received),
62                                         int(now - stats.connect_time));
63                         }
64                 }
65                 if (fclose(fp) == EOF) {
66                         log_perror("fclose");
67                         if (unlink(filename) == -1) {
68                                 log_perror(filename);
69                         }
70                         free(filename);
71                         goto sleep;
72                 }
73                 
74                 if (rename(filename, stats_file.c_str()) == -1) {
75                         log_perror("rename");
76                         if (unlink(filename) == -1) {
77                                 log_perror(filename);
78                         }
79                 }
80                 free(filename);
81
82 sleep:
83                 // Wait until we are asked to quit, stats_interval timeout,
84                 // or a spurious signal. (The latter will cause us to write stats
85                 // too often, but that's okay.)
86                 timespec timeout_ts;
87                 timeout_ts.tv_sec = stats_interval;
88                 timeout_ts.tv_nsec = 0;
89                 wait_for_wakeup(&timeout_ts);
90         }
91 }