Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Handle transfer failures in MSG_test, MSG_testany and MSG_waitany
authorthiery <thiery@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 16 Dec 2010 13:29:29 +0000 (13:29 +0000)
committerthiery <thiery@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 16 Dec 2010 13:29:29 +0000 (13:29 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@9270 48e7efb5-ca39-0410-a469-dd3cf9ba447f

examples/msg/chord/chord.c
examples/msg/chord/chord.xml
include/msg/msg.h
src/msg/gos.c
src/replay/replay [new file with mode: 0755]
src/simix/smx_network.c

index 7b9bf0e..f148ca5 100644 (file)
@@ -14,6 +14,8 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(msg_chord,
 
 #define NB_BITS 6
 #define NB_KEYS 64
+#define COMM_SIZE 10
+#define COMP_SIZE 0
 
 /**
  * Finger element.
@@ -303,47 +305,54 @@ int node(int argc, char *argv[])
       }
     }
     else {
-      // a task was received
+      // a transfer has occured
 
+      MSG_error_t status = MSG_comm_get_status(comm_receive);
       MSG_comm_destroy(comm_receive);
       comm_receive = NULL;
-      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_send = MSG_task_isend(task, task_data->answer_to);
-         xbt_dynar_push(node.comms, &comm_send);
-       }
-       else {
-         // otherwise, forward the request to the closest preceding finger in my table
-         int closest = closest_preceding_node(&node, task_data->request_id);
-         INFO2("Forwarding the 'Find Successor' request for id %d to my closest preceding finger %d",
-               task_data->request_id, closest);
-         mailbox = get_mailbox(closest);
-         comm_send = MSG_task_isend(task, mailbox);
-         xbt_dynar_push(node.comms, &comm_send);
-         xbt_free(mailbox);
-       }
+      if (status != MSG_OK) {
+        INFO0("Failed to receive a task. Nevermind.");
       }
+      else {
+        // the task was successfully received
+        const char* task_name = MSG_task_get_name(task);
+        task_data_t task_data = (task_data_t) MSG_task_get_data(task);
 
-      else if (!strcmp(task_name, "Get Predecessor")) {
-       INFO1("Receiving a 'Get Predecessor' Request from %s", task_data->issuer_host_name);
-       task_data->answer_id = node.pred_id;
-       MSG_task_set_name(task, "Get Predecessor Answer");
-       INFO2("Sending back a 'Get Predecessor Answer' to %s: my predecessor is %d",
-             task_data->issuer_host_name, task_data->answer_id);
-       comm_send = MSG_task_isend(task, task_data->answer_to);
-       xbt_dynar_push(node.comms, &comm_send);
-      }
-      /*
+        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_send = MSG_task_isend(task, task_data->answer_to);
+            xbt_dynar_push(node.comms, &comm_send);
+          }
+          else {
+            // otherwise, forward the request to the closest preceding finger in my table
+            int closest = closest_preceding_node(&node, task_data->request_id);
+            INFO2("Forwarding the 'Find Successor' request for id %d to my closest preceding finger %d",
+                task_data->request_id, closest);
+            mailbox = get_mailbox(closest);
+            comm_send = MSG_task_isend(task, mailbox);
+            xbt_dynar_push(node.comms, &comm_send);
+            xbt_free(mailbox);
+          }
+        }
+
+        else if (!strcmp(task_name, "Get Predecessor")) {
+          INFO1("Receiving a 'Get Predecessor' request from %s", task_data->issuer_host_name);
+          task_data->answer_id = node.pred_id;
+          MSG_task_set_name(task, "Get Predecessor Answer");
+          INFO2("Sending back a 'Get Predecessor Answer' to %s: my predecessor is %d",
+              task_data->issuer_host_name, task_data->answer_id);
+          comm_send = MSG_task_isend(task, task_data->answer_to);
+          xbt_dynar_push(node.comms, &comm_send);
+        }
+        /*
       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?
@@ -364,9 +373,9 @@ int node(int argc, char *argv[])
          xbt_free(mailbox);
        }
       }
-      */
+         */
 
-      /*
+        /*
       else if (!strcmp(task_name, "Notify Node Joined")) {
        // someone may be my new neighboor
        INFO1("Receiving a 'Notify Node Joine' request from %s", task_data->issuer_host_name);
@@ -377,30 +386,31 @@ int node(int argc, char *argv[])
        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 to quit
-       INFO1("Receiving a 'Predecessor Leaving' message from %s", task_data->issuer_host_name);
-       // modify my predecessor
-       set_predecessor(&node, task_data->pred_id);
-       /*TODO :
+         */
+        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 to quit
+          INFO1("Receiving a 'Predecessor Leaving' message from %s", task_data->issuer_host_name);
+          // modify my predecessor
+          set_predecessor(&node, task_data->pred_id);
+          /*TODO :
           >> notify my new predecessor
           >> send a notify_predecessors !!
-        */
-      }
-      else if (!strcmp(task_name, "Successor Leaving")) {
-       // my successor is about to quit
-       INFO1("Receiving a 'Successor Leaving' message from %s", task_data->issuer_host_name);
-       // modify my successor FIXME : this should be implicit ?
-       set_finger(&node, 0, task_data->successor_id);
-       /* TODO
+           */
+        }
+        else if (!strcmp(task_name, "Successor Leaving")) {
+          // my successor is about to quit
+          INFO1("Receiving a 'Successor Leaving' message from %s", task_data->issuer_host_name);
+          // modify my successor FIXME : this should be implicit ?
+          set_finger(&node, 0, task_data->successor_id);
+          /* TODO
           >> notify my new successor
           >> update my table & predecessors table */
+        }
       }
     }
   }
