File: disk_space_estimator.cpp

package info (click to toggle)
nageru 2.3.2-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 3,120 kB
  • sloc: cpp: 39,131; perl: 94; sh: 18; makefile: 4
file content (81 lines) | stat: -rw-r--r-- 2,188 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "shared/disk_space_estimator.h"

#include <memory>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/statfs.h>

#include "shared/metrics.h"
#include "shared/timebase.h"

using namespace std;

DiskSpaceEstimator::DiskSpaceEstimator(DiskSpaceEstimator::callback_t callback)
	: callback(callback)
{
	global_metrics.add("disk_free_bytes", &metric_disk_free_bytes, Metrics::TYPE_GAUGE);
}

void DiskSpaceEstimator::report_write(const string &filename, off_t bytes, uint64_t pts)
{
	total_size += bytes;
	report_write_internal(filename, total_size, pts);
}

void DiskSpaceEstimator::report_append(const string &filename, uint64_t pts)
{
	if (filename != last_filename) {
		last_filename = filename;
		measure_points.clear();
	}

	struct stat st;
	if (stat(filename.c_str(), &st) == -1) {
		perror(filename.c_str());
		return;
	}

	report_write_internal(filename, st.st_size, pts);
}

void DiskSpaceEstimator::report_write_internal(const string &filename, off_t file_size, uint64_t pts)
{
	if (measure_points.empty()) {
		first_pts_this_file = pts;
	}

	// Reject points that are out-of-order (happens with B-frames).
	if (!measure_points.empty() && pts <= measure_points.back().pts) {
		return;
	}

	// Remove too old points.
	while (measure_points.size() > 1 && measure_points.front().pts + window_length < pts) {
		measure_points.pop_front();
	}

	struct statfs fst;
	if (statfs(filename.c_str(), &fst) == -1) {
		perror(filename.c_str());
		return;
	}

	off_t free_bytes = off_t(fst.f_bavail) * fst.f_frsize;
	metric_disk_free_bytes = free_bytes;

	if (!measure_points.empty()) {
		double bytes_per_second = double(file_size - measure_points.front().size) /
			(pts - measure_points.front().pts) * TIMEBASE;
		double seconds_left = free_bytes / bytes_per_second;

		// Only report every second, since updating the UI can be expensive.
		if (last_pts_reported == 0 || pts - last_pts_reported >= TIMEBASE) {
			callback(free_bytes, seconds_left, double(pts - first_pts_this_file) / TIMEBASE);
			last_pts_reported = pts;
		}
	}

	measure_points.push_back({ pts, file_size });
}

DiskSpaceEstimator *global_disk_space_estimator = nullptr;  // Created in MainWindow::MainWindow().