diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-02-09 18:45:18 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-02-09 18:45:18 +0000 |
commit | 9e9b96a4ad14008284c61b475b0ad783469fb74d (patch) | |
tree | 00aa4e0f5f1f9eab8b9b12793ad837de35631904 /src/util/bandwidth.c | |
parent | 5caf86f236b1a819abdfdc5c2515bdc087b56a69 (diff) | |
download | gnunet-9e9b96a4ad14008284c61b475b0ad783469fb74d.tar.gz gnunet-9e9b96a4ad14008284c61b475b0ad783469fb74d.zip |
add api to bandwidth tracker to notify clients about excess bandwidth available
Diffstat (limited to 'src/util/bandwidth.c')
-rw-r--r-- | src/util/bandwidth.c | 136 |
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 | */ |
76 | uint64_t | 76 | uint64_t |
77 | GNUNET_BANDWIDTH_value_get_available_until (struct GNUNET_BANDWIDTH_Value32NBO | 77 | GNUNET_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 | */ | ||
128 | static void | ||
129 | excess_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 | */ | ||
142 | static void | ||
143 | update_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 | */ |
141 | void | 206 | void |
142 | GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av, | 207 | GNUNET_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 | */ | ||
248 | void | ||
249 | GNUNET_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 | ||