@@ -441,7 +451,9 @@ static void join(node_t node, int known_id)
   int successor_id;
   do {
     successor_id = remote_find_successor(node, known_id, node->id);
-    INFO0("My 'Find Successor' request has failed, let's try again");
+    if (successor_id == -1) {
+      INFO0("I really want to join the ring. Let's try again.");
+    }
   } while (successor_id == -1);
 
   set_finger(node, 0, successor_id);
@@ -486,7 +498,7 @@ static void remote_notify_node_joined(node_t node, int notify_id)
 
   // send a "Notify" request to notify_id
   INFO2("Sending a 'Notify' request to %d because I have joined the network with id %d", notify_id, node->id);
-  m_task_t task = MSG_task_create("Notify", 1000, 5000, req_data);
+  m_task_t task = MSG_task_create("Notify", COMP_SIZE, COMM_SIZE, req_data);
   char* mailbox = get_mailbox(notify_id);
   msg_comm_t comm = MSG_task_isend(task, mailbox);
   xbt_dynar_push(node->comms, &comm);
@@ -568,7 +580,7 @@ static void quit_notify(node_t node, int to)
     task_name = "Predecessor Leaving";
 
   }
-  m_task_t task = MSG_task_create(task_name, 1000, 5000, req_data);
+  m_task_t task = MSG_task_create(task_name, COMP_SIZE, COMM_SIZE, req_data);
   //char* mailbox = get_mailbox(to_mailbox);
   msg_comm_t comm = MSG_task_isend(task, to_mailbox);
   xbt_dynar_push(node->comms, &comm);
