diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-02-05 12:52:20 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-02-05 12:52:20 +0000 |
commit | c55971f17dc99f9833af48e078c8f681be771cb7 (patch) | |
tree | 544fd671b67903506419c98d463d086a696e25a1 /src/ats/gnunet-service-ats_normalization.c | |
parent | 15dd8e6cc1199d611d804853e134882bf13b234a (diff) | |
download | gnunet-c55971f17dc99f9833af48e078c8f681be771cb7.tar.gz gnunet-c55971f17dc99f9833af48e078c8f681be771cb7.zip |
big ATS refactoring, no serious semantic changes should stem from this
Diffstat (limited to 'src/ats/gnunet-service-ats_normalization.c')
-rw-r--r-- | src/ats/gnunet-service-ats_normalization.c | 730 |
1 files changed, 34 insertions, 696 deletions
diff --git a/src/ats/gnunet-service-ats_normalization.c b/src/ats/gnunet-service-ats_normalization.c index b4051c9fa..7003f69e4 100644 --- a/src/ats/gnunet-service-ats_normalization.c +++ b/src/ats/gnunet-service-ats_normalization.c | |||
@@ -23,116 +23,18 @@ | |||
23 | * @brief ats service address: management of ATS properties and preferences normalization | 23 | * @brief ats service address: management of ATS properties and preferences normalization |
24 | * @author Matthias Wachs | 24 | * @author Matthias Wachs |
25 | * @author Christian Grothoff | 25 | * @author Christian Grothoff |
26 | * | ||
27 | * FIXME: rename to 'properties'! | ||
26 | */ | 28 | */ |
27 | #include "platform.h" | 29 | #include "platform.h" |
28 | #include "gnunet_ats_service.h" | 30 | #include "gnunet_ats_service.h" |
29 | #include "gnunet-service-ats_addresses.h" | 31 | #include "gnunet-service-ats_addresses.h" |
30 | #include "gnunet-service-ats_normalization.h" | 32 | #include "gnunet-service-ats_normalization.h" |
33 | #include "gnunet-service-ats_plugins.h" | ||
31 | 34 | ||
32 | #define LOG(kind,...) GNUNET_log_from (kind, "ats-normalization",__VA_ARGS__) | 35 | #define LOG(kind,...) GNUNET_log_from (kind, "ats-normalization",__VA_ARGS__) |
33 | 36 | ||
34 | /** | ||
35 | * Preference client | ||
36 | */ | ||
37 | struct PreferenceClient | ||
38 | { | ||
39 | /** | ||
40 | * Next in DLL | ||
41 | */ | ||
42 | struct PreferenceClient *prev; | ||
43 | |||
44 | /** | ||
45 | * Next in DLL | ||
46 | */ | ||
47 | |||
48 | struct PreferenceClient *next; | ||
49 | |||
50 | /** | ||
51 | * Client handle | ||
52 | */ | ||
53 | void *client; | ||
54 | |||
55 | /** | ||
56 | * Array of sum of absolute preferences for this client | ||
57 | */ | ||
58 | double f_abs_sum[GNUNET_ATS_PreferenceCount]; | ||
59 | |||
60 | /** | ||
61 | * Array of sum of relative preferences for this client | ||
62 | */ | ||
63 | double f_rel_sum[GNUNET_ATS_PreferenceCount]; | ||
64 | |||
65 | /** | ||
66 | * List of peer preferences for this client | ||
67 | */ | ||
68 | |||
69 | /** | ||
70 | * Head of peer list | ||
71 | */ | ||
72 | struct PreferencePeer *p_head; | ||
73 | |||
74 | /** | ||
75 | * Tail of peer list | ||
76 | */ | ||
77 | struct PreferencePeer *p_tail; | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * Preference peer | ||
82 | */ | ||
83 | struct PreferencePeer | ||
84 | { | ||
85 | /** | ||
86 | * Next in DLL | ||
87 | */ | ||
88 | struct PreferencePeer *next; | ||
89 | |||
90 | /** | ||
91 | * Previous in DLL | ||
92 | */ | ||
93 | struct PreferencePeer *prev; | ||
94 | |||
95 | /** | ||
96 | * Client | ||
97 | */ | ||
98 | struct PreferenceClient *client; | ||
99 | |||
100 | /** | ||
101 | * Peer id | ||
102 | */ | ||
103 | struct GNUNET_PeerIdentity id; | ||
104 | 37 | ||
105 | /** | ||
106 | * Absolute preference values for all preference types | ||
107 | */ | ||
108 | double f_abs[GNUNET_ATS_PreferenceCount]; | ||
109 | |||
110 | /** | ||
111 | * Relative preference values for all preference types | ||
112 | */ | ||
113 | double f_rel[GNUNET_ATS_PreferenceCount]; | ||
114 | |||
115 | /** | ||
116 | * Absolute point of time of next aging process | ||
117 | */ | ||
118 | struct GNUNET_TIME_Absolute next_aging[GNUNET_ATS_PreferenceCount]; | ||
119 | }; | ||
120 | |||
121 | /** | ||
122 | * Relative preferences for a peer | ||
123 | */ | ||
124 | struct PeerRelative | ||
125 | { | ||
126 | /** | ||
127 | * Relative preference values | ||
128 | */ | ||
129 | double f_rel[GNUNET_ATS_PreferenceCount]; | ||
130 | |||
131 | /** | ||
132 | * Peer id | ||
133 | */ | ||
134 | struct GNUNET_PeerIdentity id; | ||
135 | }; | ||
136 | 38 | ||
137 | /** | 39 | /** |
138 | * Quality Normalization | 40 | * Quality Normalization |
@@ -147,490 +49,27 @@ struct Property | |||
147 | 49 | ||
148 | static struct Property properties[GNUNET_ATS_QualityPropertiesCount]; | 50 | static struct Property properties[GNUNET_ATS_QualityPropertiesCount]; |
149 | 51 | ||
150 | |||
151 | /** | ||
152 | * Callback to call on changing preference values | ||
153 | */ | ||
154 | static GAS_Normalization_preference_changed_cb pref_changed_cb; | ||
155 | |||
156 | /** | ||
157 | * Closure for callback to call on changing preference values | ||
158 | */ | ||
159 | static void *pref_changed_cb_cls; | ||
160 | |||
161 | /** | ||
162 | * Callback to call on changing property values | ||
163 | */ | ||
164 | static GAS_Normalization_property_changed_cb prop_ch_cb; | ||
165 | |||
166 | /** | ||
167 | * Closure for callback to call on changing property values | ||
168 | */ | ||
169 | static void *prop_ch_cb_cls; | ||
170 | |||
171 | /** | ||
172 | * Hashmap to store peer information for preference normalization | ||
173 | */ | ||
174 | static struct GNUNET_CONTAINER_MultiPeerMap *preference_peers; | ||
175 | |||
176 | /** | 52 | /** |
177 | * Hashmap to store peer information for property normalization | 53 | * Hashmap to store peer information for property normalization |
178 | * FIXME: this map is not used! | 54 | * FIXME: this map is not used! |
179 | */ | 55 | */ |
180 | static struct GNUNET_CONTAINER_MultiPeerMap *property_peers; | 56 | static struct GNUNET_CONTAINER_MultiPeerMap *property_peers; |
181 | 57 | ||
182 | /** | ||
183 | * Clients in DLL: head | ||
184 | */ | ||
185 | static struct PreferenceClient *pc_head; | ||
186 | |||
187 | /** | ||
188 | * Clients in DLL: tail | ||
189 | */ | ||
190 | static struct PreferenceClient *pc_tail; | ||
191 | |||
192 | /** | ||
193 | * Default values | ||
194 | */ | ||
195 | static struct PeerRelative defvalues; | ||
196 | |||
197 | static struct GNUNET_SCHEDULER_Task * aging_task; | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Update a peer | ||
202 | * | ||
203 | * @param id peer id | ||
204 | * @param kind the kind | ||
205 | * @param rp the relative peer struct | ||
206 | * @return the new relative preference | ||
207 | */ | ||
208 | static void | ||
209 | update_relative_values_for_peer (const struct GNUNET_PeerIdentity *id, | ||
210 | enum GNUNET_ATS_PreferenceKind kind, struct PeerRelative *rp) | ||
211 | { | ||
212 | struct PreferenceClient *c_cur; | ||
213 | struct PreferencePeer *p_cur; | ||
214 | double f_rel_total; | ||
215 | double f_rel_sum; | ||
216 | double backup; | ||
217 | unsigned int peer_count; | ||
218 | |||
219 | f_rel_sum = 0.0; | ||
220 | f_rel_total = 0.0; | ||
221 | peer_count = 0; | ||
222 | |||
223 | /* For all clients */ | ||
224 | for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) | ||
225 | { | ||
226 | /* For peer entries with this id */ | ||
227 | for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) | ||
228 | { | ||
229 | f_rel_sum += p_cur->f_rel[kind]; | ||
230 | if (0 == memcmp (id, &p_cur->id, sizeof(struct GNUNET_PeerIdentity))) | ||
231 | { | ||
232 | peer_count ++; | ||
233 | f_rel_total += p_cur->f_rel[kind]; | ||
234 | } | ||
235 | |||
236 | } | ||
237 | } | ||
238 | |||
239 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
240 | "%u clients have a total relative preference for peer `%s' `%s' of %.3f and for %s in total %.3f\n", | ||
241 | peer_count, GNUNET_i2s (id), | ||
242 | GNUNET_ATS_print_preference_type (kind), | ||
243 | f_rel_total, | ||
244 | GNUNET_ATS_print_preference_type (kind), | ||
245 | f_rel_sum); | ||
246 | |||
247 | /* Find entry for the peer containing relative values in the hashmap */ | ||
248 | if (NULL != rp) | ||
249 | { | ||
250 | backup = rp->f_rel[kind]; | ||
251 | if (f_rel_sum > 0) | ||
252 | rp->f_rel[kind] = f_rel_total / f_rel_sum; | ||
253 | else | ||
254 | { | ||
255 | /* No client had any preferences for this type and any peer */ | ||
256 | rp->f_rel[kind] = DEFAULT_REL_PREFERENCE; | ||
257 | } | ||
258 | if ((backup != rp->f_rel[kind]) && (NULL != pref_changed_cb)) | ||
259 | { | ||
260 | pref_changed_cb (pref_changed_cb_cls, &rp->id, kind, rp->f_rel[kind]); | ||
261 | } | ||
262 | } | ||
263 | } | ||
264 | |||
265 | |||
266 | /** | ||
267 | * Recalculate preference for a specific ATS property | ||
268 | * | ||
269 | * @param c the preference client | ||
270 | * @param kind the preference kind | ||
271 | * @return the result | ||
272 | */ | ||
273 | static void | ||
274 | recalculate_relative_preferences (struct PreferenceClient *c, | ||
275 | enum GNUNET_ATS_PreferenceKind kind) | ||
276 | { | ||
277 | struct PreferencePeer *p_cur; | ||
278 | |||
279 | /* For this client: sum of absolute preference values for this preference */ | ||
280 | c->f_abs_sum[kind] = 0.0; | ||
281 | /* For this client: sum of relative preference values for this preference | ||
282 | * | ||
283 | * Note: this value should also be 1.0, but: | ||
284 | * if no preferences exist due to aging, this value can be 0.0 | ||
285 | * and the client can be removed */ | ||
286 | c->f_rel_sum[kind] = 0.0; | ||
287 | |||
288 | for (p_cur = c->p_head; NULL != p_cur; p_cur = p_cur->next) | ||
289 | c->f_abs_sum[kind] += p_cur->f_abs[kind]; | ||
290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
291 | "Client %p has sum of total preferences for %s of %.3f\n", | ||
292 | c->client, GNUNET_ATS_print_preference_type (kind), c->f_abs_sum[kind]); | ||
293 | |||
294 | /* For all peers: calculate relative preference */ | ||
295 | for (p_cur = c->p_head; NULL != p_cur; p_cur = p_cur->next) | ||
296 | { | ||
297 | /* Calculate relative preference for specific kind */ | ||
298 | |||
299 | /* Every application has a preference for each peer between | ||
300 | * [0 .. 1] in relative values | ||
301 | * and [0 .. inf] in absolute values */ | ||
302 | p_cur->f_rel[kind] = p_cur->f_abs[kind] / c->f_abs_sum[kind]; | ||
303 | c->f_rel_sum[kind] += p_cur->f_rel[kind]; | ||
304 | |||
305 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
306 | "Client %p has relative preference for %s for peer `%s' of %.3f\n", | ||
307 | c->client, | ||
308 | GNUNET_ATS_print_preference_type (kind), | ||
309 | GNUNET_i2s (&p_cur->id), | ||
310 | p_cur->f_rel[kind]); | ||
311 | } | ||
312 | |||
313 | } | ||
314 | |||
315 | |||
316 | /** | ||
317 | * Update the absolute preference value for a peer | ||
318 | * @param c the client | ||
319 | * @param p the peer | ||
320 | * @param kind the preference kind | ||
321 | * @param score_abs the absolute value | ||
322 | * @return the new relative preference value | ||
323 | */ | ||
324 | static void | ||
325 | update_abs_preference (struct PreferenceClient *c, | ||
326 | struct PreferencePeer *p, | ||
327 | enum GNUNET_ATS_PreferenceKind kind, | ||
328 | float score_abs) | ||
329 | { | ||
330 | double score = score_abs; | ||
331 | |||
332 | /* Update preference value according to type */ | ||
333 | switch (kind) | ||
334 | { | ||
335 | case GNUNET_ATS_PREFERENCE_BANDWIDTH: | ||
336 | case GNUNET_ATS_PREFERENCE_LATENCY: | ||
337 | p->f_abs[kind] = score; | ||
338 | /* p->f_abs[kind] = (p->f_abs[kind] + score) / 2; */ | ||
339 | p->next_aging[kind] = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
340 | PREF_AGING_INTERVAL); | ||
341 | break; | ||
342 | case GNUNET_ATS_PREFERENCE_END: | ||
343 | break; | ||
344 | default: | ||
345 | break; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | |||
350 | static int | ||
351 | update_iterator (void *cls, | ||
352 | const struct GNUNET_PeerIdentity *key, | ||
353 | void *value) | ||
354 | { | ||
355 | enum GNUNET_ATS_PreferenceKind *kind = cls; | ||
356 | struct PeerRelative *pr = value; | ||
357 | |||
358 | update_relative_values_for_peer (key, | ||
359 | (*kind), | ||
360 | pr); | ||
361 | return GNUNET_OK; | ||
362 | } | ||
363 | |||
364 | |||
365 | static void | ||
366 | run_preference_update (struct PreferenceClient *c_cur, | ||
367 | struct PreferencePeer *p_cur, | ||
368 | enum GNUNET_ATS_PreferenceKind kind, | ||
369 | float score_abs) | ||
370 | { | ||
371 | double old_value; | ||
372 | 58 | ||
373 | /* Update relative value */ | ||
374 | old_value = p_cur->f_rel[kind]; | ||
375 | recalculate_relative_preferences (c_cur, kind); | ||
376 | if (p_cur->f_rel[kind] == old_value) | ||
377 | return; | ||
378 | |||
379 | /* Relative preference value changed, recalculate for all peers */ | ||
380 | GNUNET_CONTAINER_multipeermap_iterate (preference_peers, &update_iterator, &kind); | ||
381 | } | ||
382 | |||
383 | |||
384 | /** | ||
385 | * Reduce absolute preferences since they got old | ||
386 | * | ||
387 | * @param cls the PreferencePeer | ||
388 | * @param tc context | ||
389 | */ | ||
390 | static void | ||
391 | preference_aging (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
392 | { | ||
393 | struct PreferencePeer *p; | ||
394 | struct PreferenceClient *cur_client; | ||
395 | int i; | ||
396 | int values_to_update; | ||
397 | double backup; | ||
398 | |||
399 | aging_task = NULL; | ||
400 | values_to_update = 0; | ||
401 | cur_client = NULL; | ||
402 | |||
403 | for (cur_client = pc_head; NULL != cur_client; cur_client = cur_client->next) | ||
404 | { | ||
405 | for (p = cur_client->p_head; NULL != p; p = p->next) | ||
406 | { | ||
407 | /* Aging absolute values: */ | ||
408 | for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) | ||
409 | { | ||
410 | if (0 | ||
411 | == GNUNET_TIME_absolute_get_remaining (p->next_aging[i]).rel_value_us) | ||
412 | { | ||
413 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
414 | "Aging preference for peer `%s'\n", GNUNET_i2s (&p->id)); | ||
415 | backup = p->f_abs[i]; | ||
416 | if (p->f_abs[i] > DEFAULT_ABS_PREFERENCE) | ||
417 | p->f_abs[i] *= PREF_AGING_FACTOR; | ||
418 | |||
419 | if (p->f_abs[i] <= DEFAULT_ABS_PREFERENCE + PREF_EPSILON) | ||
420 | p->f_abs[i] = DEFAULT_ABS_PREFERENCE; | ||
421 | |||
422 | if ( (p->f_abs[i] != DEFAULT_ABS_PREFERENCE) && | ||
423 | (backup != p->f_abs[i]) ) | ||
424 | { | ||
425 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
426 | "Aged preference for peer `%s' from %.3f to %.3f\n", | ||
427 | GNUNET_i2s (&p->id), backup, p->f_abs[i]); | ||
428 | |||
429 | run_preference_update(cur_client, p, i, p->f_abs[i]); | ||
430 | |||
431 | p->next_aging[i] = GNUNET_TIME_absolute_add ( | ||
432 | GNUNET_TIME_absolute_get (), PREF_AGING_INTERVAL); | ||
433 | values_to_update++; | ||
434 | } | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | |||
440 | if (values_to_update > 0) | ||
441 | { | ||
442 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
443 | "Rescheduling aging task due to %u elements to age\n", | ||
444 | values_to_update); | ||
445 | aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL, | ||
446 | &preference_aging, NULL ); | ||
447 | } | ||
448 | else | ||
449 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
450 | "No values to age left, not rescheduling aging task\n"); | ||
451 | |||
452 | } | ||
453 | |||
454 | |||
455 | /** | ||
456 | * Normalize an updated preference value | ||
457 | * | ||
458 | * @param client the client with this preference | ||
459 | * @param peer the peer to change the preference for | ||
460 | * @param kind the kind to change the preference | ||
461 | * @param score_abs the normalized score | ||
462 | */ | ||
463 | void | ||
464 | GAS_normalization_normalize_preference (void *client, | ||
465 | const struct GNUNET_PeerIdentity *peer, | ||
466 | enum GNUNET_ATS_PreferenceKind kind, | ||
467 | float score_abs) | ||
468 | { | ||
469 | struct PreferenceClient *c_cur; | ||
470 | struct PreferencePeer *p_cur; | ||
471 | struct PeerRelative *r_cur; | ||
472 | double old_value; | ||
473 | int i; | ||
474 | |||
475 | GNUNET_assert(NULL != client); | ||
476 | GNUNET_assert(NULL != peer); | ||
477 | |||
478 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
479 | "Client %p changes preference for peer `%s' for `%s' to %.2f\n", | ||
480 | client, | ||
481 | GNUNET_i2s (peer), | ||
482 | GNUNET_ATS_print_preference_type (kind), | ||
483 | score_abs); | ||
484 | |||
485 | if (kind >= GNUNET_ATS_PreferenceCount) | ||
486 | { | ||
487 | GNUNET_break(0); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | /* Find preference client */ | ||
492 | for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) | ||
493 | { | ||
494 | if (client == c_cur->client) | ||
495 | break; | ||
496 | } | ||
497 | /* Not found: create new preference client */ | ||
498 | if (NULL == c_cur) | ||
499 | { | ||
500 | c_cur = GNUNET_new (struct PreferenceClient); | ||
501 | c_cur->client = client; | ||
502 | for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) | ||
503 | { | ||
504 | c_cur->f_abs_sum[i] = DEFAULT_ABS_PREFERENCE; | ||
505 | c_cur->f_rel_sum[i] = DEFAULT_REL_PREFERENCE; | ||
506 | } | ||
507 | |||
508 | GNUNET_CONTAINER_DLL_insert(pc_head, pc_tail, c_cur); | ||
509 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding new client %p \n", c_cur); | ||
510 | } | ||
511 | |||
512 | /* Find entry for peer */ | ||
513 | for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) | ||
514 | if (0 == memcmp (&p_cur->id, peer, sizeof(p_cur->id))) | ||
515 | break; | ||
516 | |||
517 | /* Not found: create new peer entry */ | ||
518 | if (NULL == p_cur) | ||
519 | { | ||
520 | p_cur = GNUNET_new (struct PreferencePeer); | ||
521 | p_cur->client = c_cur; | ||
522 | p_cur->id = (*peer); | ||
523 | for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) | ||
524 | { | ||
525 | /* Default value per peer absolute preference for a preference: 0 */ | ||
526 | p_cur->f_abs[i] = DEFAULT_ABS_PREFERENCE; | ||
527 | /* Default value per peer relative preference for a quality: 1.0 */ | ||
528 | p_cur->f_rel[i] = DEFAULT_REL_PREFERENCE; | ||
529 | p_cur->next_aging[i] = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
530 | } | ||
531 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding new peer %p for client %p \n", | ||
532 | p_cur, c_cur); | ||
533 | GNUNET_CONTAINER_DLL_insert(c_cur->p_head, c_cur->p_tail, p_cur); | ||
534 | } | ||
535 | |||
536 | /* Create struct for peer */ | ||
537 | if (NULL == GNUNET_CONTAINER_multipeermap_get (preference_peers, peer)) | ||
538 | { | ||
539 | r_cur = GNUNET_new (struct PeerRelative); | ||
540 | r_cur->id = (*peer); | ||
541 | for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) | ||
542 | r_cur->f_rel[i] = DEFAULT_REL_PREFERENCE; | ||
543 | GNUNET_assert( | ||
544 | GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (preference_peers, | ||
545 | &r_cur->id, r_cur, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
546 | } | ||
547 | |||
548 | /* Update absolute value */ | ||
549 | old_value = p_cur->f_abs[kind]; | ||
550 | update_abs_preference (c_cur, p_cur, kind, score_abs); | ||
551 | if (p_cur->f_abs[kind] == old_value) | ||
552 | return; | ||
553 | |||
554 | run_preference_update (c_cur, p_cur, kind, score_abs); | ||
555 | |||
556 | /* Start aging task */ | ||
557 | if (NULL == aging_task) | ||
558 | aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL, | ||
559 | &preference_aging, NULL ); | ||
560 | |||
561 | } | ||
562 | |||
563 | |||
564 | /** | ||
565 | * Get the normalized preference values for a specific peer or | ||
566 | * the default values if | ||
567 | * | ||
568 | * @param id the peer | ||
569 | * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind, | ||
570 | * default preferences if peer does not exist | ||
571 | */ | ||
572 | const double * | ||
573 | GAS_normalization_get_preferences_by_peer (const struct GNUNET_PeerIdentity *id) | ||
574 | { | ||
575 | GNUNET_assert(NULL != preference_peers); | ||
576 | GNUNET_assert(NULL != id); | ||
577 | |||
578 | struct PeerRelative *rp; | ||
579 | if (NULL == (rp = GNUNET_CONTAINER_multipeermap_get (preference_peers, id))) | ||
580 | { | ||
581 | return defvalues.f_rel; | ||
582 | } | ||
583 | return rp->f_rel; | ||
584 | } | ||
585 | |||
586 | |||
587 | /** | ||
588 | * Get the normalized preference values for a specific client and peer | ||
589 | * | ||
590 | * @param client client | ||
591 | * @param peer the peer | ||
592 | * @param pref the preference type | ||
593 | * @return the value | ||
594 | */ | ||
595 | double | ||
596 | GAS_normalization_get_preferences_by_client (const void *client, | ||
597 | const struct GNUNET_PeerIdentity *peer, | ||
598 | enum GNUNET_ATS_PreferenceKind pref) | ||
599 | { | ||
600 | struct PreferenceClient *c_cur; | ||
601 | struct PreferencePeer *p_cur; | ||
602 | |||
603 | /* Find preference client */ | ||
604 | for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) | ||
605 | { | ||
606 | if (client == c_cur->client) | ||
607 | break; | ||
608 | } | ||
609 | if (NULL == c_cur) | ||
610 | return -1.0; | ||
611 | |||
612 | for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) | ||
613 | { | ||
614 | if (0 == memcmp (peer, &p_cur->id, sizeof (struct GNUNET_PeerIdentity))) | ||
615 | break; | ||
616 | } | ||
617 | if (NULL == p_cur) | ||
618 | return DEFAULT_REL_PREFERENCE; /* Not found, return default */ | ||
619 | |||
620 | return p_cur->f_rel[pref]; | ||
621 | } | ||
622 | 59 | ||
623 | 60 | ||
624 | /** | 61 | /** |
625 | * Get the normalized properties values for a specific peer or | 62 | * Get the normalized properties values for a specific peer or |
626 | * the default values if | 63 | * the default values if |
627 | * | 64 | * |
65 | * @param cls ignored | ||
628 | * @param address the address | 66 | * @param address the address |
629 | * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind, | 67 | * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind, |
630 | * default preferences if peer does not exist | 68 | * default preferences if peer does not exist |
631 | */ | 69 | */ |
632 | const double * | 70 | const double * |
633 | GAS_normalization_get_properties (const struct ATS_Address *address) | 71 | GAS_normalization_get_properties (void *cls, |
72 | const struct ATS_Address *address) | ||
634 | { | 73 | { |
635 | static double norm_values[GNUNET_ATS_QualityPropertiesCount]; | 74 | static double norm_values[GNUNET_ATS_QualityPropertiesCount]; |
636 | int i; | 75 | int i; |
@@ -742,7 +181,9 @@ find_min_max_it (void *cls, const struct GNUNET_PeerIdentity *h, void *k) | |||
742 | 181 | ||
743 | 182 | ||
744 | static int | 183 | static int |
745 | normalize_address (void *cls, const struct GNUNET_PeerIdentity *h, void *k) | 184 | normalize_address (void *cls, |
185 | const struct GNUNET_PeerIdentity *h, | ||
186 | void *k) | ||
746 | { | 187 | { |
747 | struct Property *p = cls; | 188 | struct Property *p = cls; |
748 | struct ATS_Address *address = k; | 189 | struct ATS_Address *address = k; |
@@ -769,9 +210,9 @@ normalize_address (void *cls, const struct GNUNET_PeerIdentity *h, void *k) | |||
769 | address->atsin[p->prop_type].avg, p->min, p->max, | 210 | address->atsin[p->prop_type].avg, p->min, p->max, |
770 | address->atsin[p->prop_type].norm); | 211 | address->atsin[p->prop_type].norm); |
771 | 212 | ||
772 | if (NULL != prop_ch_cb) | 213 | GAS_normalized_property_changed (address, |
773 | prop_ch_cb (prop_ch_cb_cls, address, p->atsi_type, | 214 | p->atsi_type, |
774 | address->atsin[p->prop_type].norm); | 215 | address->atsin[p->prop_type].norm); |
775 | 216 | ||
776 | return GNUNET_OK; | 217 | return GNUNET_OK; |
777 | } | 218 | } |
@@ -781,14 +222,14 @@ normalize_address (void *cls, const struct GNUNET_PeerIdentity *h, void *k) | |||
781 | * Normalize avg_value to a range of values between [1.0, 2.0] | 222 | * Normalize avg_value to a range of values between [1.0, 2.0] |
782 | * based on min max values currently known. | 223 | * based on min max values currently known. |
783 | * | 224 | * |
784 | * @param addresses the address hashmap | ||
785 | * @param p the property | 225 | * @param p the property |
786 | * @param address the address | 226 | * @param address the address |
787 | * @param avg_value the value to normalize | 227 | * @param avg_value the value to normalize |
788 | */ | 228 | */ |
789 | static void | 229 | static void |
790 | property_normalize (struct GNUNET_CONTAINER_MultiPeerMap *addresses, | 230 | property_normalize (struct Property *p, |
791 | struct Property *p, struct ATS_Address *address, uint32_t avg_value) | 231 | struct ATS_Address *address, |
232 | uint32_t avg_value) | ||
792 | { | 233 | { |
793 | struct FindMinMaxCtx find_ctx; | 234 | struct FindMinMaxCtx find_ctx; |
794 | int addr_count; | 235 | int addr_count; |
@@ -797,8 +238,9 @@ property_normalize (struct GNUNET_CONTAINER_MultiPeerMap *addresses, | |||
797 | find_ctx.p = p; | 238 | find_ctx.p = p; |
798 | find_ctx.max = 0; | 239 | find_ctx.max = 0; |
799 | find_ctx.min = UINT32_MAX; | 240 | find_ctx.min = UINT32_MAX; |
800 | addr_count = GNUNET_CONTAINER_multipeermap_iterate (addresses, | 241 | addr_count = GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses, |
801 | &find_min_max_it, &find_ctx); | 242 | &find_min_max_it, |
243 | &find_ctx); | ||
802 | if (0 == addr_count) | 244 | if (0 == addr_count) |
803 | { | 245 | { |
804 | GNUNET_break(0); | 246 | GNUNET_break(0); |
@@ -808,19 +250,21 @@ property_normalize (struct GNUNET_CONTAINER_MultiPeerMap *addresses, | |||
808 | limits_changed = GNUNET_NO; | 250 | limits_changed = GNUNET_NO; |
809 | if (find_ctx.max != p->max) | 251 | if (find_ctx.max != p->max) |
810 | { | 252 | { |
811 | LOG(GNUNET_ERROR_TYPE_DEBUG, | 253 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
812 | "Normalizing %s: new maximum %u -> recalculate all values\n", | 254 | "Normalizing %s: new maximum %u -> recalculate all values\n", |
813 | GNUNET_ATS_print_property_type (p->atsi_type), find_ctx.max); | 255 | GNUNET_ATS_print_property_type (p->atsi_type), |
256 | find_ctx.max); | ||
814 | p->max = find_ctx.max; | 257 | p->max = find_ctx.max; |
815 | limits_changed = GNUNET_YES; | 258 | limits_changed = GNUNET_YES; |
816 | } | 259 | } |
817 | 260 | ||
818 | if ((find_ctx.min != p->min) && (find_ctx.min < p->max)) | 261 | if ((find_ctx.min != p->min) && (find_ctx.min < p->max)) |
819 | { | 262 | { |
820 | LOG(GNUNET_ERROR_TYPE_DEBUG, | 263 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
821 | "Normalizing %s: new minimum %u -> recalculate all values\n", | 264 | "Normalizing %s: new minimum %u -> recalculate all values\n", |
822 | GNUNET_ATS_print_property_type (p->atsi_type), find_ctx.min, | 265 | GNUNET_ATS_print_property_type (p->atsi_type), |
823 | find_ctx.max); | 266 | find_ctx.min, |
267 | find_ctx.max); | ||
824 | p->min = find_ctx.min; | 268 | p->min = find_ctx.min; |
825 | limits_changed = GNUNET_YES; | 269 | limits_changed = GNUNET_YES; |
826 | } | 270 | } |
@@ -835,13 +279,13 @@ property_normalize (struct GNUNET_CONTAINER_MultiPeerMap *addresses, | |||
835 | { | 279 | { |
836 | /* normalize just this address */ | 280 | /* normalize just this address */ |
837 | normalize_address (p, &address->peer, address); | 281 | normalize_address (p, &address->peer, address); |
838 | return; | ||
839 | } | 282 | } |
840 | else | 283 | else |
841 | { | 284 | { |
842 | /* limits changed, normalize all addresses */ | 285 | /* limits changed, normalize all addresses */ |
843 | GNUNET_CONTAINER_multipeermap_iterate (addresses, &normalize_address, p); | 286 | GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses, |
844 | return; | 287 | &normalize_address, |
288 | p); | ||
845 | } | 289 | } |
846 | } | 290 | } |
847 | 291 | ||
@@ -849,14 +293,12 @@ property_normalize (struct GNUNET_CONTAINER_MultiPeerMap *addresses, | |||
849 | /** | 293 | /** |
850 | * Update and normalize atsi performance information | 294 | * Update and normalize atsi performance information |
851 | * | 295 | * |
852 | * @param addresses hashmap containing all addresses | ||
853 | * @param address the address to update | 296 | * @param address the address to update |
854 | * @param atsi the array of performance information | 297 | * @param atsi the array of performance information |
855 | * @param atsi_count the number of atsi information in the array | 298 | * @param atsi_count the number of atsi information in the array |
856 | */ | 299 | */ |
857 | void | 300 | void |
858 | GAS_normalization_normalize_property (struct GNUNET_CONTAINER_MultiPeerMap *addresses, | 301 | GAS_normalization_normalize_property (struct ATS_Address *address, |
859 | struct ATS_Address *address, | ||
860 | const struct GNUNET_ATS_Information *atsi, | 302 | const struct GNUNET_ATS_Information *atsi, |
861 | uint32_t atsi_count) | 303 | uint32_t atsi_count) |
862 | { | 304 | { |
@@ -867,9 +309,6 @@ GAS_normalization_normalize_property (struct GNUNET_CONTAINER_MultiPeerMap *addr | |||
867 | uint32_t current_val; | 309 | uint32_t current_val; |
868 | unsigned int existing_properties[] = GNUNET_ATS_QualityProperties; | 310 | unsigned int existing_properties[] = GNUNET_ATS_QualityProperties; |
869 | 311 | ||
870 | GNUNET_assert (NULL != address); | ||
871 | GNUNET_assert (NULL != atsi); | ||
872 | |||
873 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 312 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
874 | "Updating %u elements for peer `%s'\n", | 313 | "Updating %u elements for peer `%s'\n", |
875 | atsi_count, | 314 | atsi_count, |
@@ -901,70 +340,22 @@ GAS_normalization_normalize_property (struct GNUNET_CONTAINER_MultiPeerMap *addr | |||
901 | /* Normalizing */ | 340 | /* Normalizing */ |
902 | /* Check min, max */ | 341 | /* Check min, max */ |
903 | cur_prop = &properties[c2]; | 342 | cur_prop = &properties[c2]; |
904 | property_normalize (addresses, cur_prop, address, current_val); | 343 | property_normalize (cur_prop, address, current_val); |
905 | } | 344 | } |
906 | } | 345 | } |
907 | 346 | ||
908 | 347 | ||
909 | static void | ||
910 | free_client (struct PreferenceClient *pc) | ||
911 | { | ||
912 | struct PreferencePeer *next_p; | ||
913 | struct PreferencePeer *p; | ||
914 | next_p = pc->p_head; | ||
915 | while (NULL != (p = next_p)) | ||
916 | { | ||
917 | next_p = p->next; | ||
918 | GNUNET_CONTAINER_DLL_remove(pc->p_head, pc->p_tail, p); | ||
919 | GNUNET_free(p); | ||
920 | } | ||
921 | GNUNET_free(pc); | ||
922 | } | ||
923 | |||
924 | |||
925 | /** | ||
926 | * A performance client disconnected | ||
927 | * | ||
928 | * @param client the client | ||
929 | */ | ||
930 | void | ||
931 | GAS_normalization_preference_client_disconnect (void *client) | ||
932 | { | ||
933 | struct PreferenceClient *c_cur; | ||
934 | /* Find preference client */ | ||
935 | |||
936 | for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) | ||
937 | { | ||
938 | if (client == c_cur->client) | ||
939 | break; | ||
940 | } | ||
941 | if (NULL == c_cur) | ||
942 | return; | ||
943 | |||
944 | GNUNET_CONTAINER_DLL_remove(pc_head, pc_tail, c_cur); | ||
945 | free_client (c_cur); | ||
946 | } | ||
947 | |||
948 | 348 | ||
949 | /** | 349 | /** |
950 | * Start the normalization component | 350 | * Start the normalization component |
951 | * | ||
952 | * @param pref_ch_cb callback to call on relative preference changing | ||
953 | * @param pref_ch_cb_cls cls for the preference callback | ||
954 | * @param property_ch_cb callback to call on relative property changing | ||
955 | * @param property_ch_cb_cls cls for the property callback | ||
956 | */ | 351 | */ |
957 | void | 352 | void |
958 | GAS_normalization_start (GAS_Normalization_preference_changed_cb pref_ch_cb, | 353 | GAS_normalization_start () |
959 | void *pref_ch_cb_cls, GAS_Normalization_property_changed_cb property_ch_cb, | ||
960 | void *property_ch_cb_cls) | ||
961 | { | 354 | { |
962 | int c1; | 355 | int c1; |
963 | int i; | ||
964 | preference_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
965 | property_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
966 | unsigned int existing_properties[] = GNUNET_ATS_QualityProperties; | 356 | unsigned int existing_properties[] = GNUNET_ATS_QualityProperties; |
967 | 357 | ||
358 | property_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
968 | for (c1 = 0; c1 < GNUNET_ATS_QualityPropertiesCount; c1++) | 359 | for (c1 = 0; c1 < GNUNET_ATS_QualityPropertiesCount; c1++) |
969 | { | 360 | { |
970 | properties[c1].prop_type = c1; | 361 | properties[c1].prop_type = c1; |
@@ -972,42 +363,9 @@ GAS_normalization_start (GAS_Normalization_preference_changed_cb pref_ch_cb, | |||
972 | properties[c1].min = 0; | 363 | properties[c1].min = 0; |
973 | properties[c1].max = 0; | 364 | properties[c1].max = 0; |
974 | } | 365 | } |
975 | |||
976 | pref_changed_cb = pref_ch_cb; | ||
977 | pref_changed_cb_cls = pref_ch_cb_cls; | ||
978 | prop_ch_cb = property_ch_cb; | ||
979 | prop_ch_cb_cls = pref_ch_cb_cls; | ||
980 | |||
981 | pc_head = NULL; | ||
982 | pc_tail = NULL; | ||
983 | |||
984 | for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) | ||
985 | defvalues.f_rel[i] = DEFAULT_REL_PREFERENCE; | ||
986 | aging_task = NULL; | ||
987 | return; | ||
988 | } | 366 | } |
989 | 367 | ||
990 | 368 | ||
991 | /** | ||
992 | * Free a peer | ||
993 | * | ||
994 | * @param cls unused | ||
995 | * @param key the key | ||
996 | * @param value RelativePeer | ||
997 | * @return #GNUNET_OK to continue | ||
998 | */ | ||
999 | static int | ||
1000 | free_peer (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | ||
1001 | { | ||
1002 | struct PeerRelative *rp = value; | ||
1003 | if (GNUNET_YES | ||
1004 | == GNUNET_CONTAINER_multipeermap_remove (preference_peers, key, value)) | ||
1005 | GNUNET_free(rp); | ||
1006 | else | ||
1007 | GNUNET_break(0); | ||
1008 | return GNUNET_OK; | ||
1009 | } | ||
1010 | |||
1011 | 369 | ||
1012 | /** | 370 | /** |
1013 | * Stop the normalization component and free all items | 371 | * Stop the normalization component and free all items |
@@ -1015,27 +373,7 @@ free_peer (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | |||
1015 | void | 373 | void |
1016 | GAS_normalization_stop () | 374 | GAS_normalization_stop () |
1017 | { | 375 | { |
1018 | struct PreferenceClient *pc; | ||
1019 | struct PreferenceClient *next_pc; | ||
1020 | |||
1021 | if (NULL != aging_task) | ||
1022 | { | ||
1023 | GNUNET_SCHEDULER_cancel (aging_task); | ||
1024 | aging_task = NULL; | ||
1025 | } | ||
1026 | |||
1027 | next_pc = pc_head; | ||
1028 | while (NULL != (pc = next_pc)) | ||
1029 | { | ||
1030 | next_pc = pc->next; | ||
1031 | GNUNET_CONTAINER_DLL_remove(pc_head, pc_tail, pc); | ||
1032 | free_client (pc); | ||
1033 | } | ||
1034 | |||
1035 | GNUNET_CONTAINER_multipeermap_iterate (preference_peers, &free_peer, NULL ); | ||
1036 | GNUNET_CONTAINER_multipeermap_destroy (preference_peers); | ||
1037 | GNUNET_CONTAINER_multipeermap_destroy (property_peers); | 376 | GNUNET_CONTAINER_multipeermap_destroy (property_peers); |
1038 | return; | ||
1039 | } | 377 | } |
1040 | 378 | ||
1041 | /* end of gnunet-service-ats_normalization.c */ | 379 | /* end of gnunet-service-ats_normalization.c */ |