File: ratelimit.cpp

package info (click to toggle)
libfilezilla 0.52.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,492 kB
  • sloc: cpp: 30,965; sh: 4,241; makefile: 375; xml: 37
file content (110 lines) | stat: -rw-r--r-- 2,776 bytes parent folder | download | duplicates (3)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "../lib/libfilezilla/rate_limiter.hpp"

#include <array>
#include <iostream>

struct handler : public fz::event_handler
{
	handler(fz::event_loop & loop)
	    : fz::event_handler(loop)
	    , loop_(loop)
	    , mgr_(loop)
	    , start_(fz::monotonic_clock::now())
	{
		mgr_.add(&limiter_);

		add_timer(fz::duration::from_milliseconds(10), false);

		limiter_.add(&buckets_[0]);
		limiter_.add(&buckets_[1]);
		limiter_.add(&buckets_[2]);
		limiter_.add(&sub_limiter_[0]);
		limiter_.add(&sub_limiter_[1]);
		limiter_.add(&sub_limiter_[2]);
		sub_limiter_[0].add(&buckets_[3]);
		sub_limiter_[0].add(&buckets_[4]);
		sub_limiter_[1].add(&buckets_[5]);
		sub_limiter_[2].add(&buckets_[6]);
		limiter_.set_limits(10000, fz::rate::unlimited);
		sub_limiter_[0].set_limits(1000, fz::rate::unlimited);

		sub_limiter_[1].set_limits(2500, fz::rate::unlimited);
	}

	~handler()
	{
		remove_handler();
	}

	void operator()(fz::event_base const& ev)
	{
		fz::dispatch<fz::timer_event>(ev, this, &handler::on_timer);
	}

	void on_timer(fz::timer_id const&)
	{
		auto const now = fz::monotonic_clock::now();
		int const elapsed = (now - start_).get_seconds();

		int const delay = 3;
		int const duration = 5;
		if (elapsed >= delay + duration) {
			fz::rate::type sum{};
			for (size_t i = 0; i < buckets_.size(); ++i) {
				sum += consumed_[i];
				std::cout << "Bucket " << i << " has rate of " << consumed_[i] / duration << " bytes/s\n";
			}
			std::cout << "Total rate is " << sum / duration << " bytes/s\n";

			float ratio = float(sum) / (limiter_.limit(fz::direction::inbound) * duration);
			if (ratio < 0.9 || ratio > 1.1) {
				std::cout << "Bad total rate ratio: " << ratio << std::endl;
				exit(1);
			}

			ratio = float(consumed_[3] + consumed_[4]) / (sub_limiter_[0].limit(fz::direction::inbound) * duration);
			if (ratio < 0.9 || ratio > 1.1) {
				std::cout << "Bad sublimit rate ratio: " << ratio << std::endl;
				exit(1);
			}

			loop_.stop();
		}

		for (size_t i = 0; i < buckets_.size(); ++i) {
			fz::rate::type amount = rates_[i];
			fz::rate::type available = buckets_[i].available(fz::direction::inbound);
			if (available != fz::rate::unlimited && available < amount) {
				amount = available;
			}
			if (elapsed >= delay) {
				consumed_[i] += amount;
			}
			buckets_[i].consume(fz::direction::inbound, amount);
		}
	}

	fz::event_loop & loop_;

	fz::rate_limit_manager mgr_;
	fz::rate_limiter limiter_;
	fz::rate_limiter sub_limiter_[3];

	std::array<fz::rate::type, 7> rates_{1, 2, 1000, 3, 1000, 100000, 100000};
	std::array<fz::bucket, 7> buckets_;
	std::array<fz::rate::type, 7> consumed_{};

	fz::monotonic_clock start_;
};

int main()
{
	fz::event_loop loop(fz::event_loop::threadless);

	handler h(loop);

	loop.run();

	return 0;
}