gnunet-service-ats_preferences.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2011-2015 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file ats/gnunet-service-ats_preferences.c
  19. * @brief manage preferences expressed by clients
  20. * @author Matthias Wachs
  21. * @author Christian Grothoff
  22. */
  23. #include "platform.h"
  24. #include "gnunet-service-ats.h"
  25. #include "gnunet-service-ats_addresses.h"
  26. #include "gnunet-service-ats_performance.h"
  27. #include "gnunet-service-ats_plugins.h"
  28. #include "gnunet-service-ats_preferences.h"
  29. #include "gnunet-service-ats_reservations.h"
  30. #include "ats.h"
  31. #define LOG(kind,...) GNUNET_log_from (kind, "ats-preferencesx",__VA_ARGS__)
  32. /**
  33. *
  34. */
  35. #define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
  36. /**
  37. *
  38. */
  39. #define PREF_AGING_FACTOR 0.95
  40. /**
  41. *
  42. */
  43. #define PREF_EPSILON 0.01
  44. /**
  45. * Relative preferences for a peer
  46. */
  47. struct PeerRelative
  48. {
  49. /**
  50. * Relative preference values
  51. */
  52. double f_rel[GNUNET_ATS_PreferenceCount];
  53. /**
  54. * Peer identity for which we have these preferences.
  55. */
  56. struct GNUNET_PeerIdentity id;
  57. };
  58. /**
  59. * Default values
  60. */
  61. static struct PeerRelative defvalues;
  62. /**
  63. * Preference client, information we keep track of per client.
  64. */
  65. struct PreferenceClient
  66. {
  67. /**
  68. * Previous in DLL
  69. */
  70. struct PreferenceClient *prev;
  71. /**
  72. * Next in DLL
  73. */
  74. struct PreferenceClient *next;
  75. /**
  76. * Head of peer list
  77. */
  78. struct PreferencePeer *p_head;
  79. /**
  80. * Tail of peer list
  81. */
  82. struct PreferencePeer *p_tail;
  83. /**
  84. * Client handle
  85. */
  86. struct GNUNET_SERVER_Client *client;
  87. /**
  88. * Array of sum of absolute preferences for this client
  89. */
  90. double f_abs_sum[GNUNET_ATS_PreferenceCount];
  91. /**
  92. * Array of sum of relative preferences for this client
  93. */
  94. double f_rel_sum[GNUNET_ATS_PreferenceCount];
  95. };
  96. /**
  97. * Preference information per peer and client.
  98. */
  99. struct PreferencePeer
  100. {
  101. /**
  102. * Next in DLL of preference entries for the same client.
  103. */
  104. struct PreferencePeer *next;
  105. /**
  106. * Previous in DLL of preference entries for the same client.
  107. */
  108. struct PreferencePeer *prev;
  109. /**
  110. * Client that expressed this preferences.
  111. */
  112. struct PreferenceClient *client;
  113. /**
  114. * Peer identity for which the preference was expressed.
  115. */
  116. struct GNUNET_PeerIdentity id;
  117. /**
  118. * Absolute preference values for all preference types
  119. */
  120. double f_abs[GNUNET_ATS_PreferenceCount];
  121. /**
  122. * Relative preference values for all preference types
  123. */
  124. double f_rel[GNUNET_ATS_PreferenceCount];
  125. /**
  126. * Absolute point of time of next aging process
  127. */
  128. struct GNUNET_TIME_Absolute next_aging[GNUNET_ATS_PreferenceCount];
  129. };
  130. /**
  131. * Hashmap to store peer information for preference normalization
  132. */
  133. static struct GNUNET_CONTAINER_MultiPeerMap *preference_peers;
  134. /**
  135. * Clients in DLL: head
  136. */
  137. static struct PreferenceClient *pc_head;
  138. /**
  139. * Clients in DLL: tail
  140. */
  141. static struct PreferenceClient *pc_tail;
  142. /**
  143. * Handle for task we run periodically to age preferences over time.
  144. */
  145. static struct GNUNET_SCHEDULER_Task *aging_task;
  146. /**
  147. * Update a peer
  148. *
  149. * @param id peer id
  150. * @param kind the kind
  151. * @param rp the relative peer struct
  152. * @return the new relative preference
  153. */
  154. static void
  155. update_relative_values_for_peer (const struct GNUNET_PeerIdentity *id,
  156. enum GNUNET_ATS_PreferenceKind kind,
  157. struct PeerRelative *rp)
  158. {
  159. struct PreferenceClient *c_cur;
  160. struct PreferencePeer *p_cur;
  161. double f_rel_total;
  162. double f_rel_sum;
  163. double backup;
  164. unsigned int peer_count;
  165. f_rel_sum = 0.0;
  166. f_rel_total = 0.0;
  167. peer_count = 0;
  168. /* For all clients */
  169. for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next)
  170. {
  171. /* For peer entries with this id */
  172. for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next)
  173. {
  174. f_rel_sum += p_cur->f_rel[kind];
  175. if (0 == memcmp (id, &p_cur->id, sizeof(struct GNUNET_PeerIdentity)))
  176. {
  177. peer_count ++;
  178. f_rel_total += p_cur->f_rel[kind];
  179. }
  180. }
  181. }
  182. LOG (GNUNET_ERROR_TYPE_DEBUG,
  183. "%u clients have a total relative preference for peer `%s' `%s' of %.3f and for %s in total %.3f\n",
  184. peer_count,
  185. GNUNET_i2s (id),
  186. GNUNET_ATS_print_preference_type (kind),
  187. f_rel_total,
  188. GNUNET_ATS_print_preference_type (kind),
  189. f_rel_sum);
  190. /* Find entry for the peer containing relative values in the hashmap */
  191. if (NULL != rp)
  192. {
  193. backup = rp->f_rel[kind];
  194. if (f_rel_sum > 0)
  195. rp->f_rel[kind] = f_rel_total / f_rel_sum;
  196. else
  197. {
  198. /* No client had any preferences for this type and any peer */
  199. rp->f_rel[kind] = DEFAULT_REL_PREFERENCE;
  200. }
  201. if (backup != rp->f_rel[kind])
  202. GAS_normalized_preference_changed (&rp->id, kind,
  203. rp->f_rel[kind]);
  204. }
  205. }
  206. /**
  207. * FIXME
  208. */
  209. static int
  210. update_iterator (void *cls,
  211. const struct GNUNET_PeerIdentity *key,
  212. void *value)
  213. {
  214. enum GNUNET_ATS_PreferenceKind *kind = cls;
  215. struct PeerRelative *pr = value;
  216. update_relative_values_for_peer (key,
  217. *kind,
  218. pr);
  219. return GNUNET_OK;
  220. }
  221. /**
  222. * Recalculate preference for a specific ATS property
  223. *
  224. * @param c the preference client
  225. * @param kind the preference kind
  226. * @return the result
  227. */
  228. static void
  229. recalculate_relative_preferences (struct PreferenceClient *c,
  230. enum GNUNET_ATS_PreferenceKind kind)
  231. {
  232. struct PreferencePeer *p_cur;
  233. /* For this client: sum of absolute preference values for this preference */
  234. c->f_abs_sum[kind] = 0.0;
  235. /* For this client: sum of relative preference values for this preference
  236. *
  237. * Note: this value should also be 1.0, but:
  238. * if no preferences exist due to aging, this value can be 0.0
  239. * and the client can be removed */
  240. c->f_rel_sum[kind] = 0.0;
  241. for (p_cur = c->p_head; NULL != p_cur; p_cur = p_cur->next)
  242. c->f_abs_sum[kind] += p_cur->f_abs[kind];
  243. LOG (GNUNET_ERROR_TYPE_DEBUG,
  244. "Client %p has sum of total preferences for %s of %.3f\n",
  245. c->client, GNUNET_ATS_print_preference_type (kind), c->f_abs_sum[kind]);
  246. /* For all peers: calculate relative preference */
  247. for (p_cur = c->p_head; NULL != p_cur; p_cur = p_cur->next)
  248. {
  249. /* Calculate relative preference for specific kind */
  250. /* Every application has a preference for each peer between
  251. * [0 .. 1] in relative values
  252. * and [0 .. inf] in absolute values */
  253. p_cur->f_rel[kind] = p_cur->f_abs[kind] / c->f_abs_sum[kind];
  254. c->f_rel_sum[kind] += p_cur->f_rel[kind];
  255. LOG (GNUNET_ERROR_TYPE_DEBUG,
  256. "Client %p has relative preference for %s for peer `%s' of %.3f\n",
  257. c->client,
  258. GNUNET_ATS_print_preference_type (kind),
  259. GNUNET_i2s (&p_cur->id),
  260. p_cur->f_rel[kind]);
  261. }
  262. }
  263. /**
  264. * FIXME.
  265. *
  266. */
  267. static void
  268. run_preference_update (struct PreferenceClient *c_cur,
  269. struct PreferencePeer *p_cur,
  270. enum GNUNET_ATS_PreferenceKind kind,
  271. float score_abs)
  272. {
  273. double old_value;
  274. /* Update relative value */
  275. old_value = p_cur->f_rel[kind];
  276. recalculate_relative_preferences (c_cur, kind);
  277. if (p_cur->f_rel[kind] == old_value)
  278. return;
  279. /* Relative preference value changed, recalculate for all peers */
  280. GNUNET_CONTAINER_multipeermap_iterate (preference_peers,
  281. &update_iterator,
  282. &kind);
  283. }
  284. /**
  285. * Reduce absolute preferences since they got old
  286. *
  287. * @param cls the PreferencePeer
  288. * @param tc context
  289. */
  290. static void
  291. preference_aging (void *cls,
  292. const struct GNUNET_SCHEDULER_TaskContext *tc)
  293. {
  294. struct PreferencePeer *p;
  295. struct PreferenceClient *cur_client;
  296. unsigned int i;
  297. unsigned int values_to_update;
  298. double backup;
  299. aging_task = NULL;
  300. values_to_update = 0;
  301. cur_client = NULL;
  302. for (cur_client = pc_head; NULL != cur_client; cur_client = cur_client->next)
  303. {
  304. for (p = cur_client->p_head; NULL != p; p = p->next)
  305. {
  306. /* Aging absolute values: */
  307. for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
  308. {
  309. if (0
  310. == GNUNET_TIME_absolute_get_remaining (p->next_aging[i]).rel_value_us)
  311. {
  312. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
  313. "Aging preference for peer `%s'\n", GNUNET_i2s (&p->id));
  314. backup = p->f_abs[i];
  315. if (p->f_abs[i] > DEFAULT_ABS_PREFERENCE)
  316. p->f_abs[i] *= PREF_AGING_FACTOR;
  317. if (p->f_abs[i] <= DEFAULT_ABS_PREFERENCE + PREF_EPSILON)
  318. p->f_abs[i] = DEFAULT_ABS_PREFERENCE;
  319. if ( (p->f_abs[i] != DEFAULT_ABS_PREFERENCE) &&
  320. (backup != p->f_abs[i]) )
  321. {
  322. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
  323. "Aged preference for peer `%s' from %.3f to %.3f\n",
  324. GNUNET_i2s (&p->id), backup, p->f_abs[i]);
  325. run_preference_update(cur_client, p, i, p->f_abs[i]);
  326. p->next_aging[i] = GNUNET_TIME_absolute_add (
  327. GNUNET_TIME_absolute_get (), PREF_AGING_INTERVAL);
  328. values_to_update++;
  329. }
  330. }
  331. }
  332. }
  333. }
  334. if (values_to_update > 0)
  335. {
  336. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  337. "Rescheduling aging task due to %u elements to age\n",
  338. values_to_update);
  339. aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL,
  340. &preference_aging,
  341. NULL);
  342. }
  343. else
  344. {
  345. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  346. "No values to age left, not rescheduling aging task\n");
  347. }
  348. }
  349. /**
  350. * Update the absolute preference value for a peer
  351. * @param c the client
  352. * @param p the peer
  353. * @param kind the preference kind
  354. * @param score_abs the absolute value
  355. * @return the new relative preference value
  356. */
  357. static void
  358. update_abs_preference (struct PreferenceClient *c,
  359. struct PreferencePeer *p,
  360. enum GNUNET_ATS_PreferenceKind kind,
  361. float score_abs)
  362. {
  363. double score = score_abs;
  364. /* Update preference value according to type */
  365. switch (kind)
  366. {
  367. case GNUNET_ATS_PREFERENCE_BANDWIDTH:
  368. case GNUNET_ATS_PREFERENCE_LATENCY:
  369. p->f_abs[kind] = score;
  370. /* p->f_abs[kind] = (p->f_abs[kind] + score) / 2; */
  371. p->next_aging[kind] = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
  372. PREF_AGING_INTERVAL);
  373. break;
  374. case GNUNET_ATS_PREFERENCE_END:
  375. break;
  376. default:
  377. break;
  378. }
  379. }
  380. /**
  381. * Normalize an updated preference value
  382. *
  383. * @param client the client with this preference
  384. * @param peer the peer to change the preference for
  385. * @param kind the kind to change the preference
  386. * @param score_abs the normalized score
  387. */
  388. static void
  389. normalize_preference (struct GNUNET_SERVER_Client *client,
  390. const struct GNUNET_PeerIdentity *peer,
  391. enum GNUNET_ATS_PreferenceKind kind,
  392. float score_abs)
  393. {
  394. struct PreferenceClient *c_cur;
  395. struct PreferencePeer *p_cur;
  396. struct PeerRelative *r_cur;
  397. double old_value;
  398. int i;
  399. LOG (GNUNET_ERROR_TYPE_DEBUG,
  400. "Client changes preference for peer `%s' for `%s' to %.2f\n",
  401. GNUNET_i2s (peer),
  402. GNUNET_ATS_print_preference_type (kind),
  403. score_abs);
  404. if (kind >= GNUNET_ATS_PreferenceCount)
  405. {
  406. GNUNET_break(0);
  407. return;
  408. }
  409. /* Find preference client */
  410. for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next)
  411. if (client == c_cur->client)
  412. break;
  413. /* Not found: create new preference client */
  414. if (NULL == c_cur)
  415. {
  416. c_cur = GNUNET_new (struct PreferenceClient);
  417. c_cur->client = client;
  418. for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
  419. {
  420. c_cur->f_abs_sum[i] = DEFAULT_ABS_PREFERENCE;
  421. c_cur->f_rel_sum[i] = DEFAULT_REL_PREFERENCE;
  422. }
  423. GNUNET_CONTAINER_DLL_insert (pc_head,
  424. pc_tail,
  425. c_cur);
  426. LOG (GNUNET_ERROR_TYPE_DEBUG,
  427. "Adding new client %p\n",
  428. c_cur);
  429. }
  430. /* Find entry for peer */
  431. for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next)
  432. if (0 == memcmp (&p_cur->id,
  433. peer,
  434. sizeof (p_cur->id)))
  435. break;
  436. /* Not found: create new peer entry */
  437. if (NULL == p_cur)
  438. {
  439. p_cur = GNUNET_new (struct PreferencePeer);
  440. p_cur->client = c_cur;
  441. p_cur->id = *peer;
  442. for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
  443. {
  444. /* Default value per peer absolute preference for a preference: 0 */
  445. p_cur->f_abs[i] = DEFAULT_ABS_PREFERENCE;
  446. /* Default value per peer relative preference for a quality: 1.0 */
  447. p_cur->f_rel[i] = DEFAULT_REL_PREFERENCE;
  448. p_cur->next_aging[i] = GNUNET_TIME_UNIT_FOREVER_ABS;
  449. }
  450. LOG (GNUNET_ERROR_TYPE_DEBUG,
  451. "Adding new peer %p for client %p\n",
  452. p_cur,
  453. c_cur);
  454. GNUNET_CONTAINER_DLL_insert (c_cur->p_head,
  455. c_cur->p_tail,
  456. p_cur);
  457. }
  458. /* Create struct for peer */
  459. if (NULL ==
  460. GNUNET_CONTAINER_multipeermap_get (preference_peers,
  461. peer))
  462. {
  463. r_cur = GNUNET_new (struct PeerRelative);
  464. r_cur->id = *peer;
  465. for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
  466. r_cur->f_rel[i] = DEFAULT_REL_PREFERENCE;
  467. GNUNET_assert(GNUNET_OK ==
  468. GNUNET_CONTAINER_multipeermap_put (preference_peers,
  469. &r_cur->id,
  470. r_cur,
  471. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  472. }
  473. /* Update absolute value */
  474. old_value = p_cur->f_abs[kind];
  475. update_abs_preference (c_cur, p_cur, kind, score_abs);
  476. if (p_cur->f_abs[kind] == old_value)
  477. return;
  478. GAS_plugin_solver_lock ();
  479. run_preference_update (c_cur,
  480. p_cur,
  481. kind,
  482. score_abs);
  483. GAS_plugin_solver_unlock ();
  484. if (NULL == aging_task)
  485. aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL,
  486. &preference_aging,
  487. NULL);
  488. }
  489. /**
  490. * Handle 'preference change' messages from clients.
  491. *
  492. * @param cls unused, NULL
  493. * @param client client that sent the request
  494. * @param message the request message
  495. */
  496. void
  497. GAS_handle_preference_change (void *cls,
  498. struct GNUNET_SERVER_Client *client,
  499. const struct GNUNET_MessageHeader *message)
  500. {
  501. const struct ChangePreferenceMessage *msg;
  502. const struct PreferenceInformation *pi;
  503. uint16_t msize;
  504. uint32_t nump;
  505. uint32_t i;
  506. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  507. "Received PREFERENCE_CHANGE message\n");
  508. msize = ntohs (message->size);
  509. if (msize < sizeof (struct ChangePreferenceMessage))
  510. {
  511. GNUNET_break (0);
  512. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  513. return;
  514. }
  515. msg = (const struct ChangePreferenceMessage *) message;
  516. nump = ntohl (msg->num_preferences);
  517. if (msize !=
  518. sizeof (struct ChangePreferenceMessage) +
  519. nump * sizeof (struct PreferenceInformation))
  520. {
  521. GNUNET_break (0);
  522. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  523. return;
  524. }
  525. GNUNET_STATISTICS_update (GSA_stats,
  526. "# preference change requests processed",
  527. 1, GNUNET_NO);
  528. pi = (const struct PreferenceInformation *) &msg[1];
  529. for (i = 0; i < nump; i++)
  530. normalize_preference (client,
  531. &msg->peer,
  532. (enum GNUNET_ATS_PreferenceKind)
  533. ntohl (pi[i].preference_kind),
  534. pi[i].preference_value);
  535. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  536. }
  537. /**
  538. * Initialize preferences subsystem.
  539. */
  540. void
  541. GAS_preference_init ()
  542. {
  543. int i;
  544. preference_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
  545. for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
  546. defvalues.f_rel[i] = DEFAULT_REL_PREFERENCE;
  547. }
  548. /**
  549. * Free a peer
  550. *
  551. * @param cls unused
  552. * @param key the key
  553. * @param value RelativePeer
  554. * @return #GNUNET_OK to continue
  555. */
  556. static int
  557. free_peer (void *cls,
  558. const struct GNUNET_PeerIdentity *key,
  559. void *value)
  560. {
  561. struct PeerRelative *rp = value;
  562. if (GNUNET_YES ==
  563. GNUNET_CONTAINER_multipeermap_remove (preference_peers,
  564. key,
  565. value))
  566. GNUNET_free (rp);
  567. else
  568. GNUNET_break (0);
  569. return GNUNET_OK;
  570. }
  571. static void
  572. free_client (struct PreferenceClient *pc)
  573. {
  574. struct PreferencePeer *next_p;
  575. struct PreferencePeer *p;
  576. next_p = pc->p_head;
  577. while (NULL != (p = next_p))
  578. {
  579. next_p = p->next;
  580. GNUNET_CONTAINER_DLL_remove(pc->p_head, pc->p_tail, p);
  581. GNUNET_free(p);
  582. }
  583. GNUNET_free(pc);
  584. }
  585. /**
  586. * Shutdown preferences subsystem.
  587. */
  588. void
  589. GAS_preference_done ()
  590. {
  591. struct PreferenceClient *pc;
  592. struct PreferenceClient *next_pc;
  593. if (NULL != aging_task)
  594. {
  595. GNUNET_SCHEDULER_cancel (aging_task);
  596. aging_task = NULL;
  597. }
  598. next_pc = pc_head;
  599. while (NULL != (pc = next_pc))
  600. {
  601. next_pc = pc->next;
  602. GNUNET_CONTAINER_DLL_remove (pc_head,
  603. pc_tail,
  604. pc);
  605. free_client (pc);
  606. }
  607. GNUNET_CONTAINER_multipeermap_iterate (preference_peers,
  608. &free_peer,
  609. NULL);
  610. GNUNET_CONTAINER_multipeermap_destroy (preference_peers);
  611. }
  612. /**
  613. * Get the normalized preference values for a specific peer or
  614. * the default values if
  615. *
  616. * @param cls ignored
  617. * @param id the peer
  618. * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind,
  619. * default preferences if peer does not exist
  620. */
  621. const double *
  622. GAS_normalization_get_preferences_by_peer (void *cls,
  623. const struct GNUNET_PeerIdentity *id)
  624. {
  625. struct PeerRelative *rp;
  626. if (NULL ==
  627. (rp = GNUNET_CONTAINER_multipeermap_get (preference_peers,
  628. id)))
  629. {
  630. return defvalues.f_rel;
  631. }
  632. return rp->f_rel;
  633. }
  634. /**
  635. * A performance client disconnected
  636. *
  637. * @param client the client
  638. */
  639. void
  640. GAS_normalization_preference_client_disconnect (struct GNUNET_SERVER_Client *client)
  641. {
  642. struct PreferenceClient *c_cur;
  643. for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next)
  644. if (client == c_cur->client)
  645. break;
  646. if (NULL == c_cur)
  647. return;
  648. GNUNET_CONTAINER_DLL_remove (pc_head,
  649. pc_tail,
  650. c_cur);
  651. free_client (c_cur);
  652. }
  653. /* end of gnunet-service-ats_preferences.c */