1 // libTorrent - BitTorrent library
2 // Copyright (C) 2005-2011, Jari Sundell
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 //
18 // In addition, as a special exception, the copyright holders give
19 // permission to link the code of portions of this program with the
20 // OpenSSL library under certain conditions as described in each
21 // individual source file, and distribute linked combinations
22 // including the two.
23 //
24 // You must obey the GNU General Public License in all respects for
25 // all of the code used other than OpenSSL. If you modify file(s)
26 // with this exception, you may extend this exception to your version
27 // of the file(s), but you are not obligated to do so. If you do not
28 // wish to do so, delete this exception statement from your version.
29 // If you delete this exception statement from all source files in the
30 // program, then also delete it here.
31 //
32 // Contact: Jari Sundell <jaris@ifi.uio.no>
33 //
34 // Skomakerveien 33
35 // 3185 Skoppum, NORWAY
36
37 #include "config.h"
38
39 #include <rak/timer.h>
40
41 #include "net/throttle_internal.h"
42 #include "net/throttle_list.h"
43
44 #include "globals.h"
45
46 #include "exceptions.h"
47 #include "throttle.h"
48
49 namespace torrent {
50
51 // Plans:
52 //
53 // Make ThrottleList do a callback when it needs more? This would
54 // allow us to remove us from the task scheduler when we're full. Also
55 // this would let us be abit more flexible with the interval.
56
57 Throttle*
create_throttle()58 Throttle::create_throttle() {
59 ThrottleInternal* throttle = new ThrottleInternal(ThrottleInternal::flag_root);
60
61 throttle->m_maxRate = 0;
62 throttle->m_throttleList = new ThrottleList();
63
64 return throttle;
65 }
66
67 void
destroy_throttle(Throttle * throttle)68 Throttle::destroy_throttle(Throttle* throttle) {
69 delete throttle->m_ptr()->m_throttleList;
70 delete throttle->m_ptr();
71 }
72
73 Throttle*
create_slave()74 Throttle::create_slave() {
75 return m_ptr()->create_slave();
76 }
77
78 bool
is_throttled()79 Throttle::is_throttled() {
80 return m_maxRate != 0 && m_maxRate != std::numeric_limits<uint32_t>::max();
81 }
82
83 void
set_max_rate(uint32_t v)84 Throttle::set_max_rate(uint32_t v) {
85 if (v == m_maxRate)
86 return;
87
88 if (v > (1 << 30))
89 throw input_error("Throttle rate must be between 0 and 2^30.");
90
91 uint32_t oldRate = m_maxRate;
92 m_maxRate = v;
93
94 m_throttleList->set_min_chunk_size(calculate_min_chunk_size());
95 m_throttleList->set_max_chunk_size(calculate_max_chunk_size());
96
97 if (!m_ptr()->is_root())
98 return;
99
100 if (oldRate == 0)
101 m_ptr()->enable();
102 else if (m_maxRate == 0)
103 m_ptr()->disable();
104 }
105
106 const Rate*
rate() const107 Throttle::rate() const {
108 return m_throttleList->rate_slow();
109 }
110
111 uint32_t
calculate_min_chunk_size() const112 Throttle::calculate_min_chunk_size() const {
113 // Just for each modification, make this into a function, rather
114 // than if-else chain.
115 if (m_maxRate <= (8 << 10))
116 return (1 << 9);
117
118 else if (m_maxRate <= (32 << 10))
119 return (2 << 9);
120
121 else if (m_maxRate <= (64 << 10))
122 return (3 << 9);
123
124 else if (m_maxRate <= (128 << 10))
125 return (4 << 9);
126
127 else if (m_maxRate <= (512 << 10))
128 return (8 << 9);
129
130 else if (m_maxRate <= (2048 << 10))
131 return (16 << 9);
132
133 else
134 return (32 << 9);
135 }
136
137 uint32_t
calculate_max_chunk_size() const138 Throttle::calculate_max_chunk_size() const {
139 // Make this return a lower value for very low throttle settings.
140 return calculate_min_chunk_size() * 4;
141 }
142
143 uint32_t
calculate_interval() const144 Throttle::calculate_interval() const {
145 uint32_t rate = m_throttleList->rate_slow()->rate();
146
147 if (rate < 1024)
148 return 10 * 100000;
149
150 // At least two max chunks per tick.
151 uint32_t interval = (5 * m_throttleList->max_chunk_size()) / rate;
152
153 if (interval == 0)
154 return 1 * 100000;
155 else if (interval > 10)
156 return 10 * 100000;
157 else
158 return interval * 100000;
159 }
160
161 }
162