+ 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;
+
+ 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
+ }
+
+ if (!MSG_comm_test(node.comm_receive)) {
+
+ // no task was received: make some periodic calls
+
+ #ifdef HAVE_MC
+ if(MC_is_active()){
+ if(MC_random()){
+ stabilize(&node);
+ }else if(MC_random()){
+ fix_fingers(&node);
+ }else if(MC_random()){
+ check_predecessor(&node);
+ }else if(MC_random()){
+ random_lookup(&node);
+ }else{
+ MSG_process_sleep(5);
+ }
+ }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(5);
+ }
+ }
+ #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(5);
+ }
+ #endif
+
+ } 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) {
+ 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)