Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot//simgrid/simgrid
authorMarion Guthmuller <marion.guthmuller@loria.fr>
Wed, 30 May 2012 09:04:59 +0000 (11:04 +0200)
committerMarion Guthmuller <marion.guthmuller@loria.fr>
Wed, 30 May 2012 09:04:59 +0000 (11:04 +0200)
21 files changed:
.gitignore
ChangeLog
buildtools/Cmake/AddTests.cmake
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/MakeExe.cmake
doc/module-msg.doc
examples/msg/cloud/CMakeLists.txt [new file with mode: 0644]
examples/msg/cloud/masterslave_virtual_machines.c [new file with mode: 0644]
examples/msg/cloud/masterslave_virtual_machines.xml [new file with mode: 0644]
include/msg/datatypes.h
include/msg/msg.h
include/simgrid/simix.h
src/msg/msg_global.c
src/msg/msg_host.c
src/msg/msg_private.h
src/msg/msg_process.c
src/msg/msg_vm.c [new file with mode: 0644]
src/simix/smx_network.c
src/simix/smx_private.h
src/simix/smx_user.c
src/xbt/log.c

index ee1d9ab..8edd0e3 100644 (file)
@@ -135,6 +135,7 @@ examples/msg/masterslave/toto.txt
 examples/msg/simulation.trace
 examples/msg/toto.txt
 examples/msg/z_gtnets.trace
+examples/msg/cloud/masterslave_virtual_machines
 examples/msg/tracing/link_srcdst_user_variables
 examples/msg/tracing/link_user_variables
 examples/msg/tracing/simple
index a9fd34a..463d8fa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 SimGrid (3.8) NOT RELEASED; urgency=low
 
+ The "SimGrid makes psssshiiiit and jumps into the cloud" release.
+  
+ MSG:
+ * Add an experimental interface to manipulate VMs. They are mainly
+   process groups with very few intrinsic semantic, but they should
+   allow you to build the semantic you want easily.
+
  SimDag:
  * New type of typed tasks SD_TASK_COMP_PAR_AMDAHL that represents a
    parallel task whose initial work is distributed among host according
@@ -17,6 +24,11 @@ SimGrid (3.8) NOT RELEASED; urgency=low
 
 SimGrid (3.7.1) NOT RELEASED; urgency=low
 
+ MSG:
+ * Restore the prototype of MSG_process_create_with_environment() to
+   the pre-3.7 situation by removing the kill_time argument.
+ * Add a MSG_process_set_kill_time() function instead.
+
  SURF:
  * Fix weird behaviors when dealing with parallel tasks.
 
index 6c038b2..be472c7 100644 (file)
@@ -146,6 +146,8 @@ ADD_TEST(msg-masterslave-failure-thread        ${CMAKE_BINARY_DIR}/bin/tesh ${TE
 ADD_TEST(msg-masterslave-mailbox-thread        ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:thread       --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg    --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/masterslave/masterslave_mailbox_crosstraffic.tesh)
 ADD_TEST(msg-masterslave-cpu-ti-thread         ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:thread       --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/masterslave    --cd ${CMAKE_HOME_DIRECTORY}/examples/msg masterslave/masterslave_cpu_ti_crosstraffic.tesh)
 
+ADD_TEST(msg-masterslave-virtual-machines ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:thread --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/cloud     --cd ${CMAKE_HOME_DIRECTORY}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/cloud/masterslave_virtual_machines.tesh)
+
 if(HAVE_UCONTEXT_H)
        ADD_TEST(msg-sendrecv-CLM03-ucontext    ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION}     --cfg contexts/factory:ucontext         --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg    --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_CLM03.tesh)
        ADD_TEST(msg-sendrecv-Vegas-ucontext    ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION}     --cfg contexts/factory:ucontext         --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg    --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_Vegas.tesh)
index 41c3f36..948d959 100644 (file)
@@ -281,6 +281,7 @@ set(MSG_SRC
        src/msg/msg_deployment.c
        src/msg/msg_mailbox.c
        src/msg/msg_actions.c
+       src/msg/msg_vm.c
 )
 
 set(SIMDAG_SRC
index eac15c9..b3f1413 100644 (file)
@@ -60,6 +60,7 @@ add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/msg/pmm)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/msg/start_kill_time)\r
 \r
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/msg/io)\r
+add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/msg/cloud)\r
 \r
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/examples/msg/gpu)\r
 \r
index 3df79fe..b4ffe38 100644 (file)
@@ -19,6 +19,7 @@
    - \ref m_task_management
    - \ref msg_file_management
    - \ref msg_task_usage
+   - \ref msg_VMs
    - \ref msg_trace_driven
    - \ref msg_deprecated_functions
 
@@ -87,6 +88,23 @@ details).
  *         by a process to execute, communicate or otherwise handle some task.
  */
 
