X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/0e72b989742d684a4fcc27bb60eaf4b3d2129ac3..417742f1c7f6545db82079acd702fde03547d400:/examples/msg/dht-kademlia/answer.c diff --git a/examples/msg/dht-kademlia/answer.c b/examples/msg/dht-kademlia/answer.c new file mode 100644 index 0000000000..5aa893ff62 --- /dev/null +++ b/examples/msg/dht-kademlia/answer.c @@ -0,0 +1,150 @@ +/* Copyright (c) 2012-2014. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "answer.h" + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(msg_kademlia_node); + +/** Initialize a node answer object. */ +answer_t answer_init(unsigned int destination_id) +{ + answer_t answer = xbt_new(s_answer_t, 1); + answer->nodes = xbt_dynar_new(sizeof(node_contact_t), NULL); + answer->size = 0; + answer->destination_id = destination_id; + + return answer; +} + +/** Destroys a node answer object. */ +void answer_free(answer_t answer) +{ + unsigned int i; + for (i = 0; i < answer->size; i++) { + node_contact_free(*(void **) xbt_dynar_get_ptr(answer->nodes, i)); + } + xbt_dynar_free(&answer->nodes); + xbt_free(answer); +} + +/** @brief Prints a answer_t, for debugging purposes */ +void answer_print(answer_t answer) +{ + unsigned int cpt; + node_contact_t contact; + XBT_INFO("Searching %08x, size %d", answer->destination_id, answer->size); + xbt_dynar_foreach(answer->nodes, cpt, contact) { + XBT_INFO("Node %08x: %08x is at distance %d", cpt, contact->id, contact->distance); + } +} + +/** @brief Merge two answer_t together, only keeping the best nodes + * @param destination the destination in which the nodes will be put + * @param source the source of the nodes to add + */ +unsigned int answer_merge(answer_t destination, answer_t source) +{ + node_contact_t contact, contact_copy; + unsigned int cpt; + unsigned int nb_added = 0; + /* TODO: Check if same destination */ + xbt_dynar_foreach(source->nodes, cpt, contact) { + if (!answer_contains(destination, contact->id)) { + contact_copy = node_contact_copy(contact); + xbt_dynar_push(destination->nodes, &contact_copy); + destination->size++; + nb_added++; + } + } + answer_sort(destination); + answer_trim(destination); + return nb_added; +} + +/** Helper to sort answer_t objects */ +static int _answer_sort_function(const void *e1, const void *e2) +{ + node_contact_t c1 = *(void **) e1; + node_contact_t c2 = *(void **) e2; + if (c1->distance == c2->distance) + return 0; + else + if (c1->distance < c2->distance) + return -1; + else + return 1; +} + +/** @brief Sorts a answer_t, by node distance. + * @param answer the answer to sort + * @param destination_id the id of the guy we are trying to find + */ +void answer_sort(answer_t answer) +{ + xbt_dynar_sort(answer->nodes, &_answer_sort_function); +} + +/** @brief Trims a answer_t, in order for it to have a size of less or equal to "bucket_size" + * @param answer the answer_t to trim + */ +void answer_trim(answer_t answer) +{ + node_contact_t value; + while (answer->size > bucket_size) { + xbt_dynar_pop(answer->nodes, &value); + answer->size--; + node_contact_free(value); + } + xbt_assert(xbt_dynar_length(answer->nodes) == answer->size, "Wrong size for the answer"); +} + +/** @brief Adds the content of a bucket unsigned into a answer object. + * @param bucket the bucket we have to had unsigned into + * @param answer the answer object we're going to put the data in + * @param destination_id the id of the guy we are trying to find. + */ +void answer_add_bucket(bucket_t bucket, answer_t answer) +{ + unsigned int cpt; + unsigned int id, distance; + node_contact_t contact; + xbt_assert((bucket != NULL), "Provided a NULL bucket"); + xbt_assert((bucket->nodes != NULL), "Provided a bucket which nodes are NULL"); + xbt_dynar_foreach(bucket->nodes, cpt, id) { + distance = id ^ answer->destination_id; + contact = node_contact_new(id, distance); + xbt_dynar_push(answer->nodes, &contact); + answer->size++; + } +} + +/** @brief Returns if the id supplied is in the answer. + * @param id : id we're looking for + */ +unsigned int answer_contains(answer_t answer, unsigned int id) +{ + unsigned int i = 0; + node_contact_t contact; + xbt_dynar_foreach(answer->nodes, i, contact){ + if (id == contact->id) { + return 1; + } + } + return 0; +} + +/** @brief Returns if the destination we are trying to find is found + * @param answer the answer + * @return if the destination is found. + */ +unsigned int answer_destination_found(answer_t answer) +{ + if (xbt_dynar_length(answer->nodes) < 1) { + return 0; + } + node_contact_t contact_tail = xbt_dynar_get_as(answer->nodes, 0, node_contact_t); + return contact_tail->distance == 0; +}