Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
another useless function dies
[simgrid.git] / src / simix / smx_host.cpp
1 /* Copyright (c) 2007-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "smx_private.h"
8 #include <xbt/ex.hpp>
9 #include "xbt/sysdep.h"
10 #include "mc/mc.h"
11 #include "src/mc/mc_replay.h"
12 #include "src/surf/virtual_machine.hpp"
13 #include "src/surf/HostImpl.hpp"
14
15 #include "src/kernel/activity/SynchroExec.hpp"
16 #include "src/kernel/activity/SynchroComm.hpp"
17
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_host, simix, "SIMIX hosts");
19
20 namespace simgrid {
21   namespace simix {
22     simgrid::xbt::Extension<simgrid::s4u::Host, Host> Host::EXTENSION_ID;
23
24     Host::Host()
25     {
26       if (!EXTENSION_ID.valid())
27         EXTENSION_ID = simgrid::s4u::Host::extension_create<simgrid::simix::Host>();
28
29       simgrid::simix::ActorImpl act;
30       process_list = xbt_swag_new(xbt_swag_offset(act, host_proc_hookup));
31     }
32
33     Host::~Host()
34     {
35       /* Clean Simulator data */
36       if (xbt_swag_size(process_list) != 0) {
37         char *msg = xbt_strdup("Shutting down host, but it's not empty:");
38         char *tmp;
39         smx_actor_t process = nullptr;
40
41         xbt_swag_foreach(process, process_list) {
42           tmp = bprintf("%s\n\t%s", msg, process->name.c_str());
43           free(msg);
44           msg = tmp;
45         }
46         SIMIX_display_process_status();
47         THROWF(arg_error, 0, "%s", msg);
48       }
49       xbt_dynar_free(&auto_restart_processes);
50       xbt_dynar_free(&boot_processes);
51       xbt_swag_free(process_list);
52     }
53   }
54 }
55
56 /** @brief Internal function to create a SIMIX host. */
57 void SIMIX_host_create(sg_host_t host)
58 {
59   sg_host_simix_set(host, new simgrid::simix::Host());
60 }
61
62 /** @brief Start the host if it is off */
63 void SIMIX_host_on(sg_host_t h)
64 {
65   smx_host_priv_t host = sg_host_simix(h);
66
67   xbt_assert((host != nullptr), "Invalid parameters");
68
69   if (h->isOff()) {
70     simgrid::surf::HostImpl* surf_host = h->extension<simgrid::surf::HostImpl>();
71     surf_host->turnOn();
72
73     unsigned int cpt;
74     smx_process_arg_t arg;
75     xbt_dynar_foreach(host->boot_processes,cpt,arg) {
76       XBT_DEBUG("Booting Process %s(%s) right now",
77         arg->name.c_str(), arg->hostname);
78       if (simix_global->create_process_function) {
79         simix_global->create_process_function(arg->name.c_str(),
80                                               arg->code,
81                                               nullptr,
82                                               arg->hostname,
83                                               arg->kill_time,
84                                               arg->properties,
85                                               arg->auto_restart,
86                                               nullptr);
87       } else {
88         simcall_process_create(arg->name.c_str(),
89                                arg->code,
90                                nullptr,
91                                arg->hostname,
92                                arg->kill_time,
93                                arg->properties,
94                                arg->auto_restart);
95       }
96     }
97   }
98 }
99
100 /** @brief Stop the host if it is on */
101 void SIMIX_host_off(sg_host_t h, smx_actor_t issuer)
102 {
103   smx_host_priv_t host = sg_host_simix(h);
104
105   xbt_assert((host != nullptr), "Invalid parameters");
106
107   if (h->isOn()) {
108     simgrid::surf::HostImpl* surf_host = h->extension<simgrid::surf::HostImpl>();
109     surf_host->turnOff();
110
111     /* Clean Simulator data */
112     if (xbt_swag_size(host->process_list) != 0) {
113       smx_actor_t process = nullptr;
114       xbt_swag_foreach(process, host->process_list) {
115         SIMIX_process_kill(process, issuer);
116         XBT_DEBUG("Killing %s on %s by %s",
117           process->name.c_str(),  sg_host_get_name(process->host),
118           issuer->name.c_str());
119       }
120     }
121   } else {
122     XBT_INFO("Host %s is already off", h->name().c_str());
123   }
124 }
125
126 sg_host_t SIMIX_host_self()
127 {
128   smx_actor_t process = SIMIX_process_self();
129   return (process == nullptr) ? nullptr : process->host;
130 }
131
132 /* needs to be public and without simcall for exceptions and logging events */
133 const char* SIMIX_host_self_get_name()
134 {
135   sg_host_t host = SIMIX_host_self();
136   if (host == nullptr || SIMIX_process_self() == simix_global->maestro_process)
137     return "";
138
139   return sg_host_get_name(host);
140 }
141
142 void _SIMIX_host_free_process_arg(void *data)
143 {
144   smx_process_arg_t arg = *(static_cast<smx_process_arg_t*>(data));
145   delete arg;
146 }
147 /**
148  * \brief Add a process to the list of the processes that the host will restart when it comes back
149  * This function add a process to the list of the processes that will be restarted when the host comes
150  * back. It is expected that this function is called when the host is down.
151  * The processes will only be restarted once, meaning that you will have to register the process
152  * again to restart the process again.
153  */
154 void SIMIX_host_add_auto_restart_process(
155   sg_host_t host, const char *name, std::function<void()> code,
156   void* data, const char *hostname, double kill_time,
157   xbt_dict_t properties, int auto_restart)
158 {
159   if (!sg_host_simix(host)->auto_restart_processes) {
160     sg_host_simix(host)->auto_restart_processes = xbt_dynar_new(sizeof(smx_process_arg_t),_SIMIX_host_free_process_arg);
161   }
162   smx_process_arg_t arg = new simgrid::simix::ProcessArg();
163   arg->name = name;
164   arg->code = std::move(code);
165   arg->data = data;
166   arg->hostname = hostname;
167   arg->kill_time = kill_time;
168   arg->properties = properties;
169   arg->auto_restart = auto_restart;
170
171   if( host->isOff() && !xbt_dict_get_or_null(watched_hosts_lib,sg_host_get_name(host))){
172     xbt_dict_set(watched_hosts_lib,sg_host_get_name(host),host,nullptr);
173     XBT_DEBUG("Push host %s to watched_hosts_lib because state == SURF_RESOURCE_OFF",sg_host_get_name(host));
174   }
175   xbt_dynar_push_as(sg_host_simix(host)->auto_restart_processes,smx_process_arg_t,arg);
176 }
177 /** @brief Restart the list of processes that have been registered to the host */
178 void SIMIX_host_autorestart(sg_host_t host)
179 {
180   unsigned int cpt;
181   smx_process_arg_t arg;
182   xbt_dynar_t process_list = sg_host_simix(host)->auto_restart_processes;
183   if (!process_list)
184     return;
185
186   xbt_dynar_foreach (process_list, cpt, arg) {
187
188     XBT_DEBUG("Restarting Process %s(%s) right now", arg->name.c_str(), arg->hostname);
189     if (simix_global->create_process_function) {
190       simix_global->create_process_function(arg->name.c_str(), arg->code, nullptr, arg->hostname, arg->kill_time,
191                                             arg->properties, arg->auto_restart, nullptr);
192     } else {
193       simcall_process_create(arg->name.c_str(), arg->code, nullptr, arg->hostname, arg->kill_time, arg->properties,
194                              arg->auto_restart);
195     }
196   }
197   xbt_dynar_reset(process_list);
198 }
199
200 smx_activity_t simcall_HANDLER_execution_start(smx_simcall_t simcall, const char* name, double flops_amount,
201                                               double priority, double bound) {
202   return SIMIX_execution_start(simcall->issuer, name,flops_amount,priority,bound);
203 }
204
205 smx_activity_t SIMIX_execution_start(smx_actor_t issuer, const char *name, double flops_amount, double priority,
206                                     double bound){
207
208   /* alloc structures and initialize */
209   simgrid::kernel::activity::Exec *exec = new simgrid::kernel::activity::Exec(name, issuer->host);
210
211   /* set surf's action */
212   if (!MC_is_active() && !MC_record_replay_is_active()) {
213
214     exec->surf_exec = issuer->host->pimpl_cpu->execution_start(flops_amount);
215     exec->surf_exec->setData(exec);
216     exec->surf_exec->setPriority(priority);
217
218     if (bound > 0)
219       static_cast<simgrid::surf::CpuAction*>(exec->surf_exec)->setBound(bound);
220   }
221
222   XBT_DEBUG("Create execute synchro %p: %s", exec, exec->name.c_str());
223
224   return exec;
225 }
226
227 smx_activity_t SIMIX_execution_parallel_start(const char *name, int host_nb, sg_host_t *host_list, double *flops_amount,
228                                              double *bytes_amount, double amount, double rate){
229
230   /* alloc structures and initialize */
231   simgrid::kernel::activity::Exec *exec = new simgrid::kernel::activity::Exec(name, nullptr);
232
233   /* set surf's synchro */
234   sg_host_t *host_list_cpy = xbt_new0(sg_host_t, host_nb);
235   for (int i = 0; i < host_nb; i++)
236     host_list_cpy[i] = host_list[i];
237
238   /* Check that we are not mixing VMs and PMs in the parallel task */
239   simgrid::surf::HostImpl *host = host_list[0]->extension<simgrid::surf::HostImpl>();
240   bool is_a_vm = (nullptr != dynamic_cast<simgrid::surf::VirtualMachine*>(host));
241   for (int i = 1; i < host_nb; i++) {
242     bool tmp_is_a_vm = (nullptr != dynamic_cast<simgrid::surf::VirtualMachine*>(host_list[i]->extension<simgrid::surf::HostImpl>()));
243     xbt_assert(is_a_vm == tmp_is_a_vm, "parallel_execute: mixing VMs and PMs is not supported (yet).");
244   }
245
246   /* set surf's synchro */
247   if (!MC_is_active() && !MC_record_replay_is_active()) {
248     exec->surf_exec = surf_host_model->executeParallelTask(host_nb, host_list_cpy, flops_amount, bytes_amount, rate);
249     exec->surf_exec->setData(exec);
250   }
251   XBT_DEBUG("Create parallel execute synchro %p", exec);
252
253   return exec;
254 }
255
256 void SIMIX_execution_cancel(smx_activity_t synchro)
257 {
258   XBT_DEBUG("Cancel synchro %p", synchro);
259   simgrid::kernel::activity::Exec *exec = static_cast<simgrid::kernel::activity::Exec *>(synchro);
260
261   if (exec->surf_exec)
262     exec->surf_exec->cancel();
263 }
264
265 void SIMIX_execution_set_priority(smx_activity_t synchro, double priority)
266 {
267   simgrid::kernel::activity::Exec *exec = static_cast<simgrid::kernel::activity::Exec *>(synchro);
268   if(exec->surf_exec)
269     exec->surf_exec->setPriority(priority);
270 }
271
272 void SIMIX_execution_set_bound(smx_activity_t synchro, double bound)
273 {
274   simgrid::kernel::activity::Exec *exec = static_cast<simgrid::kernel::activity::Exec *>(synchro);
275   if(exec->surf_exec)
276     static_cast<simgrid::surf::CpuAction*>(exec->surf_exec)->setBound(bound);
277 }
278
279 void simcall_HANDLER_execution_wait(smx_simcall_t simcall, smx_activity_t synchro)
280 {
281   simgrid::kernel::activity::Exec *exec = static_cast<simgrid::kernel::activity::Exec *>(synchro);
282   XBT_DEBUG("Wait for execution of synchro %p, state %d", synchro, (int)synchro->state);
283
284   /* Associate this simcall to the synchro */
285   synchro->simcalls.push_back(simcall);
286   simcall->issuer->waiting_synchro = synchro;
287
288   /* set surf's synchro */
289   if (MC_is_active() || MC_record_replay_is_active()) {
290     synchro->state = SIMIX_DONE;
291     SIMIX_execution_finish(exec);
292     return;
293   }
294
295   /* If the synchro is already finished then perform the error handling */
296   if (synchro->state != SIMIX_RUNNING)
297     SIMIX_execution_finish(exec);
298 }
299
300 void SIMIX_execution_finish(simgrid::kernel::activity::Exec *exec)
301 {
302   for (smx_simcall_t simcall : exec->simcalls) {
303     switch (exec->state) {
304
305       case SIMIX_DONE:
306         /* do nothing, synchro done */
307         XBT_DEBUG("SIMIX_execution_finished: execution successful");
308         break;
309
310       case SIMIX_FAILED:
311         XBT_DEBUG("SIMIX_execution_finished: host '%s' failed", sg_host_get_name(simcall->issuer->host));
312         simcall->issuer->context->iwannadie = 1;
313         SMX_EXCEPTION(simcall->issuer, host_error, 0, "Host failed");
314         break;
315
316       case SIMIX_CANCELED:
317         XBT_DEBUG("SIMIX_execution_finished: execution canceled");
318         SMX_EXCEPTION(simcall->issuer, cancel_error, 0, "Canceled");
319         break;
320
321       default:
322         xbt_die("Internal error in SIMIX_execution_finish: unexpected synchro state %d",
323             (int)exec->state);
324     }
325     /* Fail the process if the host is down */
326     if (simcall->issuer->host->isOff())
327       simcall->issuer->context->iwannadie = 1;
328
329     simcall->issuer->waiting_synchro = nullptr;
330     simcall_execution_wait__set__result(simcall, exec->state);
331     SIMIX_simcall_answer(simcall);
332   }
333
334   /* We no longer need it */
335   exec->unref();
336 }
337
338 void SIMIX_set_category(smx_activity_t synchro, const char *category)
339 {
340   if (synchro->state != SIMIX_RUNNING)
341     return;
342
343   simgrid::kernel::activity::Exec *exec = dynamic_cast<simgrid::kernel::activity::Exec *>(synchro);
344   if (exec != nullptr) {
345     exec->surf_exec->setCategory(category);
346     return;
347   }
348
349   simgrid::kernel::activity::Comm *comm = dynamic_cast<simgrid::kernel::activity::Comm *>(synchro);
350   if (comm != nullptr) {
351     comm->surf_comm->setCategory(category);
352     return;
353   }
354 }