1 #include "shared/disk_space_estimator.h"
6 #include <sys/statfs.h>
8 #include "shared/metrics.h"
9 #include "shared/timebase.h"
13 DiskSpaceEstimator::DiskSpaceEstimator(DiskSpaceEstimator::callback_t callback)
16 global_metrics.add("disk_free_bytes", &metric_disk_free_bytes, Metrics::TYPE_GAUGE);
19 void DiskSpaceEstimator::report_write(const string &filename, off_t bytes, uint64_t pts)
22 report_write_internal(filename, total_size, pts);
25 void DiskSpaceEstimator::report_append(const string &filename, uint64_t pts)
27 if (filename != last_filename) {
28 last_filename = filename;
29 measure_points.clear();
33 if (stat(filename.c_str(), &st) == -1) {
34 perror(filename.c_str());
38 report_write_internal(filename, st.st_size, pts);
41 void DiskSpaceEstimator::report_write_internal(const string &filename, off_t file_size, uint64_t pts)
43 // Reject points that are out-of-order (happens with B-frames).
44 if (!measure_points.empty() && pts <= measure_points.back().pts) {
48 // Remove too old points.
49 while (measure_points.size() > 1 && measure_points.front().pts + window_length < pts) {
50 measure_points.pop_front();
54 if (statfs(filename.c_str(), &fst) == -1) {
55 perror(filename.c_str());
59 off_t free_bytes = off_t(fst.f_bavail) * fst.f_frsize;
60 metric_disk_free_bytes = free_bytes;
62 if (!measure_points.empty()) {
63 double bytes_per_second = double(file_size - measure_points.front().size) /
64 (pts - measure_points.front().pts) * TIMEBASE;
65 double seconds_left = free_bytes / bytes_per_second;
67 // Only report every second, since updating the UI can be expensive.
68 if (last_pts_reported == 0 || pts - last_pts_reported >= TIMEBASE) {
69 callback(free_bytes, seconds_left);
70 last_pts_reported = pts;
74 measure_points.push_back({ pts, file_size });
77 DiskSpaceEstimator *global_disk_space_estimator = nullptr; // Created in MainWindow::MainWindow().