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)
15 answer_t answer = xbt_new(s_answer_t, 1);
16 answer->nodes = xbt_dynar_new(sizeof(node_contact_t), NULL);
18 answer->destination_id = destination_id;
24 * Destroys a node answer object.
26 void answer_free(answer_t answer)
29 for (i = 0; i < answer->size; i++) {
30 node_contact_free(*(void **) xbt_dynar_get_ptr(answer->nodes, i));
32 xbt_dynar_free(&answer->nodes);
37 * @brief Prints a answer_t, for debugging purposes
39 void answer_print(answer_t answer)
42 node_contact_t contact;
43 XBT_INFO("Searching %08x, size %d", answer->destination_id, answer->size);
44 xbt_dynar_foreach(answer->nodes, cpt, contact) {
45 XBT_INFO("Node %08x: %08x is at distance %d", cpt, contact->id,
51 * @brief Merge two answer_t together, only keeping the best nodes
52 * @param destination the destination in which the nodes will be put
53 * @param source the source of the nodes to add
55 unsigned int answer_merge(answer_t destination, answer_t source)
57 node_contact_t contact, contact_copy;
59 unsigned int nb_added = 0;
60 /* TODO: Check if same destination */
61 xbt_dynar_foreach(source->nodes, cpt, contact) {
62 if (!answer_contains(destination, contact->id)) {
63 contact_copy = node_contact_copy(contact);
64 xbt_dynar_push(destination->nodes, &contact_copy);
69 answer_sort(destination);
70 answer_trim(destination);
75 * Helper to sort answer_t objects
77 static int _answer_sort_function(const void *e1, const void *e2)
79 node_contact_t c1 = *(void **) e1;
80 node_contact_t c2 = *(void **) e2;
81 if (c1->distance == c2->distance)
84 if (c1->distance < c2->distance)
91 * Sorts a answer_t, by node distance.
92 * @param answer the answer to sort
93 * @param destination_id the id of the guy we are trying to find
95 void answer_sort(answer_t answer)
97 xbt_dynar_sort(answer->nodes, &_answer_sort_function);
101 * Trims a answer_t, in order for it to have a size of less or equal
103 * @param answer the answer_t to trim
105 void answer_trim(answer_t answer)
107 node_contact_t value;
108 while (answer->size > bucket_size) {
109 xbt_dynar_pop(answer->nodes, &value);
111 node_contact_free(value);
113 xbt_assert(xbt_dynar_length(answer->nodes) == answer->size,
114 "Wrong size for the answer");
118 * Adds the content of a bucket unsigned into a answer object.
119 * @param bucket the bucket we have to had unsigned into
120 * @param answer the answer object we're going to put the data in
121 * @param destination_id the id of the guy we are trying to find.
123 void answer_add_bucket(bucket_t bucket, answer_t answer)
126 unsigned int id, distance;
127 node_contact_t contact;
128 xbt_assert((bucket != NULL), "Provided a NULL bucket");
129 xbt_assert((bucket->nodes != NULL), "Provided a bucket which nodes are NULL");
130 xbt_dynar_foreach(bucket->nodes, cpt, id) {
131 distance = id ^ answer->destination_id;
132 contact = node_contact_new(id, distance);
133 xbt_dynar_push(answer->nodes, &contact);
139 * Returns if the id supplied is in the answer.
140 * @param id : id we're looking for
142 unsigned int answer_contains(answer_t answer, unsigned int id)
144 unsigned int i = 0, size = xbt_dynar_length(answer->nodes);
145 node_contact_t contact;
146 for (i = 0; i < size; i++) {
147 contact = xbt_dynar_get_as(answer->nodes, i, node_contact_t);
148 if (id == contact->id) {
156 * Returns if the destination we are trying to find is found
157 * @param answer the answer
158 * @return if the destination is found.
160 unsigned int answer_destination_found(answer_t answer)
162 if (xbt_dynar_length(answer->nodes) < 1) {
165 node_contact_t contact_tail =
166 xbt_dynar_get_as(answer->nodes, 0, node_contact_t);
167 return contact_tail->distance == 0;