@@ -681,7 +693,7 @@ static void remote_update_finger_table(node_t node, int ask_to_id, int candidate
 
   // send a "Update Finger" request to ask_to_id
   INFO3("Sending an 'Update Finger' request to %d: his finger #%d may be %d now", ask_to_id, finger_index, candidate_id);
-  m_task_t task = MSG_task_create("Update Finger", 1000, 5000, req_data);
+  m_task_t task = MSG_task_create("Update Finger", COMP_SIZE, COMM_SIZE, req_data);
   char* mailbox = get_mailbox(ask_to_id);
   msg_comm_t comm = MSG_task_isend(task, mailbox);
   xbt_dynar_push(node->comms, &comm);
@@ -725,13 +737,13 @@ static int remote_find_successor(node_t node, int ask_to, int id)
 
   // send a "Find Successor" request to ask_to_id
   INFO2("Sending a 'Find Successor' request to %d for key %d", ask_to, id);
-  m_task_t task = MSG_task_create("Find Successor", 1000, 5000, &req_data);
-  MSG_error_t res = MSG_task_send_with_timeout(task, get_mailbox(ask_to), 20);
+  m_task_t task = MSG_task_create("Find Successor", COMP_SIZE, COMM_SIZE, &req_data);
+  MSG_error_t res = MSG_task_send_with_timeout(task, get_mailbox(ask_to), 200);
   if (res == MSG_OK) {
 
     // receive the answer
     task = NULL;
-    res = MSG_task_receive_with_timeout(&task, req_data.answer_to, 20);
+    res = MSG_task_receive_with_timeout(&task, req_data.answer_to, 200);
 
     if (res == MSG_OK) {
 
@@ -742,6 +754,9 @@ static int remote_find_successor(node_t node, int ask_to, int id)
     }
   }
 
+  if (res != MSG_OK) {
+    INFO2("My 'Find Successor' request to node %d for key %d has failed", ask_to, id);
+  }
   xbt_free(mailbox);
   return successor;
 }
@@ -763,7 +778,7 @@ static int remote_get_predecessor(node_t node, int ask_to)
 
   // send a "Get Predecessor" request to ask_to_id
   INFO1("Sending a 'Get Predecessor' request to %d", ask_to);
-  m_task_t task = MSG_task_create("Get Predecessor", 1000, 5000, &req_data);
+  m_task_t task = MSG_task_create("Get Predecessor", COMP_SIZE, COMM_SIZE, &req_data);
   MSG_error_t res = MSG_task_send_with_timeout(task, get_mailbox(ask_to), 20);
 
   if (res == MSG_OK) {
@@ -781,6 +796,10 @@ static int remote_get_predecessor(node_t node, int ask_to)
     }
   }
 
+  if (res != MSG_OK) {
+    INFO1("My 'Get Predecessor' request to node %d has failed", ask_to);
+  }
+
   xbt_free(mailbox);
   return predecessor_id;
 }
@@ -825,7 +844,7 @@ static int remote_find_predecessor(node_t node, int ask_to, int id)
 
   // send a "Find Predecessor" request to ask_to
   INFO2("Sending a 'Find Predecessor' request to %d for key %d", ask_to, id);
-  m_task_t task = MSG_task_create("Find Predecessor", 1000, 5000, &req_data);
+  m_task_t task = MSG_task_create("Find Predecessor", COMP_SIZE, COMM_SIZE, &req_data);
   MSG_task_send(task, get_mailbox(ask_to));
 
   // receive the answer
