1 /* Copyright (c) 2012. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
8 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(msg_kademlia_node);
11 * Initialize a node answer object.
13 answer_t answer_init(unsigned int destination_id) {
14 answer_t answer = xbt_new(s_answer_t,1);
15 answer->nodes = xbt_dynar_new(sizeof(node_contact_t),NULL);
17 answer->destination_id = destination_id;
22 * Destroys a node answer object.
24 void answer_free(answer_t answer) {
26 for (i = 0; i < answer->size; i++) {
27 node_contact_free(*(void**)xbt_dynar_get_ptr(answer->nodes,i));
29 xbt_dynar_free(&answer->nodes);
33 * @brief Prints a answer_t, for debugging purposes
35 void answer_print(answer_t answer) {
37 node_contact_t contact;
38 XBT_INFO("Searching %d, size %d",answer->destination_id,answer->size);
39 xbt_dynar_foreach(answer->nodes,cpt,contact) {
40 XBT_INFO("Node %d: %d is at distance %d",cpt,contact->id,contact->distance);
44 * @brief Merge two answer_t together, only keeping the best nodes
45 * @param destination the destination in which the nodes will be put
46 * @param source the source of the nodes to add
48 unsigned int answer_merge(answer_t destination, answer_t source) {
49 node_contact_t contact, contact_copy;
51 unsigned int nb_added = 0;
52 /* TODO: Check if same destination */
53 xbt_dynar_foreach(source->nodes,cpt,contact) {
54 if (!answer_contains(destination,contact->id)) {
55 contact_copy = node_contact_copy(contact);
56 xbt_dynar_push(destination->nodes,&contact_copy);
61 answer_sort(destination);
62 answer_trim(destination);
66 * Helper to sort answer_t objects
68 static int _answer_sort_function(const void* e1,const void* e2) {
69 node_contact_t c1 = *(void**)e1;
70 node_contact_t c2 = *(void**)e2;
71 return c1->distance >= c2->distance;
74 * Sorts a answer_t, by node distance.
75 * @param answer the answer to sort
76 * @param destination_id the id of the guy we are trying to find
78 void answer_sort(answer_t answer) {
79 xbt_dynar_sort(answer->nodes,&_answer_sort_function);
82 * Trims a answer_t, in order for it to have a size of less or equal
84 * @param answer the answer_t to trim
86 void answer_trim(answer_t answer) {
88 while (answer->size > bucket_size) {
89 xbt_dynar_pop(answer->nodes,&value);
91 node_contact_free(value);
93 xbt_assert(xbt_dynar_length(answer->nodes) == answer->size,"Wrong size for the answer");
96 * Adds the content of a bucket unsigned into a answer object.
97 * @param bucket the bucket we have to had unsigned into
98 * @param answer the answer object we're going to put the data in
99 * @param destination_id the id of the guy we are trying to find.
101 void answer_add_bucket(bucket_t bucket, answer_t answer) {
103 unsigned int id, distance;
104 node_contact_t contact;
105 xbt_assert((bucket != NULL), "Provided a NULL bucket");
106 xbt_assert((bucket->nodes != NULL), "Provided a bucket which nodes are NULL");
107 xbt_dynar_foreach(bucket->nodes,cpt,id) {
108 distance = id ^ answer->destination_id;
109 contact = node_contact_new(id,distance);
110 xbt_dynar_push(answer->nodes,&contact);
115 * Returns if the id supplied is in the answer.
116 * @param id : id we're looking for
118 unsigned int answer_contains(answer_t answer, unsigned int id) {
119 unsigned int i = 0, size = xbt_dynar_length(answer->nodes);
120 node_contact_t contact;
121 for (i = 0; i < size; i++) {
122 contact = xbt_dynar_get_as(answer->nodes,i,node_contact_t);
123 if (id == contact->id) {
130 * Returns if the destination we are trying to find is found
131 * @param answer the answer
132 * @return if the destination is found.
134 unsigned int answer_destination_found(answer_t answer) {
135 if (xbt_dynar_length(answer->nodes) < 1) {
138 node_contact_t contact_tail = xbt_dynar_get_as(answer->nodes,0,node_contact_t);
139 return contact_tail->distance == 0;