aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-02-09 18:45:18 +0000
committerChristian Grothoff <christian@grothoff.org>2014-02-09 18:45:18 +0000
commit9e9b96a4ad14008284c61b475b0ad783469fb74d (patch)
tree00aa4e0f5f1f9eab8b9b12793ad837de35631904 /src/util
parent5caf86f236b1a819abdfdc5c2515bdc087b56a69 (diff)
downloadgnunet-9e9b96a4ad14008284c61b475b0ad783469fb74d.tar.gz
gnunet-9e9b96a4ad14008284c61b475b0ad783469fb74d.zip
add api to bandwidth tracker to notify clients about excess bandwidth available
Diffstat (limited to 'src/util')
-rw-r--r--src/util/bandwidth.c136
1 files changed, 121 insertions, 15 deletions
diff --git a/src/util/bandwidth.c b/src/util/bandwidth.c
index 09107963c..877164789 100644
--- a/src/util/bandwidth.c
+++ b/src/util/bandwidth.c
@@ -74,10 +74,8 @@ GNUNET_BANDWIDTH_value_min (struct GNUNET_BANDWIDTH_Value32NBO b1,
74 * @return number of bytes available at bps until deadline 74 * @return number of bytes available at bps until deadline
75 */ 75 */
76uint64_t 76uint64_t
77GNUNET_BANDWIDTH_value_get_available_until (struct GNUNET_BANDWIDTH_Value32NBO 77GNUNET_BANDWIDTH_value_get_available_until (struct GNUNET_BANDWIDTH_Value32NBO bps,
78 bps, 78 struct GNUNET_TIME_Relative deadline)
79 struct GNUNET_TIME_Relative
80 deadline)
81{ 79{
82 uint64_t b; 80 uint64_t b;
83 81
@@ -121,14 +119,79 @@ GNUNET_BANDWIDTH_value_get_delay_for (struct GNUNET_BANDWIDTH_Value32NBO bps,
121} 119}
122 120
123 121
122/**
123 * Task run whenever we hit the bandwidth limit for a tracker.
124 *
125 * @param cls the `struct GNUNET_BANDWIDTH_Tracker`
126 * @param tc scheduler context
127 */
128static void
129excess_trigger (void *cls,
130 const struct GNUNET_SCHEDULER_TaskContext *tc)
131{
132 struct GNUNET_BANDWIDTH_Tracker *av = cls;
133
134 av->excess_task = GNUNET_SCHEDULER_NO_TASK;
135 av->excess_cb (av->excess_cb_cls);
136}
137
138
139/**
140 * Recalculate when we might need to call the excess callback.
141 */
142static void
143update_excess (struct GNUNET_BANDWIDTH_Tracker *av)
144{
145 struct GNUNET_TIME_Relative delay;
146 struct GNUNET_TIME_Absolute now;
147 uint64_t delta_time;
148 uint64_t delta_avail;
149 int64_t left_bytes;
150 uint64_t max_carry;
151 int64_t current_consumption;
152
153 if (NULL == av->excess_cb)
154 return; /* nothing to do */
155 now = GNUNET_TIME_absolute_get ();
156 delta_time = now.abs_value_us - av->last_update__.abs_value_us;
157 delta_avail =
158 (delta_time * ((unsigned long long) av->available_bytes_per_s__) +
159 500000LL) / 1000000LL;
160 current_consumption = av->consumption_since_last_update__ - delta_avail;
161 /* negative current_consumption means that we have savings */
162 max_carry = av->available_bytes_per_s__ * av->max_carry_s__;
163 if (max_carry < GNUNET_SERVER_MAX_MESSAGE_SIZE)
164 max_carry = GNUNET_SERVER_MAX_MESSAGE_SIZE;
165 left_bytes = max_carry + current_consumption;
166 /* left_bytes now contains the number of bytes needed until
167 we have more savings than allowed */
168 if (left_bytes < 0)
169 {
170 /* having excess already */
171 delay = GNUNET_TIME_UNIT_ZERO;
172 }
173 else
174 {
175 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
176 left_bytes);
177 delay = GNUNET_TIME_relative_divide (delay,
178 av->available_bytes_per_s__);
179 }
180 if (GNUNET_SCHEDULER_NO_TASK != av->excess_task)
181 GNUNET_SCHEDULER_cancel (av->excess_task);
182 av->excess_task = GNUNET_SCHEDULER_add_delayed (delay,
183 &excess_trigger,
184 av);
185}
186
124 187
125/** 188/**
126 * Initialize bandwidth tracker. Note that in addition to the 189 * Initialize bandwidth tracker. Note that in addition to the
127 * 'max_carry_s' limit, we also always allow at least 190 * 'max_carry_s' limit, we also always allow at least
128 * GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the 191 * #GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the
129 * bytes-per-second limit is so small that within 'max_carry_s' not 192 * bytes-per-second limit is so small that within 'max_carry_s' not
130 * even GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is 193 * even #GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is
131 * ignored and replaced by GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in 194 * ignored and replaced by #GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in
132 * bytes). 195 * bytes).
133 * 196 *
134 * @param av tracker to initialize 197 * @param av tracker to initialize
@@ -137,13 +200,17 @@ GNUNET_BANDWIDTH_value_get_delay_for (struct GNUNET_BANDWIDTH_Value32NBO bps,
137 * @param bytes_per_second_limit initial limit to assume 200 * @param bytes_per_second_limit initial limit to assume
138 * @param max_carry_s maximum number of seconds unused bandwidth 201 * @param max_carry_s maximum number of seconds unused bandwidth
139 * may accumulate before it expires 202 * may accumulate before it expires
203 * @param excess_cb callback to notify if we have excess bandwidth
204 * @param excess_cb_cls closure for @a excess_cb
140 */ 205 */
141void 206void
142GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av, 207GNUNET_BANDWIDTH_tracker_init2 (struct GNUNET_BANDWIDTH_Tracker *av,
143 GNUNET_BANDWIDTH_tracker_update_cb update_cb, 208 GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb,
144 void *update_cb_cls, 209 void *update_cb_cls,
145 struct GNUNET_BANDWIDTH_Value32NBO 210 struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit,
146 bytes_per_second_limit, uint32_t max_carry_s) 211 uint32_t max_carry_s,
212 GNUNET_BANDWIDTH_ExcessNotificationCallback excess_cb,
213 void *excess_cb_cls)
147{ 214{
148 av->update_cb = update_cb; 215 av->update_cb = update_cb;
149 av->update_cb_cls = update_cb_cls; 216 av->update_cb_cls = update_cb_cls;
@@ -151,9 +218,45 @@ GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av,
151 av->last_update__ = GNUNET_TIME_absolute_get (); 218 av->last_update__ = GNUNET_TIME_absolute_get ();
152 av->available_bytes_per_s__ = ntohl (bytes_per_second_limit.value__); 219 av->available_bytes_per_s__ = ntohl (bytes_per_second_limit.value__);
153 av->max_carry_s__ = max_carry_s; 220 av->max_carry_s__ = max_carry_s;
221 av->excess_cb = excess_cb;
222 av->excess_cb_cls = excess_cb_cls;
154 LOG (GNUNET_ERROR_TYPE_DEBUG, 223 LOG (GNUNET_ERROR_TYPE_DEBUG,
155 "Tracker %p initialized with %u Bps and max carry %u\n", av, 224 "Tracker %p initialized with %u Bps and max carry %u\n",
156 (unsigned int) av->available_bytes_per_s__, (unsigned int) max_carry_s); 225 av,
226 (unsigned int) av->available_bytes_per_s__,
227 (unsigned int) max_carry_s);
228 update_excess (av);
229}
230
231
232/**
233 * Initialize bandwidth tracker. Note that in addition to the
234 * 'max_carry_s' limit, we also always allow at least
235 * GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the
236 * bytes-per-second limit is so small that within 'max_carry_s' not
237 * even GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is
238 * ignored and replaced by GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in
239 * bytes).
240 *
241 * @param av tracker to initialize
242 * @param update_cb callback to notify a client about the tracker being updated
243 * @param update_cb_cls cls for the callback
244 * @param bytes_per_second_limit initial limit to assume
245 * @param max_carry_s maximum number of seconds unused bandwidth
246 * may accumulate before it expires
247 */
248void
249GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av,
250 GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb,
251 void *update_cb_cls,
252 struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit,
253 uint32_t max_carry_s)
254{
255 GNUNET_BANDWIDTH_tracker_init2 (av, update_cb,
256 update_cb_cls,
257 bytes_per_second_limit,
258 max_carry_s,
259 NULL, NULL);
157} 260}
158 261
159 262
@@ -230,6 +333,7 @@ GNUNET_BANDWIDTH_tracker_consume (struct GNUNET_BANDWIDTH_Tracker *av,
230 } 333 }
231 av->consumption_since_last_update__ = nc; 334 av->consumption_since_last_update__ = nc;
232 update_tracker (av); 335 update_tracker (av);
336 update_excess (av);
233 if (av->consumption_since_last_update__ > 0) 337 if (av->consumption_since_last_update__ > 0)
234 { 338 {
235 LOG (GNUNET_ERROR_TYPE_DEBUG, 339 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -241,6 +345,7 @@ GNUNET_BANDWIDTH_tracker_consume (struct GNUNET_BANDWIDTH_Tracker *av,
241 else 345 else
242 { 346 {
243 av->consumption_since_last_update__ += size; 347 av->consumption_since_last_update__ += size;
348 update_excess (av);
244 } 349 }
245 return GNUNET_NO; 350 return GNUNET_NO;
246} 351}
@@ -262,7 +367,7 @@ GNUNET_BANDWIDTH_tracker_get_delay (struct GNUNET_BANDWIDTH_Tracker *av,
262 struct GNUNET_TIME_Relative ret; 367 struct GNUNET_TIME_Relative ret;
263 int64_t bytes_needed; 368 int64_t bytes_needed;
264 369
265 if (av->available_bytes_per_s__ == 0) 370 if (0 == av->available_bytes_per_s__)
266 { 371 {
267 LOG (GNUNET_ERROR_TYPE_DEBUG, 372 LOG (GNUNET_ERROR_TYPE_DEBUG,
268 "Tracker %p delay is infinity\n", av); 373 "Tracker %p delay is infinity\n", av);
@@ -340,6 +445,7 @@ GNUNET_BANDWIDTH_tracker_update_quota (struct GNUNET_BANDWIDTH_Tracker *av,
340 av->update_cb (av->update_cb_cls); 445 av->update_cb (av->update_cb_cls);
341 if (old_limit > new_limit) 446 if (old_limit > new_limit)
342 update_tracker (av); /* maximum excess might be less now */ 447 update_tracker (av); /* maximum excess might be less now */
448 update_excess (av);
343} 449}
344 450
345 451