-/* Copyright (c) 2010-2015. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2010-2016. 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 <xbt/RngStream.h>
#include "src/mc/mc_replay.h" // FIXME: this is an internal header
-/** @addtogroup MSG_examples
- *
- * - <b>Chord P2P protocol dht-chord/dht-chord.c:</b>. This example implements the well known Chord P2P protocol. Its
- * main advantage is that it constitutes a fully working non-trivial example. In addition, its implementation is
- * rather efficient, as demonstrated in http://hal.inria.fr/inria-00602216/
- */
-
-
XBT_LOG_NEW_DEFAULT_CATEGORY(msg_chord, "Messages specific for this msg example");
#define COMM_SIZE 10
static void set_finger(node_t node, int finger_index, int id);
static void set_predecessor(node_t node, int predecessor_id);
-// process functions
-static int node(int argc, char *argv[]);
+//// process functions
static void handle_task(node_t node, msg_task_t task);
-// Chord core
+//// Chord core
static void create(node_t node);
static int join(node_t node, int known_id);
static void leave(node_t node);
static void remote_notify(node_t node, int notify_to, int predecessor_candidate_id);
static void fix_fingers(node_t node);
static void check_predecessor(node_t node);
-static void random_lookup(node_t);
+static void random_lookup(node_t node);
static void quit_notify(node_t node);
-/* \brief Global initialization of the Chord simulation. */
+/* Global initialization of the Chord simulation. */
static void chord_initialize(void)
{
// compute the powers of 2 once for all
powers2 = xbt_new(int, nb_bits);
- int pow = 1;
+ unsigned int pow = 1;
unsigned i;
for (i = 0; i < nb_bits; i++) {
powers2[i] = pow;
xbt_free(powers2);
}
-/**
- * \brief Turns an id into an equivalent id in [0, nb_keys).
- * \param id an id
- * \return the corresponding normalized id
- */
+/* Turns an id into an equivalent id in [0, nb_keys). */
static int normalize(int id)
{
- // like id % nb_keys, but works with negatives numbers (and faster)
- return id & (nb_keys - 1);
+ return id % nb_keys;
}
-/**
- * \brief Returns whether an id belongs to the interval [start, end].
+/* Returns whether an id belongs to the interval [start, end].
*
- * The parameters are noramlized to make sure they are between 0 and nb_keys - 1).
+ * The parameters are normalized to make sure they are between 0 and nb_keys - 1).
* 1 belongs to [62, 3]
* 1 does not belong to [3, 62]
* 63 belongs to [62, 3]
*/
static int is_in_interval(int id, int start, int end)
{
- id = normalize(id);
- start = normalize(start);
- end = normalize(end);
+ int i = normalize(id);
+ int s = normalize(start);
+ int e = normalize(end);
// make sure end >= start and id >= start
- if (end < start) {
- end += nb_keys;
+ if (e < s) {
+ e += nb_keys;
}
- if (id < start) {
- id += nb_keys;
+ if (i < s) {
+ i += nb_keys;
}
- return id <= end;
+ return i <= e;
}
-/**
- * \brief Gets the mailbox name of a host given its chord id.
+/* Gets the mailbox name of a host given its chord id.
* \param node_id id of a node
* \param mailbox pointer to where the mailbox name should be written
* (there must be enough space)
snprintf(mailbox, MAILBOX_NAME_SIZE - 1, "%d", node_id);
}
-/**
- * \brief Frees the memory used by a task.
- * \param task the MSG task to destroy
- */
+/* Frees the memory used by a task and destroy it */
static void task_free(void* task)
{
// TODO add a parameter data_free_function to MSG_task_create?
}
}
-/**
- * \brief Displays the finger table of a node.
- * \param node a node
- */
+/* Displays the finger table of a node. */
static void print_finger_table(node_t node)
{
if (XBT_LOG_ISENABLED(msg_chord, xbt_log_priority_verbose)) {
- int i;
XBT_VERB("My finger table:");
XBT_VERB("Start | Succ");
- for (i = 0; i < nb_bits; i++) {
+ for (int i = 0; i < nb_bits; i++) {
XBT_VERB(" %3d | %3d", (node->id + powers2[i]) % nb_keys, node->fingers[i].id);
}
XBT_VERB("Predecessor: %d", node->pred_id);
}
}
-/**
- * \brief Sets a finger of the current node.
+/* Sets a finger of the current node.
+ *
* \param node the current node
* \param finger_index index of the finger to set (0 to nb_bits - 1)
* \param id the id to set for this finger
}
}
-/**
- * \brief Sets the predecessor of the current node.
+/* Sets the predecessor of the current node.
+ *
* \param node the current node
* \param id the id to predecessor, or -1 to unset the predecessor
*/
}
}
-/**
- * \brief Node Function
+/* Node main Function
+ *
* Arguments:
* - my id
* - the id of a guy I know in the system (except for the first node)
* - the time to sleep before I join (except for the first node)
*/
-int node(int argc, char *argv[])
+static int node(int argc, char *argv[])
{
-
/* Reduce the run size for the MC */
if(MC_is_active() || MC_record_replay_is_active()){
periodic_stabilize_delay = 8;
} else {
int known_id = xbt_str_parse_int(argv[2],"Invalid root ID: %s");
- //double sleep_time = atof(argv[3]);
deadline = xbt_str_parse_double(argv[4],"Invalid deadline: %s");
- /*
- // sleep before starting
- XBT_DEBUG("Let's sleep during %f", sleep_time);
- MSG_process_sleep(sleep_time);
- */
XBT_DEBUG("Hey! Let's join the system.");
join_success = join(&node, known_id);
return 0;
}
-/**
- * \brief This function is called when the current node receives a task.
+/* This function is called when the current node receives a task.
+ *
* \param node the current node
- * \param task the task to handle (don't touch it then:
- * it will be destroyed, reused or forwarded)
+ * \param task the task to handle (don't touch it afterward: it will be destroyed, reused or forwarded)
*/
static void handle_task(node_t node, msg_task_t task) {
task_data->type = TASK_FIND_SUCCESSOR_ANSWER;
task_data->answer_id = node->fingers[0].id;
XBT_DEBUG("Sending back a 'Find Successor Answer' to %s (mailbox %s): the successor of %d is %d",
- task_data->issuer_host_name,
- task_data->answer_to,
- task_data->request_id, task_data->answer_id);
+ task_data->issuer_host_name, task_data->answer_to, task_data->request_id, task_data->answer_id);
MSG_task_dsend(task, task_data->answer_to, task_free);
- }
- else {
+ } else {
// otherwise, forward the request to the closest preceding finger in my table
int closest = closest_preceding_node(node, task_data->request_id);
XBT_DEBUG("Forwarding the 'Find Successor' request for id %d to my closest preceding finger %d",
task_data->type = TASK_GET_PREDECESSOR_ANSWER;
task_data->answer_id = node->pred_id;
XBT_DEBUG("Sending back a 'Get Predecessor Answer' to %s via mailbox '%s': my predecessor is %d",
- task_data->issuer_host_name,
- task_data->answer_to, task_data->answer_id);
+ task_data->issuer_host_name, task_data->answer_to, task_data->answer_id);
MSG_task_dsend(task, task_data->answer_to, task_free);
break;
XBT_DEBUG("Receiving a 'Predecessor Alive' request from %s", task_data->issuer_host_name);
task_data->type = TASK_PREDECESSOR_ALIVE_ANSWER;
XBT_DEBUG("Sending back a 'Predecessor Alive Answer' to %s (mailbox %s)",
- task_data->issuer_host_name,
- task_data->answer_to);
+ task_data->issuer_host_name, task_data->answer_to);
MSG_task_dsend(task, task_data->answer_to, task_free);
break;
}
}
-/**
- * \brief Initializes the current node as the first one of the system.
- * \param node the current node
- */
+/* Initializes the current node as the first one of the system */
static void create(node_t node)
{
XBT_DEBUG("Create a new Chord ring...");
print_finger_table(node);
}
-/**
- * \brief Makes the current node join the ring, knowing the id of a node
- * already in the ring
+/* Makes the current node join the ring, knowing the id of a node already in the ring
+ *
* \param node the current node
* \param known_id id of a node already in the ring
* \return 1 if the join operation succeeded, 0 otherwise
XBT_INFO("Joining the ring with id %d, knowing node %d", node->id, known_id);
set_predecessor(node, -1); // no predecessor (yet)
- /*
- int i;
- for (i = 0; i < nb_bits; i++) {
- set_finger(node, i, known_id);
- }
- */
-
int successor_id = remote_find_successor(node, known_id, node->id);
if (successor_id == -1) {
XBT_INFO("Cannot join the ring.");
return successor_id != -1;
}
-/**
- * \brief Makes the current node quit the system
- * \param node the current node
- */
+/* Makes the current node quit the system */
static void leave(node_t node)
{
XBT_DEBUG("Well Guys! I Think it's time for me to quit ;)");
quit_notify(node);
}
-/**
- * \brief Notifies the successor and the predecessor of the current node
- * of the departure
- * \param node the current node
- */
+/* Notifies the successor and the predecessor of the current node before leaving */
static void quit_notify(node_t node)
{
char mailbox[MAILBOX_NAME_SIZE];
msg_task_t task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data);
XBT_DEBUG("Sending a 'PREDECESSOR_LEAVING' to my successor %d",node->fingers[0].id);
- if (MSG_task_send_with_timeout(task_sent, node->fingers[0].mailbox, timeout)==
- MSG_TIMEOUT) {
- XBT_DEBUG("Timeout expired when sending a 'PREDECESSOR_LEAVING' to my successor %d",
- node->fingers[0].id);
+ if (MSG_task_send_with_timeout(task_sent, node->fingers[0].mailbox, timeout)== MSG_TIMEOUT) {
+ XBT_DEBUG("Timeout expired when sending a 'PREDECESSOR_LEAVING' to my successor %d", node->fingers[0].id);
task_free(task_sent);
}
msg_task_t task_sent_s = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data_s);
XBT_DEBUG("Sending a 'SUCCESSOR_LEAVING' to my predecessor %d",node->pred_id);
- if (MSG_task_send_with_timeout(task_sent_s, mailbox, timeout)==
- MSG_TIMEOUT) {
- XBT_DEBUG("Timeout expired when sending a 'SUCCESSOR_LEAVING' to my predecessor %d",
- node->pred_id);
+ if (MSG_task_send_with_timeout(task_sent_s, mailbox, timeout)== MSG_TIMEOUT) {
+ XBT_DEBUG("Timeout expired when sending a 'SUCCESSOR_LEAVING' to my predecessor %d", node->pred_id);
task_free(task_sent_s);
}
-
}
-/**
- * \brief Makes the current node find the successor node of an id.
+/* Makes the current node find the successor node of an id.
+ *
* \param node the current node
* \param id the id to find
* \return the id of the successor node, or -1 if the request failed
return remote_find_successor(node, closest, id);
}
-/**
- * \brief Asks another node the successor node of an id.
+/* \brief Asks another node the successor node of an id.
+ *
* \param node the current node
* \param ask_to the node to ask to
* \param id the id to find
msg_error_t res = MSG_task_send_with_timeout(task_sent, mailbox, timeout);
if (res != MSG_OK) {
- XBT_DEBUG("Failed to send the 'Find Successor' request (task %p) to %d for id %d",
- task_sent, ask_to, id);
+ XBT_DEBUG("Failed to send the 'Find Successor' request (task %p) to %d for id %d", task_sent, ask_to, id);
task_free(task_sent);
}
else {
// Once upon a time, our code assumed that here, task_received != task_sent all the time
//
// This assumption is wrong (as messages from differing round can interleave), leading to a bug in our code.
- // We failed to find this bug directly, as it only occured on large platforms, leading to hardly usable traces.
+ // We failed to find this bug directly, as it only occurred on large platforms, leading to hardly usable traces.
// Instead, we used the model-checker to track down the issue by adding the following test here in the code:
// if (MC_is_active()) {
// MC_assert(task_received == task_sent);
return successor;
}
-/**
- * \brief Asks another node its predecessor.
+/* Asks its predecessor to a remote node
+ *
* \param node the current node
* \param ask_to the node to ask to
* \return the id of its predecessor node, or -1 if the request failed
return predecessor_id;
}
-/**
- * \brief Returns the closest preceding finger of an id
- * with respect to the finger table of the current node.
+/* Returns the closest preceding finger of an id with respect to the finger table of the current node.
+ *
* \param node the current node
* \param id the id to find
* \return the closest preceding finger of that id
*/
-int closest_preceding_node(node_t node, int id)
+static int closest_preceding_node(node_t node, int id)
{
int i;
for (i = nb_bits - 1; i >= 0; i--) {
return node->id;
}
-/**
- * \brief This function is called periodically. It checks the immediate
- * successor of the current node.
- * \param node the current node
- */
+/* This function is called periodically. It checks the immediate successor of the current node. */
static void stabilize(node_t node)
{
XBT_DEBUG("Stabilizing node");
}
}
-/**
- * \brief Notifies the current node that its predecessor may have changed.
- * \param node the current node
- * \param candidate_id the possible new predecessor
- */
+/* Notifies the current node that its predecessor may have changed. */
static void notify(node_t node, int predecessor_candidate_id) {
if (node->pred_id == -1
}
}
-/**
- * \brief Notifies a remote node that its predecessor may have changed.
- * \param node the current node
- * \param notify_id id of the node to notify
- * \param candidate_id the possible new predecessor
- */
+/* Notifies a remote node that its predecessor may have changed. */
static void remote_notify(node_t node, int notify_id, int predecessor_candidate_id) {
task_data_t req_data = xbt_new0(s_task_data_t, 1);
MSG_task_dsend(task, mailbox, task_free);
}
-/**
- * \brief This function is called periodically.
- * It refreshes the finger table of the current node.
- * \param node the current node
- */
+/* refreshes the finger table of the current node (called periodically) */
static void fix_fingers(node_t node) {
XBT_DEBUG("Fixing fingers");
}
}
-/**
- * \brief This function is called periodically.
- * It checks whether the predecessor has failed
- * \param node the current node
- */
+/* checks whether the predecessor has failed (called periodically) */
static void check_predecessor(node_t node)
{
XBT_DEBUG("Checking whether my predecessor is alive");
}
}
-/**
- * \brief Performs a find successor request to a random id.
- * \param node the current node
- */
+/* Performs a find successor request to a random id */
static void random_lookup(node_t node)
{
int random_index = RngStream_RandInt (node->stream, 0, nb_bits - 1);