+ double init_time = MSG_get_clock();
+ msg_task_t task_received = NULL;
+ int i;
+ int join_success = 0;
+ double deadline;
+ double next_stabilize_date = init_time + periodic_stabilize_delay;
+ double next_fix_fingers_date = init_time + periodic_fix_fingers_delay;
+ double next_check_predecessor_date = init_time + periodic_check_predecessor_delay;
+ double next_lookup_date = init_time + periodic_lookup_delay;
+
+ int listen = 0;
+ int no_op = 0;
+ int sub_protocol = 0;
+
+ xbt_assert(argc == 3 || argc == 5, "Wrong number of arguments for this node");
+
+ // initialize my node
+ s_node_t node = {0};
+ node.id = atoi(argv[1]);
+ get_mailbox(node.id, node.mailbox);
+ node.next_finger_to_fix = 0;
+ node.fingers = xbt_new0(s_finger_t, nb_bits);
+ node.last_change_date = init_time;
+
+ for (i = 0; i < nb_bits; i++) {
+ node.fingers[i].id = -1;
+ set_finger(&node, i, node.id);
+ }
+
+ if (argc == 3) { // first ring
+ deadline = atof(argv[2]);
+ create(&node);
+ join_success = 1;
+ }
+ else {
+ int known_id = atoi(argv[2]);
+ //double sleep_time = atof(argv[3]);
+ deadline = atof(argv[4]);
+
+ /*
+ // 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);
+ }
+
+ if (join_success) {
+ while (MSG_get_clock() < init_time + deadline
+// && MSG_get_clock() < node.last_change_date + 1000
+ && MSG_get_clock() < max_simulation_time) {
+
+ if (node.comm_receive == NULL) {
+ task_received = NULL;
+ node.comm_receive = MSG_task_irecv(&task_received, node.mailbox);
+ // FIXME: do not make MSG_task_irecv() calls from several functions
+ }
+
+ //XBT_INFO("Node %d is ring member : %d", node.id, is_ring_member(known_id, node.id) != -1);
+
+ if (!MSG_comm_test(node.comm_receive)) {
+
+ // no task was received: make some periodic calls
+
+ if(MC_is_active()){
+ if(!MC_visited_reduction() && no_op){
+ MC_cut();
+ }
+ if(listen == 0 && (sub_protocol = MC_random(0, 4)) > 0){
+ if(sub_protocol == 1)
+ stabilize(&node);
+ else if(sub_protocol == 2)
+ fix_fingers(&node);
+ else if(sub_protocol == 3)
+ check_predecessor(&node);
+ else
+ random_lookup(&node);
+ listen = 1;
+ }else{
+ MSG_process_sleep(sleep_delay);
+ if(!MC_visited_reduction())
+ no_op = 1;
+ }
+ }else{
+ if (MSG_get_clock() >= next_stabilize_date) {
+ stabilize(&node);
+ next_stabilize_date = MSG_get_clock() + periodic_stabilize_delay;
+ }else if (MSG_get_clock() >= next_fix_fingers_date) {
+ fix_fingers(&node);
+ next_fix_fingers_date = MSG_get_clock() + periodic_fix_fingers_delay;
+ }else if (MSG_get_clock() >= next_check_predecessor_date) {
+ check_predecessor(&node);
+ next_check_predecessor_date = MSG_get_clock() + periodic_check_predecessor_delay;
+ }else if (MSG_get_clock() >= next_lookup_date) {
+ random_lookup(&node);
+ next_lookup_date = MSG_get_clock() + periodic_lookup_delay;
+ }else {
+ // nothing to do: sleep for a while
+ MSG_process_sleep(sleep_delay);
+ }
+ }
+
+ } else {
+ // a transfer has occurred
+
+ msg_error_t status = MSG_comm_get_status(node.comm_receive);
+
+ if (status != MSG_OK) {
+ XBT_DEBUG("Failed to receive a task. Nevermind.");
+ MSG_comm_destroy(node.comm_receive);
+ node.comm_receive = NULL;
+ }
+ else {
+ // the task was successfully received
+ MSG_comm_destroy(node.comm_receive);
+ node.comm_receive = NULL;
+ handle_task(&node, task_received);
+ }
+ }
+ }
+
+ if (node.comm_receive) {
+ /* handle last task if any */
+ if (MSG_comm_wait(node.comm_receive, 0) == MSG_OK)
+ task_free(task_received);
+ MSG_comm_destroy(node.comm_receive);
+ node.comm_receive = NULL;
+ }
+
+ // leave the ring
+ leave(&node);
+ }
+
+ // stop the simulation
+ xbt_free(node.fingers);
+ return 0;
+}
+
+/**
+ * \brief 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)