X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/8be7ea3f9e71cd563e91b6aba63f5c70f043fbd5..e99158dd85fe789ea5e1a40c29f196fa6c715bcf:/examples/msg/chord/chord.c diff --git a/examples/msg/chord/chord.c b/examples/msg/chord/chord.c index 9744413746..ef8324c8e3 100644 --- a/examples/msg/chord/chord.c +++ b/examples/msg/chord/chord.c @@ -1,27 +1,27 @@ - -/* Copyright (c) 2010-2013. The SimGrid Team. +/* Copyright (c) 2010-2015. 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 -#include "msg/msg.h" +#include "simgrid/msg.h" #include "xbt/log.h" #include "xbt/asserts.h" #include "simgrid/modelchecker.h" #include +#include "src/mc/mc_replay.h" // FIXME: this is an internal header /** @addtogroup MSG_examples * * - chord/chord.c: Classical Chord P2P protocol * This example implements the well known Chord P2P protocol. Its * main advantage is that it constitute a fully working non-trivial - * example. In addition, its implementation is rather efficient, as + * 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"); @@ -38,6 +38,8 @@ static int periodic_fix_fingers_delay = 120; static int periodic_check_predecessor_delay = 120; static int periodic_lookup_delay = 10; +static const double sleep_delay = 4.9999; + extern long int smx_total_comms; /* @@ -75,7 +77,7 @@ typedef enum { TASK_SUCCESSOR_LEAVING, TASK_PREDECESSOR_LEAVING, TASK_PREDECESSOR_ALIVE, - TASK_PREDECESSOR_ALIVE_ANSWER + TASK_PREDECESSOR_ALIVE_ANSWER } e_task_type_t; /* @@ -91,6 +93,7 @@ typedef struct s_task_data { } s_task_data_t, *task_data_t; static int *powers2; +static xbt_dynar_t host_list; // utility functions static void chord_initialize(void); @@ -131,17 +134,35 @@ static void chord_initialize(void) // compute the powers of 2 once for all powers2 = xbt_new(int, nb_bits); int pow = 1; - int i; + unsigned i; for (i = 0; i < nb_bits; i++) { powers2[i] = pow; pow = pow << 1; } nb_keys = pow; XBT_DEBUG("Sets nb_keys to %d", nb_keys); + + msg_host_t host; + host_list = MSG_hosts_as_dynar(); + xbt_dynar_foreach(host_list, i, host) { + char descr[512]; + RngStream stream; + snprintf(descr, sizeof descr, "RngSream<%s>", MSG_host_get_name(host)); + stream = RngStream_CreateStream(descr); + MSG_host_set_property_value(host, "stream", (char*)stream, NULL); + } } static void chord_exit(void) { + msg_host_t host; + unsigned i; + xbt_dynar_foreach(host_list, i, host) { + RngStream stream = (RngStream)MSG_host_get_property_value(host, "stream"); + RngStream_DeleteStream(&stream); + } + xbt_dynar_free(&host_list); + xbt_free(powers2); } @@ -223,9 +244,9 @@ 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 "); + XBT_VERB("Start | Succ"); for (i = 0; i < nb_bits; i++) { - XBT_VERB(" %3d | %3d ", (node->id + powers2[i]) % nb_keys, node->fingers[i].id); + XBT_VERB(" %3d | %3d", (node->id + powers2[i]) % nb_keys, node->fingers[i].id); } XBT_VERB("Predecessor: %d", node->pred_id); } @@ -275,9 +296,9 @@ static void set_predecessor(node_t node, int predecessor_id) */ int node(int argc, char *argv[]) { - + /* Reduce the run size for the MC */ - if(MC_is_active()){ + if(MC_is_active() || MC_record_replay_is_active()){ periodic_stabilize_delay = 8; periodic_fix_fingers_delay = 8; periodic_check_predecessor_delay = 8; @@ -293,17 +314,16 @@ int node(int argc, char *argv[]) double next_check_predecessor_date = init_time + periodic_check_predecessor_delay; double next_lookup_date = init_time + periodic_lookup_delay; - #ifdef HAVE_MC int listen = 0; int no_op = 0; int sub_protocol = 0; - #endif 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]); + node.id = xbt_str_parse_int(argv[1],"Invalid ID: %s"); + node.stream = (RngStream)MSG_host_get_property_value(MSG_host_self(), "stream"); get_mailbox(node.id, node.mailbox); node.next_finger_to_fix = 0; node.fingers = xbt_new0(s_finger_t, nb_bits); @@ -315,14 +335,14 @@ int node(int argc, char *argv[]) } if (argc == 3) { // first ring - deadline = atof(argv[2]); + deadline = xbt_str_parse_double(argv[2],"Invalid deadline: %s"); create(&node); join_success = 1; - } - else { - int known_id = atoi(argv[2]); + + } else { + int known_id = xbt_str_parse_int(argv[2],"Invalid root ID: %s"); //double sleep_time = atof(argv[3]); - deadline = atof(argv[4]); + deadline = xbt_str_parse_double(argv[4],"Invalid deadline: %s"); /* // sleep before starting @@ -351,9 +371,8 @@ int node(int argc, char *argv[]) // no task was received: make some periodic calls -#ifdef HAVE_MC - if(MC_is_active()){ - if(!MC_visited_reduction() && no_op){ + if(MC_is_active() || MC_record_replay_is_active()){ + if(MC_is_active() && !MC_visited_reduction() && no_op){ MC_cut(); } if(listen == 0 && (sub_protocol = MC_random(0, 4)) > 0){ @@ -367,7 +386,7 @@ int node(int argc, char *argv[]) random_lookup(&node); listen = 1; }else{ - MSG_process_sleep(5); + MSG_process_sleep(sleep_delay); if(!MC_visited_reduction()) no_op = 1; } @@ -386,27 +405,9 @@ int node(int argc, char *argv[]) next_lookup_date = MSG_get_clock() + periodic_lookup_delay; }else { // nothing to do: sleep for a while - MSG_process_sleep(5); + MSG_process_sleep(sleep_delay); } } -#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 @@ -428,6 +429,9 @@ int node(int argc, char *argv[]) } 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; } @@ -535,6 +539,8 @@ static void handle_task(node_t node, msg_task_t task) { MSG_task_dsend(task, task_data->answer_to, task_free); break; + default: + THROW_IMPOSSIBLE; } } @@ -588,7 +594,6 @@ static void leave(node_t node) { XBT_DEBUG("Well Guys! I Think it's time for me to quit ;)"); quit_notify(node); - RngStream_DeleteStream(&node->stream); } /** @@ -608,7 +613,12 @@ static void quit_notify(node_t node) 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); - MSG_task_send_with_timeout(task_sent, node->fingers[0].mailbox, timeout); + 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); + } //send the SUCCESSOR_LEAVING to our predecessor get_mailbox(node->pred_id, mailbox); @@ -621,7 +631,12 @@ static void quit_notify(node_t node) 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); - MSG_task_send_with_timeout(task_sent_s, mailbox, timeout); + 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); + } } @@ -698,21 +713,22 @@ static int remote_find_successor(node_t node, int ask_to, int id) XBT_DEBUG("Received a task (%p)", task_received); task_data_t ans_data = MSG_task_get_data(task_received); - // 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. - // 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); + // 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. + // 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); // } - // That explained the bug in a snap, with a very cool example and everything. - // - // This MC_assert is now desactivated as the case is now properly handled in our code and we don't want the - // MC to fail any further under that condition, but this comment is here to as a memorial for this first - // brillant victory of the model-checking in the SimGrid community :) - - if (task_received != task_sent) { + // That explained the bug in a snap, with a very cool example and everything. + // + // This MC_assert is now desactivated as the case is now properly handled in our code and we don't want the + // MC to fail any further under that condition, but this comment is here to as a memorial for this first + // brillant victory of the model-checking in the SimGrid community :) + + if (task_received != task_sent || + ans_data->type != TASK_FIND_SUCCESSOR_ANSWER) { // this is not the expected answer MSG_comm_destroy(node->comm_receive); node->comm_receive = NULL; @@ -792,7 +808,8 @@ static int remote_get_predecessor(node_t node, int ask_to) MC_assert(task_received == task_sent); }*/ - if (task_received != task_sent) { + if (task_received != task_sent || + ans_data->type != TASK_GET_PREDECESSOR_ANSWER) { MSG_comm_destroy(node->comm_receive); node->comm_receive = NULL; handle_task(node, task_received); @@ -943,9 +960,9 @@ static void check_predecessor(node_t node) msg_task_t task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); XBT_DEBUG("Sending a 'Predecessor Alive' request to my predecessor %d", node->pred_id); - + msg_error_t res = MSG_task_send_with_timeout(task_sent, mailbox, timeout); - + if (res != MSG_OK) { XBT_DEBUG("Failed to send the 'Predecessor Alive' request (task %p) to %d", task_sent, node->pred_id); task_free(task_sent); @@ -994,18 +1011,11 @@ static void check_predecessor(node_t node) */ static void random_lookup(node_t node) { - - int id = 1337; - find_successor(node, id); - - /*** Random lookup disabled for tesh examples ***/ - /*if(node->stream == NULL) - node->stream = RngStream_CreateStream(""); int random_index = RngStream_RandInt (node->stream, 0, nb_bits - 1); int random_id = node->fingers[random_index].id; XBT_DEBUG("Making a lookup request for id %d", random_id); int res = find_successor(node, random_id); - XBT_DEBUG("The successor of node %d is %d", random_id, res);*/ + XBT_DEBUG("The successor of node %d is %d", random_id, res); } @@ -1015,25 +1025,24 @@ static void random_lookup(node_t node) int main(int argc, char *argv[]) { MSG_init(&argc, argv); - if (argc < 3) { - printf("Usage: %s [-nb_bits=n] [-timeout=t] platform_file deployment_file\n", argv[0]); - printf("example: %s ../msg_platform.xml chord.xml\n", argv[0]); - exit(1); - } + xbt_assert(argc > 2, + "Usage: %s [-nb_bits=n] [-timeout=t] platform_file deployment_file\n" + "\tExample: %s ../msg_platform.xml chord.xml\n", + argv[0], argv[0]); char **options = &argv[1]; while (!strncmp(options[0], "-", 1)) { int length = strlen("-nb_bits="); if (!strncmp(options[0], "-nb_bits=", length) && strlen(options[0]) > length) { - nb_bits = atoi(options[0] + length); + nb_bits = xbt_str_parse_int(options[0] + length, "Invalid nb_bits parameter: %s"); XBT_DEBUG("Set nb_bits to %d", nb_bits); } else { length = strlen("-timeout="); if (!strncmp(options[0], "-timeout=", length) && strlen(options[0]) > length) { - timeout = atoi(options[0] + length); + timeout = xbt_str_parse_int(options[0] + length, "Invalid timeout parameter: %s"); XBT_DEBUG("Set timeout to %d", timeout); } else { @@ -1046,10 +1055,10 @@ int main(int argc, char *argv[]) const char* platform_file = options[0]; const char* application_file = options[1]; - chord_initialize(); - MSG_create_environment(platform_file); + chord_initialize(); + MSG_function_register("node", node); MSG_launch_application(application_file); @@ -1059,8 +1068,5 @@ int main(int argc, char *argv[]) chord_exit(); - if (res == MSG_OK) - return 0; - else - return 1; + return res != MSG_OK; }