+ // sleep before starting
+ INFO1("Let's sleep >>%f", sleep_time);
+ MSG_process_sleep(sleep_time);
+ INFO0("Hey! Let's join the system.");
+
+ join(&node, known_id);
+ }
+
+ while ((MSG_get_clock( )- init_time) < deadline) {
+
+ unsigned int cursor;
+ comm = NULL;
+ xbt_dynar_foreach(node.comms, cursor, comm) {
+ if (MSG_comm_test(comm)) { // FIXME: try with MSG_comm_testany instead
+ xbt_dynar_cursor_rm(node.comms, &cursor);
+ MSG_comm_destroy(comm);
+ }
+ }
+
+ m_task_t task = NULL;
+ MSG_error_t res = MSG_task_receive_with_timeout(&task, node.mailbox,45); // FIXME >> find the right timeout !!
+
+ if(res == MSG_OK) // else check deadline condition and keep waiting for a task
+ {
+
+ // get data
+ const char* task_name = MSG_task_get_name(task);
+ task_data_t task_data = (task_data_t) MSG_task_get_data(task);
+
+ if (!strcmp(task_name, "Find Successor")) {
+ INFO2("Receiving a 'Find Successor' Request from %s for id %d", task_data->issuer_host_name, task_data->request_id);
+ // is my successor the successor?
+ if (is_in_interval(task_data->request_id, node.id + 1, node.fingers[0].id)) {
+ task_data->answer_id = node.fingers[0].id;
+ MSG_task_set_name(task, "Find Successor Answer");
+ INFO3("Sending back a 'Find Successor' Answer to %s: the successor of %d is %d", task_data->issuer_host_name, task_data->request_id, task_data->answer_id);
+ comm = MSG_task_isend(task, task_data->answer_to);
+ xbt_dynar_push(node.comms, &comm);
+ }
+ else {
+ // otherwise, forward the request to the closest preceding finger in my table
+ int closest = closest_preceding_finger(&node, task_data->request_id);
+ INFO2("Forwarding 'Find Successor' request for id %d to my closest preceding finger %d", task_data->request_id, closest);
+ mailbox = get_mailbox(closest);
+ comm = MSG_task_isend(task, mailbox);
+ xbt_dynar_push(node.comms, &comm);
+ xbt_free(mailbox);
+ }
+ }
+
+ else if (!strcmp(task_name, "Find Predecessor")) {
+ INFO2("Receiving a 'Find Predecessor' Request from %s for id %d", task_data->issuer_host_name, task_data->request_id);
+ // am I the predecessor?
+ if (is_in_interval(task_data->request_id, node.id + 1, node.fingers[0].id)) {
+ task_data->answer_id = node.id;
+ MSG_task_set_name(task, "Find Predecessor Answer");
+ INFO3("Sending back a 'Find Predecessor' Answer to %s: the predecessor of %d is %d", task_data->issuer_host_name, task_data->request_id, task_data->answer_id);
+ comm = MSG_task_isend(task, task_data->answer_to);
+ xbt_dynar_push(node.comms, &comm);
+ }
+ else {
+ // otherwise, forward the request to the closest preceding finger in my table
+ int closest = closest_preceding_finger(&node, task_data->request_id);
+ INFO2("Forwarding 'Find Predecessor' request for id %d to my closest preceding finger %d", task_data->request_id, closest);
+ mailbox = get_mailbox(closest);
+ comm = MSG_task_isend(task, mailbox);
+ xbt_dynar_push(node.comms, &comm);
+ xbt_free(mailbox);
+ }
+ }
+
+ else if (!strcmp(task_name, "Update Finger")) {
+ // someone is telling me that he may be my new finger
+ INFO1("Receiving an 'Update Finger' request from %s", task_data->issuer_host_name);
+ update_finger_table(&node, task_data->request_id, task_data->request_finger);
+ }
+ else if (!strcmp(task_name, "Notify")) {
+ // someone is telling me that he may be my new predecessor
+ INFO1("Receiving a 'Notify' request from %s", task_data->issuer_host_name);
+ notify(&node, task_data->request_id);
+ }
+ else if (!strcmp(task_name, "Predecessor Leaving")) {
+ // my predecessor is about quitting
+ INFO1("Receiving a 'quite notify' from %s", task_data->issuer_host_name);
+ // modify my predecessor
+ node.pred_id = task_data->pred_id;
+ node.pred_mailbox = get_mailbox(node.id);
+ /*TODO :
+ >> notify my new predecessor
+ >> send a notify_predecessors !!
+ */
+
+ }
+ else if (!strcmp(task_name, "Successor Leaving")) {
+ // my successor is about quitting
+ INFO1("Receiving a 'quite notify' from %s", task_data->issuer_host_name);
+ // modify my successor FIXME : this should be implicit ?
+ node.fingers[0].id = task_data->successor_id;
+ node.fingers[0].mailbox = get_mailbox(node.fingers[0].id);
+ /* TODO
+ >> notify my new successor
+ >> update my table & predecessors table */
+ }
+ }
+ }
+ // leave the ring and quit simulation
+ leave(&node);
+ xbt_dynar_free(&node.comms);
+ xbt_free(node.mailbox);
+ xbt_free(node.pred_mailbox);
+ for (i = 0; i < NB_BITS - 1; i++) {
+ xbt_free(node.fingers[i].mailbox);
+ }
+ return 1;
+}
+
+/**
+ * \brief Initializes the current node as the first one of the system.
+ * \param node the current node
+ */
+static void initialize_first_node(node_t node)
+{
+ INFO0("Create a new Chord ring...");
+
+ // I am my own successor and predecessor
+ int i;
+ for (i = 0; i < NB_BITS; i++) {
+ node->fingers[i].id = node->id;
+ node->fingers[i].mailbox = xbt_strdup(node->mailbox);
+ }
+ node->pred_id = node->id;
+ node->pred_mailbox = node->mailbox;
+ print_finger_table(node);
+}
+
+/**
+ * \brief Makes the current node join the system, knowing the id of a node already in the system
+ * \param node the current node
+ * \param known_id id of a node already in the system
+ */
+static void join(node_t node, int known_id)
+{
+ initialize_finger_table(node, known_id); // determine my fingers, asking to known_id
+ remote_notify(node, node->fingers[0].id, node->id); // tell my successor that I'm his new predecessor
+ notify_predecessors(node); // tell others that I may have became their finger
+ remote_move_keys(node, node->fingers[0].id); // take some key-value pairs from my successor
+}
+
+/**
+ * \brief Makes the current node quit the system
+ * \param node the current node
+ */
+static void leave(node_t node)
+{
+ INFO0("Well Guys! I Think it's time for me to quit ;)");
+ quit_notify(node,1); // notify to my successor ( >>> 1 );
+ quit_notify(node,-1); // notify my predecessor ( >>> -1);
+ // TODO ...
+}