@@ -920,7 +939,7 @@ static void remote_notify(node_t node, int notify_id, int predecessor_candidate_
 
   // send a "Notify" request to notify_id
   INFO1("Sending a 'Notify' request to %d", notify_id);
-  m_task_t task = MSG_task_create("Notify", 1000, 5000, req_data);
+  m_task_t task = MSG_task_create("Notify", COMP_SIZE, COMM_SIZE, req_data);
   char* mailbox = get_mailbox(notify_id);
   msg_comm_t comm = MSG_task_isend(task, mailbox);
   xbt_dynar_push(node->comms, &comm);
index 4779089..e235ac7 100644 (file)
@@ -6,54 +6,54 @@
     <argument value="48"/>        <!-- my id -->
     <argument value="1"/>         <!-- known id -->
     <argument value="400"/>        <!-- time to sleep before it starts-->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
   <process host="McGee" function="node">
     <argument value="42"/>        <!-- my id -->
     <argument value="1"/>         <!-- known id -->
     <argument value="300"/>        <!-- time to sleep before it starts-->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
   <process host="iRMX" function="node">
     <argument value="38"/>        <!-- my id -->
     <argument value="1"/>         <!-- known id -->
     <argument value="200"/>         <!-- time to sleep before it starts-->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
   <process host="Geoff" function="node">
     <argument value="32"/>        <!-- my id -->
     <argument value="1"/>         <!-- known id -->
     <argument value="100"/>         <!-- time to sleep before it starts-->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
   <process host="TeX" function="node">
     <argument value="21"/>        <!-- my id -->
     <argument value="1"/>         <!-- known id -->
     <argument value="40"/>        <!-- time to sleep before it starts-->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
   <process host="Jean_Yves" function="node">
     <argument value="14"/>        <!-- my id -->
     <argument value="1"/>         <!-- known id -->
     <argument value="16"/>        <!-- time to sleep before it starts-->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
   <process host="Boivin" function="node">
     <argument value="8"/>         <!-- my id -->
     <argument value="1"/>         <!-- known id -->
     <argument value="1"/>         <!-- time to sleep before it starts-->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
   <process host="Jacquelin" function="node">
     <argument value="1"/>         <!-- my id -->
-    <argument value ="500"/>           <!-- deadline -->
+    <argument value ="5000"/>          <!-- deadline -->
   </process>
 
 </platform>
index a27b6e0..48c42b0 100644 (file)
@@ -187,6 +187,7 @@ XBT_PUBLIC(void) MSG_comm_waitall(msg_comm_t * comm, int nb_elem,
                                   double timeout);
 XBT_PUBLIC(int) MSG_comm_waitany(xbt_dynar_t comms);
 XBT_PUBLIC(m_task_t) MSG_comm_get_task(msg_comm_t comm);
+XBT_PUBLIC(MSG_error_t) MSG_comm_get_status(msg_comm_t comm);
 
 XBT_PUBLIC(int) MSG_task_listen(const char *alias);
 
index 3010fa0..2ba0587 100644 (file)
@@ -447,22 +447,70 @@ msg_comm_t MSG_task_irecv(m_task_t * task, const char *alias)
 }
 
 /** \ingroup msg_gos_functions
- * \brief Test the status of a communication.
- *
- * It takes one parameter.
- * \param comm the communication to test.
- * \return the status of the communication:
- *             TRUE : the communication is completed
- *             FALSE: the communication is incompleted
+ * \brief Returns whether a communication is finished.
+ * \param comm the communication to test
+ * \return TRUE if the communication is finished
+ * (but it may have failed, use MSG_comm_get_status() to know its status)
+ * or FALSE if the communication is not finished yet
  * If the status is FALSE, don't forget to use MSG_process_sleep() after the test.
  */
 int MSG_comm_test(msg_comm_t comm)
 {
-  return SIMIX_req_comm_test(comm);
+  xbt_ex_t e;
+  int finished = 0;
+  TRY {
+    finished = SIMIX_req_comm_test(comm);
+  }
+  CATCH(e) {
+    switch (e.category) {
+
+      case host_error:
+      case network_error:
+      case timeout_error:
+        finished = 1;
+        break;
+
+      default:
+        RETHROW;
+    }
+    xbt_ex_free(e);
+  }
+  return finished;
+}
+
+/** \ingroup msg_gos_functions
+ * \brief This function checks if a communication is finished
+ * \param comms a vector of communications
+ * \return the position of the finished communication if any
+ * (but it may have failed, use MSG_comm_get_status() to know its status),
+ * or -1 if none is finished
+ */
+int MSG_comm_testany(xbt_dynar_t comms)
+{
+  xbt_ex_t e;
+  int finished_index = -1;
+  TRY {
+    finished_index = SIMIX_req_comm_testany(comms);
+  }
+  CATCH(e) {
+    switch (e.category) {
+
+      case host_error:
+      case network_error:
+      case timeout_error:
+        finished_index = e.value;
+        break;
+
+      default:
+        RETHROW;
+    }
+    xbt_ex_free(e);
+  }
+  return finished_index;
 }
 
 /** \ingroup msg_gos_functions
- * \brief After received TRUE to MSG_comm_test(), the communication must be destroyed.
+ * \brief After received TRUE to MSG_comm_test(), the communication should be destroyed.
  *
  * It takes one parameter.
  * \param comm the communication to destroy.
@@ -512,7 +560,7 @@ MSG_error_t MSG_comm_wait(msg_comm_t comm, double timeout)
       res = MSG_TIMEOUT;
       break;
     default:
-      xbt_die(bprintf("Unhandled SIMIX network exception: %s", e.msg));
+      RETHROW;
     }
     xbt_ex_free(e);
   }
@@ -544,19 +592,64 @@ void MSG_comm_waitall(msg_comm_t * comm, int nb_elem, double timeout)
 */
 int MSG_comm_waitany(xbt_dynar_t comms)
 {
-  return SIMIX_req_comm_waitany(comms);
+  xbt_ex_t e;
+  int finished_index = -1;
+  TRY {
+    finished_index = SIMIX_req_comm_waitany(comms);
+  }
+  CATCH(e) {
+    switch (e.category) {
+
+      case host_error:
+      case network_error:
+      case timeout_error:
+        finished_index = e.value;
+      default:
+        RETHROW;
+    }
+    xbt_ex_free(e);
+  }
+  return finished_index;
 }
 