+/** @defgroup msg_VMs VMs
+ *  @ingroup MSG_API
+ *  @brief This section describes the interface created to mimick IaaS clouds.
+ *
+ *  With it, you can create virtual machines to put your processes
+ *  into, and interact directly with the VMs to manage groups of
+ *  processes. 
+ *
+ *  This interface is highly experimental at this point. Testing is
+ *  welcomed, but do not expect too much of it right now. Even the
+ *  interfaces may be changed in future releases of SimGrid (although
+ *  things are expected to stabilize nicely before SimGrid v3.8).
+ *  There is no guaranty on the rest of SimGrid, and there is less
+ *  than that on this part.
+ *
+ */
+
 /** @defgroup msg_file_management File Management Functions
  *  @ingroup MSG_API
  *  @brief This section describes the file structure of MSG
diff --git a/examples/msg/cloud/CMakeLists.txt b/examples/msg/cloud/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3103f3e
--- /dev/null
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 2.6)
+
+set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
+
+add_executable(masterslave_virtual_machines "masterslave_virtual_machines.c")
+
+### Add definitions for compile
+if(WIN32)
+  target_link_libraries(masterslave_virtual_machines simgrid )
+else(WIN32)
+  target_link_libraries(masterslave_virtual_machines simgrid m )
+endif(WIN32)
diff --git a/examples/msg/cloud/masterslave_virtual_machines.c b/examples/msg/cloud/masterslave_virtual_machines.c
new file mode 100644 (file)
index 0000000..0ed5b90
--- /dev/null
@@ -0,0 +1,216 @@
+/* Copyright (c) 2007-2012. 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 <stdio.h>
+#include "msg/msg.h"            /* Yeah! If you want to use msg, you need to include msg/msg.h */
+#include "xbt/sysdep.h"         /* calloc, printf */
+
+/* Create a log channel to have nice outputs. */
+#include "xbt/log.h"
+#include "xbt/asserts.h"
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
+                             "Messages specific for this msg example");
+
+/** @addtogroup MSG_examples
+ * 
+ *  - <b>cloud/masterslave_virtual_machines.c: Master/slaves
+ *    example, à la cloud</b>. The classical example revisited to demonstrate the use of virtual machines.
+ */
+
+double task_comp_size = 10000000;
+double task_comm_size = 10000000;
+
+
+int master(int argc, char *argv[]);
+int slave_fun(int argc, char *argv[]);
+
+static void work_batch(int slaves_count) {
+  int i;
+  for (i = 0; i < slaves_count; i++) {
+    char taskname_buffer[64];
+    char mailbox_buffer[64];
+
+    sprintf(taskname_buffer, "Task_%d", i);
+    sprintf(mailbox_buffer,"Slave_%d",i);
+
+    XBT_INFO("Sending \"%s\" to \"%s\"",taskname_buffer,mailbox_buffer);
+    MSG_task_send(MSG_task_create(taskname_buffer, task_comp_size, task_comm_size,NULL),
+        mailbox_buffer);
+  }
+}
+
+int master(int argc, char *argv[]) {
+  int slaves_count = 10;
+  m_host_t *slaves = xbt_new(m_host_t,10);
+
+  int i;
+
+  /* Retrive the hostnames constituting our playground today */
+  for (i = 1; i < argc; i++) {
+    slaves[i - 1] = MSG_get_host_by_name(argv[i]);
+    xbt_assert(slaves[i - 1] != NULL, "Cannot use inexistent host %s", argv[i]);
+  }
+
+  /* Launch the sub processes: one VM per host, with one process inside each */
+
+  for (i=0;i<slaves_count;i++) {
+    char slavename[64];
+    sprintf(slavename,"Slave %d",i);
+    char**argv=xbt_new(char*,3);
+    argv[0] = xbt_strdup(slavename);
+    argv[1] = bprintf("%d",i);
+    argv[2] = NULL;
+    msg_vm_t vm = MSG_vm_start(slaves[i],2);
+    MSG_vm_bind(vm, MSG_process_create_with_arguments(slavename,slave_fun,NULL,slaves[i],2,argv));
+  }
+
+  xbt_dynar_t vms = MSG_vms_as_dynar();
+  XBT_INFO("Launched %ld VMs", xbt_dynar_length(vms));
+
+  /* Send a bunch of work to every one */
+  XBT_INFO("Send a first batch of work to every one");
+  work_batch(slaves_count);
+
+  XBT_INFO("Now suspend all VMs, just for fun");
+  for (i=0;i<xbt_dynar_length(vms);i++)
+    MSG_vm_suspend(xbt_dynar_get_as(vms,i,msg_vm_t));
+
+  XBT_INFO("Wait a while");
+  MSG_process_sleep(2);
+
+  XBT_INFO("Enough. Let's resume everybody.");
+  for (i=0;i<xbt_dynar_length(vms);i++)
+    MSG_vm_resume(xbt_dynar_get_as(vms,i,msg_vm_t));
+
+  XBT_INFO("Sleep long enough for everyone to be done with previous batch of work");
+  MSG_process_sleep(1000-MSG_get_clock());
+
+  XBT_INFO("Add one more process per VM, and dispatch a batch of work to everyone");
+  for (i=0;i<xbt_dynar_length(vms);i++) {
+    msg_vm_t vm = xbt_dynar_get_as(vms,i,msg_vm_t);
+    char slavename[64];
+    sprintf(slavename,"Slave %ld",i+xbt_dynar_length(vms));
+    char**argv=xbt_new(char*,3);
+    argv[0] = xbt_strdup(slavename);
+    argv[1] = bprintf("%ld",i+xbt_dynar_length(vms));
+    argv[2] = NULL;
+    MSG_vm_bind(vm, MSG_process_create_with_arguments(slavename,slave_fun,NULL,slaves[i],2,argv));
+  }
+  work_batch(slaves_count*2);
+
+  XBT_INFO("Migrate everyone to the second host.");
+  for (i=0;i<xbt_dynar_length(vms);i++)
+    MSG_vm_migrate(xbt_dynar_get_as(vms,i,msg_vm_t),slaves[1]);
+
+  XBT_INFO("Suspend everyone, move them to the third host, and resume them.");
+  for (i=0;i<xbt_dynar_length(vms);i++) {
+    msg_vm_t vm = xbt_dynar_get_as(vms,i,msg_vm_t);
+    MSG_vm_suspend(vm);
+    MSG_vm_migrate(vm,slaves[2]);
+    MSG_vm_resume(vm);
+  }
+
+
+
+  XBT_INFO("Let's shut down the simulation. 10 first processes will be shut down cleanly while the second half will forcefully get killed");
+  for (i = 0; i < slaves_count; i++) {
+    char mailbox_buffer[64];
+    sprintf(mailbox_buffer,"Slave_%d",i);
+    m_task_t finalize = MSG_task_create("finalize", 0, 0, 0);
+    MSG_task_send(finalize, mailbox_buffer);
+  }
+
+  for (i=0;i<xbt_dynar_length(vms);i++) {
+    msg_vm_t vm = xbt_dynar_get_as(vms,i,msg_vm_t);
+    MSG_vm_shutdown(vm);
+  }
+
+  XBT_INFO("Goodbye now!");
+  free(slaves);
+  xbt_dynar_free(&vms);
+  return 0;
+}                               /* end_of_master */
+
+/** Receiver function  */
+int slave_fun(int argc, char *argv[])
+{
+  char *mailbox_name;
+  m_task_t task = NULL;
+  _XBT_GNUC_UNUSED int res;
+
+  /* since the slaves will move around, use slave_%d as mailbox names instead of hostnames */
+  xbt_assert(argc>=2, "slave processes need to be given their rank as parameter");
+  mailbox_name=bprintf("Slave_%s",argv[1]);
+
+  while (1) {
+    res = MSG_task_receive(&(task),mailbox_name);
+    xbt_assert(res == MSG_OK, "MSG_task_get failed");
+
+    XBT_INFO("Received \"%s\" from mailbox %s", MSG_task_get_name(task),mailbox_name);
+    if (!strcmp(MSG_task_get_name(task), "finalize")) {
+      MSG_task_destroy(task);
+      break;
+    }
+
+    MSG_task_execute(task);
+    XBT_INFO("\"%s\" done", MSG_task_get_name(task));
+    MSG_task_destroy(task);
+    task = NULL;
+  }
+  free(mailbox_name);
+  return 0;
+}                               /* end_of_slave */
+
+/** Main function */
+int main(int argc, char *argv[])
+{
+  MSG_error_t res = MSG_OK;
+  xbt_dynar_t hosts_dynar;
+  m_host_t*hosts= xbt_new(m_host_t,10);
+  char**hostnames= xbt_new(char*,10);
+  char**masterargv=xbt_new(char*,12);
+  int i;
+
+  /* Get the arguments */
+  MSG_global_init(&argc, argv);
+  if (argc < 2) {
+    printf("Usage: %s platform_file\n", argv[0]);
+    printf("example: %s msg_platform.xml\n", argv[0]);
+    exit(1);
+  } if (argc>2) {
+    printf("Usage: %s platform_file\n", argv[0]);
+    printf("Other parameters (such as the deployment file) are ignored.");
+  }
+
+  /* load the platform file */
+  MSG_create_environment(argv[1]);
+  /* Retrieve the 10 first hosts of the platform file */
+  hosts_dynar = MSG_hosts_as_dynar();
+  xbt_assert(xbt_dynar_length(hosts_dynar)>10,
+      "I need at least 10 hosts in the platform file, but %s contains only %ld hosts_dynar.",
+      argv[1],xbt_dynar_length(hosts_dynar));
+  for (i=0;i<10;i++) {
+    hosts[i] = xbt_dynar_get_as(hosts_dynar,i,m_host_t);
+    hostnames[i] = xbt_strdup(MSG_host_get_name(hosts[i]));
+  }
+  masterargv[0]=xbt_strdup("master");
+  for (i=1;i<11;i++) {
+    masterargv[i] = xbt_strdup(MSG_host_get_name(hosts[i-1]));
+  }
+  masterargv[11]=NULL;
+  MSG_process_create_with_arguments("master",master,NULL,hosts[0],11,masterargv);
+  res = MSG_main();
+  XBT_INFO("Simulation time %g", MSG_get_clock());
+
+  MSG_clean();
+  free(hosts);
+  free(hostnames);
+  xbt_dynar_free(&hosts_dynar);
+
+  if (res == MSG_OK)
+    return 0;
+  else
+    return 1;
+}                               /* end_of_main */
diff --git a/examples/msg/cloud/masterslave_virtual_machines.xml b/examples/msg/cloud/masterslave_virtual_machines.xml
new file mode 100644 (file)
index 0000000..83bcdda
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version='1.0'?>
+<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
+<platform version="3">
+  <!-- The master process (with some arguments) -->
+  <process host="Tremblay" function="master">
+     <argument value="20"/>       <!-- Number of tasks -->
+     <argument value="50000000"/>  <!-- Computation size of tasks -->
+     <argument value="1000000"/>   <!-- Communication size of tasks -->
+     <argument value="Jupiter"/>  <!-- First slave -->
+     <argument value="Fafard"/>   <!-- Second slave -->
+     <argument value="Ginette"/>  <!-- Third slave -->
+     <argument value="Bourassa"/> <!-- Last slave -->
+  </process>
+  <!-- The slave process (with no argument) -->
+  <process host="Tremblay" function="slave"/>
+  <process host="Jupiter" function="slave"/>
+  <process host="Fafard" function="slave"/>
+  <process host="Ginette" function="slave"/>
+  <process host="Bourassa" function="slave"/>
+</platform>
index 79fc90a..c2c2e61 100644 (file)
@@ -1,5 +1,4 @@
-/* Copyright (c) 2004, 2005, 2007, 2008, 2009, 2010. The SimGrid Team.
- * All rights reserved.                                                     */
+/* Copyright (c) 2004-2012. 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. */
@@ -31,6 +30,7 @@ typedef struct s_smx_rvpoint *msg_mailbox_t;
 /* ******************************** Host ************************************ */
 
 typedef struct m_host {
+  xbt_swag_t vms;
   smx_host_t smx_host;          /**< SIMIX representation of this host   */
 #ifdef MSG_USE_DEPRECATED
   msg_mailbox_t *mailboxes;     /**< the channels  */
index d28939b..5280a31 100644 (file)
@@ -1,5 +1,4 @@
-/* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
- * All rights reserved.                                                     */
+/* Copyright (c) 2004-2012. 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. */
@@ -102,7 +101,6 @@ XBT_PUBLIC(m_process_t) MSG_process_create_with_environment(const char
                                                             code,
                                                             void *data,
                                                             m_host_t host,
-                                                            double kill_time,
                                                             int argc,
                                                             char **argv,
                                                             xbt_dict_t
@@ -125,6 +123,7 @@ XBT_PUBLIC(int) MSG_process_self_PID(void);
 XBT_PUBLIC(int) MSG_process_self_PPID(void);
 XBT_PUBLIC(m_process_t) MSG_process_self(void);
 XBT_PUBLIC(xbt_dynar_t) MSG_processes_as_dynar(void);
+XBT_PUBLIC(MSG_error_t) MSG_process_set_kill_time(m_process_t process, double kill_time);
 
 /*property handlers*/
 XBT_PUBLIC(xbt_dict_t) MSG_process_get_properties(m_process_t process);
@@ -287,7 +286,59 @@ XBT_PUBLIC(int) MSG_get_channel_number(void);
 
 #include "instr/instr.h"
 
-/* Used only by the bindings */
+/** @brief Opaque type describing a Virtual Machine.
+ *  @ingroup msg_VMs
+ *
+ * All this is highly experimental and the interface will probably change in the future.
+ * Please don't depend on this yet (although testing is welcomed if you feel so).
+ * Usual lack of guaranty of any kind applies here, and is even increased.
+ *
+ */
+typedef struct msg_vm *msg_vm_t;
+/* This function should not be called directly, but rather from MSG_vm_start_from_template that does not exist yet*/
+XBT_PUBLIC(msg_vm_t) MSG_vm_start(m_host_t location, int coreAmount);
+
+XBT_PUBLIC(int) MSG_vm_is_suspended(msg_vm_t);
+XBT_PUBLIC(int) MSG_vm_is_running(msg_vm_t);
+
+XBT_PUBLIC(void) MSG_vm_bind(msg_vm_t vm, m_process_t process);
+XBT_PUBLIC(void) MSG_vm_unbind(msg_vm_t vm, m_process_t process); // simple wrapper over process_kill
+
+XBT_PUBLIC(void) MSG_vm_migrate(msg_vm_t vm, m_host_t destination);
+
+XBT_PUBLIC(void) MSG_vm_suspend(msg_vm_t vm);
+  // \forall p in VM, MSG_process_suspend(p) // Freeze the processes
+
+XBT_PUBLIC(void) MSG_vm_resume(msg_vm_t vm);  // Simulate the fact of reading the processes from disk and resuming them
+  // \forall p in VM, MSG_process_resume(p) // unfreeze them
+
+XBT_PUBLIC(void) MSG_vm_shutdown(msg_vm_t vm); // killall
+
+XBT_PUBLIC(xbt_dynar_t) MSG_vms_as_dynar(void);
+
+/*
+void* MSG_process_get_property(msg_process_t, char* key)
+void MSG_process_set_property(msg_process_t, char* key, void* data)
+void MSG_vm_set_property(msg_vm_t, char* key, void* data)
+
+void MSG_vm_setMemoryUsed(msg_vm_t vm, double size);
+void MSG_vm_setCpuUsed(msg_vm_t vm, double inducedLoad);
+  // inducedLoad: un pourcentage (>100 si ca charge plus d'un coeur;
+  //                              <100 si c'est pas CPU intensive)
+  // Contraintes à poser:
+  //   HOST_Power >= CpuUsedVm (\forall VM) + CpuUsedTask (\forall Task)
+  //   VM_coreAmount >= Load de toutes les tasks
+*/
+
+  /*
+xbt_dynar_t<msg_vm_t> MSG_vm_get_list_from_host(msg_host_t)
+xbt_dynar_t<msg_vm_t> MSG_vm_get_list_from_hosts(msg_dynar_t<msg_host_t>)
++ des fonctions de filtrage sur les dynar
+*/
+
+
+/* ****************************************************************************************** */
+/* Used only by the bindings -- unclean pimple, please ignore if you're not writing a binding */
 XBT_PUBLIC(smx_context_t) MSG_process_get_smx_ctx(m_process_t process);
 
 SG_END_DECL()
index b99a048..0bdfbab 100644 (file)
@@ -332,6 +332,7 @@ XBT_PUBLIC(smx_host_t) simcall_process_get_host(smx_process_t process);
 XBT_PUBLIC(const char *) simcall_process_get_name(smx_process_t process);
 XBT_PUBLIC(int) simcall_process_is_suspended(smx_process_t process);
 XBT_PUBLIC(xbt_dict_t) simcall_process_get_properties(smx_process_t host);
+XBT_PUBLIC(void) simcall_process_set_kill_time(smx_process_t process, double kill_time);
 
 /* Sleep control */
 XBT_PUBLIC(e_smx_state_t) simcall_process_sleep(double duration);
index cb06f1d..8aa2f6c 100644 (file)
@@ -39,6 +39,8 @@ void MSG_global_init(int *argc, char **argv)
 
   xbt_getpid = MSG_process_self_PID;
   if (!msg_global) {
+    s_msg_vm_t vm; // to compute the offset
+
     SIMIX_global_init(argc, argv);
 
     msg_global = xbt_new0(s_MSG_Global_t, 1);
@@ -50,6 +52,7 @@ void MSG_global_init(int *argc, char **argv)
     msg_global->sent_msg = 0;
     msg_global->task_copy_callback = NULL;
     msg_global->process_data_cleanup = NULL;
+    msg_global->vms = xbt_swag_new(xbt_swag_offset(vm,all_vms_hookup));
 
     /* initialization of the action module */
     _MSG_action_init();
@@ -64,6 +67,7 @@ void MSG_global_init(int *argc, char **argv)
 
   XBT_DEBUG("ADD MSG LEVELS");
   MSG_HOST_LEVEL = xbt_lib_add_level(host_lib, (void_f_pvoid_t) __MSG_host_destroy);
+
 }
 
 #ifdef MSG_USE_DEPRECATED
@@ -193,6 +197,7 @@ MSG_error_t MSG_clean(void)
 
   SIMIX_clean();
 
+  xbt_swag_free(msg_global->vms);
   free(msg_global);
   msg_global = NULL;
 
index dfa729e..086d9bf 100644 (file)
@@ -10,6 +10,8 @@
 #include "xbt/log.h"
 #include "simgrid/simix.h"
 
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(msg);
+
 /** @addtogroup m_host_management
  *     \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Hosts" --> \endhtmlonly
  * (#m_host_t) and the functions for managing it.
@@ -28,8 +30,10 @@ m_host_t __MSG_host_create(smx_host_t workstation)
 {
   const char *name = SIMIX_host_get_name(workstation);
   m_host_t host = xbt_new0(s_m_host_t, 1);
+  s_msg_vm_t vm; // simply to compute the offset
 
   host->smx_host = workstation;
+  host->vms = xbt_swag_new(xbt_swag_offset(vm,host_vms_hookup));
 
 #ifdef MSG_USE_DEPRECATED
   int i;
@@ -120,7 +124,11 @@ void __MSG_host_destroy(m_host_t host) {
   if (msg_global->max_channel > 0)
     free(host->mailboxes);
 #endif
-
+  if (xbt_swag_size(host->vms) > 0 ) {
+    XBT_VERB("Host %s shut down, but it still hosts %d VMs. They will be leaked.",
+        MSG_host_get_name(host),xbt_swag_size(host->vms));
+  }
+  xbt_swag_free(host->vms);
   free(host);
 }
 
index 55a22d6..23699dd 100644 (file)
@@ -90,6 +90,19 @@ typedef struct msg_comm {
   MSG_error_t status;           /* status of the communication once finished */
 } s_msg_comm_t;
 
+typedef enum {
+  msg_vm_state_suspended, msg_vm_state_running, msg_vm_state_migrating
+} e_msg_vm_state_t;
+
+typedef struct msg_vm {
+  s_xbt_swag_hookup_t all_vms_hookup;
+  s_xbt_swag_hookup_t host_vms_hookup;
+  xbt_dynar_t processes;
+  e_msg_vm_state_t state;
+  m_host_t location;
+  int coreAmount;
+} s_msg_vm_t;
+
 /************************** Global variables ********************************/
 typedef struct MSG_Global {
   xbt_fifo_t host;
@@ -101,6 +114,7 @@ typedef struct MSG_Global {
   unsigned long int sent_msg;   /* Total amount of messages sent during the simulation */
   void (*task_copy_callback) (m_task_t task, m_process_t src, m_process_t dst);
   void_f_pvoid_t process_data_cleanup;
+  xbt_swag_t vms;
 } s_MSG_Global_t, *MSG_Global_t;
 
 /*extern MSG_Global_t msg_global;*/
index 6e9a904..50c8fa1 100644 (file)
@@ -63,8 +63,9 @@ void MSG_process_create_from_SIMIX(smx_process_t* process, const char *name,
 {
   m_host_t host = MSG_get_host_by_name(hostname);
   m_process_t p = MSG_process_create_with_environment(name, code, data,
-                                                      host, kill_time, argc, argv,
+                                                      host, argc, argv,
                                                       properties);
+  MSG_process_set_kill_time(p,kill_time);
   *((m_process_t*) process) = p;
 }
 
@@ -79,7 +80,7 @@ m_process_t MSG_process_create(const char *name,
                                xbt_main_func_t code, void *data,
                                m_host_t host)
 {
-  return MSG_process_create_with_environment(name, code, data, host, -1, -1,
+  return MSG_process_create_with_environment(name, code, data, host, -1,
                                              NULL, NULL);
 }
 
@@ -113,7 +114,7 @@ m_process_t MSG_process_create_with_arguments(const char *name,
                                               void *data, m_host_t host,
                                               int argc, char **argv)
 {
-  return MSG_process_create_with_environment(name, code, data, host, -1.0,
+  return MSG_process_create_with_environment(name, code, data, host,
                                              argc, argv, NULL);
 }
 
@@ -136,7 +137,6 @@ m_process_t MSG_process_create_with_arguments(const char *name,
    object.  It is for user-level information and can be NULL. It can
    be retrieved with the function \ref MSG_process_get_data.
  * \param host the location where the new process is executed.
- * \param kill_time the time when the process is killed.
  * \param argc first argument passed to \a code
  * \param argv second argument passed to \a code
  * \param properties list a properties defined for this process
@@ -146,7 +146,6 @@ m_process_t MSG_process_create_with_arguments(const char *name,
 m_process_t MSG_process_create_with_environment(const char *name,
                                                 xbt_main_func_t code,
                                                 void *data, m_host_t host,
-                                                double kill_time,
                                                 int argc, char **argv,
                                                 xbt_dict_t properties)
 {
@@ -176,7 +175,7 @@ m_process_t MSG_process_create_with_environment(const char *name,
 
   /* Let's create the process: SIMIX may decide to start it right now,
    * even before returning the flow control to us */
-  simcall_process_create(&process, name, code, simdata, SIMIX_host_get_name(host->smx_host), kill_time,
+  simcall_process_create(&process, name, code, simdata, SIMIX_host_get_name(host->smx_host), -1,
                            argc, argv, properties);
 
   if (!process) {
@@ -315,6 +314,18 @@ xbt_dynar_t MSG_processes_as_dynar(void) {
   return SIMIX_processes_as_dynar();
 }
 
+/** \ingroup m_process_management
+ * \brief Set the kill time of a process.
+ *
+ * \param process a process
+ * \param kill_time the time when the process is killed.
+ */
+MSG_error_t MSG_process_set_kill_time(m_process_t process, double kill_time)
+{
+  simcall_process_set_kill_time(process,kill_time);
+  return MSG_OK;
+}
+
 /** \ingroup m_process_management
  * \brief Returns the process ID of \a process.
  *
diff --git a/src/msg/msg_vm.c b/src/msg/msg_vm.c
new file mode 100644 (file)
index 0000000..b31536f
--- /dev/null
@@ -0,0 +1,143 @@
+/* Copyright (c) 2012. 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 "msg_private.h"
+#include "xbt/sysdep.h"
+#include "xbt/log.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_vm, msg,
+                                "Cloud-oriented parts of the MSG API");
+
+/** @brief Create a new (empty) VMs
+ *  @ingroup msg_VMs
+ *
+ *  @bug it is expected that in the future, the coreAmount parameter will be used
+ *  to add extra constraints on the execution, but the argument is ignored for now.
+ */
+
+msg_vm_t MSG_vm_start(m_host_t location, int coreAmount) {
+  msg_vm_t res = xbt_new0(s_msg_vm_t,1);
+  res->all_vms_hookup.prev = NULL;
+  res->host_vms_hookup.prev = NULL;
+  res->state = msg_vm_state_running;
+  res->location = location;
+  res->coreAmount = coreAmount;
+  res->processes = xbt_dynar_new(sizeof(m_process_t),NULL);
+
+  xbt_swag_insert(res,msg_global->vms);
+  xbt_swag_insert(res,location->vms);
+
+  return res;
+}
+/** @brief Returns a newly constructed dynar containing all existing VMs in the system
+ *  @ingroup msg_VMs
+ *
+ * Don't forget to free the dynar after use.
+ */
+xbt_dynar_t MSG_vms_as_dynar(void) {
+  xbt_dynar_t res = xbt_dynar_new(sizeof(msg_vm_t),NULL);
+  msg_vm_t vm;
+  xbt_swag_foreach(vm,msg_global->vms) {
+    xbt_dynar_push(res,&vm);
+  }
+  return res;
+}
+
+/** @brief Returns whether the given VM is currently suspended
+ *  @ingroup msg_VMs
+ */
+int MSG_vm_is_suspended(msg_vm_t vm) {
+  return vm->state == msg_vm_state_suspended;
+}
+/** @brief Returns whether the given VM is currently running
+ *  @ingroup msg_VMs
+ */
+int MSG_vm_is_running(msg_vm_t vm) {
+  return vm->state == msg_vm_state_running;
+}
+/** @brief Add the given process into the VM.
+ *  @ingroup msg_VMs
+ *
+ * Afterward, when the VM is migrated or suspended or whatever, the process will have the corresponding handling, too.
+ *
+ * @bug for now, if a binded process terminates, every VM functions will segfault. Baaaad.
+ */
+void MSG_vm_bind(msg_vm_t vm, m_process_t process) {
+  xbt_dynar_push_as(vm->processes,m_process_t,process);
+}
+/** @brief Removes the given process from the given VM, and kill it
+ *  @ingroup msg_VMs
+ *
+ *  Will raise a not_found exception if the process were not binded to that VM
+ */
+void MSG_vm_unbind(msg_vm_t vm, m_process_t process) {
+  int pos = xbt_dynar_search(vm->processes,process);
+  xbt_dynar_remove_at(vm->processes,pos, NULL);
+  MSG_process_kill(process);
+}
+
+/** @brief Immediately change the host on which all processes are running
+ *  @ingroup msg_VMs
+ *
+ * No migration cost occurs. If you want to simulate this too, you want to use a
+ * MSG_task_send() before or after, depending on whether you want to do cold or hot
+ * migration.
+ */
+void MSG_vm_migrate(msg_vm_t vm, m_host_t destination) {
+  unsigned int cpt;
+  m_process_t process;
+  xbt_dynar_foreach(vm->processes,cpt,process) {
+    MSG_process_migrate(process,destination);
+  }
+  xbt_swag_remove(vm,vm->location->vms);
+  xbt_swag_insert_at_tail(vm,destination->vms);
+  vm->location = destination;
+}
+
+/** @brief Immediately suspend the execution of all processes within the given VM
+ *  @ingroup msg_VMs
+ *
+ * No suspension cost occurs. If you want to simulate this too, you want to
+ * use a \ref MSG_file_write() before or after, depending on the exact semantic
+ * of VM suspend to you.
+ */
+void MSG_vm_suspend(msg_vm_t vm) {
+  unsigned int cpt;
+  m_process_t process;
+  xbt_dynar_foreach(vm->processes,cpt,process) {
+    XBT_INFO("suspend process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
+    MSG_process_suspend(process);
+  }
+}
+
+/** @brief Immediately resumes the execution of all processes within the given VM
+ *  @ingroup msg_VMs
+ *
+ * No resume cost occurs. If you want to simulate this too, you want to
+ * use a \ref MSG_file_read() before or after, depending on the exact semantic
+ * of VM resume to you.
+ */
+void MSG_vm_resume(msg_vm_t vm) {
+  unsigned int cpt;
+  m_process_t process;
+  xbt_dynar_foreach(vm->processes,cpt,process) {
+    XBT_INFO("resume process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
+    MSG_process_resume(process);
+  }
+}
+
+/** @brief Immediately kills all processes within the given VM. Any memory that they allocated will be leaked.
+ *  @ingroup msg_VMs
+ *
+ * No extra delay occurs. If you want to simulate this too, you want to
+ * use a #MSG_process_sleep() or something. I'm not quite sure.
+ */
+void MSG_vm_shutdown(msg_vm_t vm) {
+  unsigned int cpt;
+  m_process_t process;
+  xbt_dynar_foreach(vm->processes,cpt,process) {
+    MSG_process_kill(process);
+  }
+}
index a21f74e..da59e87 100644 (file)
@@ -205,9 +205,9 @@ void SIMIX_comm_destroy(smx_action_t action)
             action, action->comm.refcount, (int)action->state);
 
   if (action->comm.refcount <= 0) {
-       xbt_backtrace_display_current();
-    xbt_die("the refcount of comm %p is already 0 before decreasing it. "
-            "That's a bug!", action);
+    xbt_backtrace_display_current();
+    xbt_die("The refcount of comm %p is already 0 before decreasing it. "
+            "That's a bug! If you didn't test and/or wait the same communication twice in your code, then the bug is SimGrid's...", action);
   }
   action->comm.refcount--;
   if (action->comm.refcount > 0)
index 2e3ca93..178acd2 100644 (file)
@@ -140,7 +140,7 @@ typedef struct s_smx_action {
       void *dst_buff;
       size_t src_buff_size;
       size_t *dst_buff_size;
-      char copied;
+      int copied:1;                   /* whether the data were already copied */
 
       void* src_data;                     /* User data associated to communication */
       void* dst_data;
@@ -281,7 +281,7 @@ static XBT_INLINE void SIMIX_context_runall(void)
  */
 static XBT_INLINE smx_context_t SIMIX_context_self(void)
 {
-  if (simix_global && simix_global->context_factory != NULL) {
+  if (simix_global && simix_global->context_factory) {
     return simix_global->context_factory->self();
   }
 
index 455b98d..a23bdda 100644 (file)
@@ -521,6 +521,24 @@ void simcall_process_set_data(smx_process_t process, void *data)
   }
 }
 
+/**
+ * \brief Set the kill time of a process.
+ *
+ * \param process a process
+ * \param kill_time a double
+ */
+void simcall_process_set_kill_time(smx_process_t process, double kill_time)
+{
+
+  if (kill_time > SIMIX_get_clock()) {
+    if (simix_global->kill_process_function) {
+      XBT_DEBUG("Set kill time %f for process %s(%s)",kill_time, process->name,
+          process->smx_host->name);
+      SIMIX_timer_set(kill_time, simix_global->kill_process_function, process);
+    }
+  }
+}
+
 /**
  * \brief Return the location on which an agent is running.
  *
@@ -987,6 +1005,10 @@ int simcall_comm_is_latency_bounded(smx_action_t comm)
 
 smx_mutex_t simcall_mutex_init(void)
 {
+  if(!simix_global) {
+    fprintf(stderr,"You must run MSG_global_init or gras_init before using MSG or GRAS\n"); // I would have loved using xbt_die but I can't since it is not initialized yet... :)
+    abort();
+  }
   smx_simcall_t simcall = SIMIX_simcall_mine();
 
   simcall->call = SIMCALL_MUTEX_INIT;
index 28b799c..95f47ca 100644 (file)
@@ -649,7 +649,8 @@ static void xbt_log_connect_categories(void)
   XBT_LOG_CONNECT(msg_mailbox);
   XBT_LOG_CONNECT(msg_process);
   XBT_LOG_CONNECT(msg_task);
-
+  XBT_LOG_CONNECT(msg_vm);
+   
   /* simdag */
   XBT_LOG_CONNECT(sd);
   XBT_LOG_CONNECT(sd_daxparse);