-/** \ingroup msg_gos_functions
-* \brief This function wait for the first completed communication
-*
-* It takes on parameter.
-* \param comms a vector of communication
-* \return the position of the completed communication, if any, or -1 if none was completed
-*/
-int MSG_comm_testany(xbt_dynar_t comms)
-{
-  return SIMIX_req_comm_testany(comms);
+/**
+ * \ingroup msg_gos_functions
+ * \brief Returns the error (if any) that occured during a finished communication.
+ * \param comm a finished communication
+ * \return the status of the communication, or MSG_OK if the communication
+ * was successfully completed
+ */
+MSG_error_t MSG_comm_get_status(msg_comm_t comm) {
+
+  MSG_error_t result;
+  e_smx_state_t smx_state = SIMIX_req_comm_get_state(comm);
+
+  switch (smx_state) {
+
+    case SIMIX_CANCELED:
+      result = MSG_TASK_CANCELLED;
+      break;
+
+    case SIMIX_FAILED:
+    case SIMIX_SRC_HOST_FAILURE:
+    case SIMIX_DST_HOST_FAILURE:
+      result = MSG_HOST_FAILURE;
+      break;
+
+    case SIMIX_LINK_FAILURE:
+      result = MSG_TRANSFER_FAILURE;
+      break;
+
+    case SIMIX_SRC_TIMEOUT:
+    case SIMIX_DST_TIMEOUT:
+      result = MSG_TIMEOUT;
+      break;
+
+    default:
+      result = MSG_OK;
+      break;
+  }
+  return result;
 }
 
 m_task_t MSG_comm_get_task(msg_comm_t comm)
diff --git a/src/replay/replay b/src/replay/replay
new file mode 100755 (executable)
index 0000000..f76519c
Binary files /dev/null and b/src/replay/replay differ
index fa62223..104dba6 100644 (file)
@@ -526,6 +526,17 @@ void SIMIX_comm_finish(smx_action_t action)
       default:
         THROW_IMPOSSIBLE;
     }
+
+    /* if there is an exception during a waitany or a testany, indicate the position of the failed communication */
+    if (req->issuer->doexception) {
+      if (req->call == REQ_COMM_WAITANY) {
+        req->issuer->running_ctx->exception.value = xbt_dynar_search(req->comm_waitany.comms, &action);
+      }
+      else if (req->call == REQ_COMM_TESTANY) {
+        req->issuer->running_ctx->exception.value = xbt_dynar_search(req->comm_testany.comms, &action);
+      }
+    }
+
     req->issuer->waiting_action = NULL;
     SIMIX_request_answer(req);
   }