Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Extract assignment from expression.
[simgrid.git] / teshsuite / s4u / monkey-masterworkers / monkey-masterworkers.cpp
1 /* Copyright (c) 2007-2022. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 /* This is a version of the masterworkers that (hopefully) survives to the chaos monkey.
7  * It tests synchronous send/receive as well as synchronous computations.
8  *
9  * It is not written to be pleasant to read, but instead to resist the aggressions of the monkey:
10  * - Workers keep going until after a global variable `todo` reaches 0.
11  * - The master is a daemon that just sends infinitely tasks
12  *   (simgrid simulations stop as soon as all non-daemon actors are done).
13  * - The platform is created programmatically to remove path issues and control the problem size.
14  *
15  * Command-line configuration items:
16  * - host-count: how many actors to start (including the master
17  * - task-count: initial value of the `todo` global
18  * - deadline: time at which the simulation is known to be failed (to detect infinite loops).
19  *
20  * See the simgrid-monkey script for more information.
21  */
22
23 #include <simgrid/s4u.hpp>
24 #include <xbt/config.hpp>
25 #include <xbt/string.hpp>
26
27 namespace sg4 = simgrid::s4u;
28
29 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "Messages specific for this s4u example");
30
31 static simgrid::config::Flag<int> cfg_host_count{"host-count", "Host count (master on one, workers on the others)", 3};
32 static simgrid::config::Flag<double> cfg_deadline{"deadline", "When to fail the simulation (infinite loop detection)",
33                                                   120};
34 static simgrid::config::Flag<int> cfg_task_count{"task-count", "Amount of tasks that must be executed to succeed", 2};
35
36 int todo; // remaining amount of tasks to execute, a global variable
37 sg4::Mailbox* mailbox; // as a global to reduce the amount of simcalls during actor reboot
38
39 XBT_ATTRIB_NORETURN static void master()
40 {
41   double comp_size = 1e6;
42   long comm_size   = 1e6;
43   XBT_INFO("Master booting");
44   sg4::Actor::self()->daemonize();
45   sg4::this_actor::on_exit(
46       [](bool forcefully) { XBT_INFO("Master dying %s.", forcefully ? "forcefully" : "peacefully"); });
47
48   while (true) { // This is a daemon
49     xbt_assert(sg4::Engine::get_clock() < cfg_deadline,
50                "Failed to run all tasks in less than %d seconds. Is this an infinite loop?", (int)cfg_deadline);
51
52     auto payload = std::make_unique<double>(comp_size);
53     try {
54       XBT_INFO("Try to send a message");
55       mailbox->put(payload.get(), comm_size, 10.0);
56       payload.release();
57     } catch (const simgrid::TimeoutException&) {
58       XBT_INFO("Timeouted while sending a task");
59     } catch (const simgrid::NetworkFailureException&) {
60       XBT_INFO("Got a NetworkFailureException. Wait a second before starting again.");
61       sg4::this_actor::sleep_for(1);
62     }
63   }
64   THROW_IMPOSSIBLE;
65 }
66
67 static void worker(int id)
68 {
69   XBT_INFO("Worker booting");
70   sg4::this_actor::on_exit(
71       [id](bool forcefully) { XBT_INFO("worker %d dying %s.", id, forcefully ? "forcefully" : "peacefully"); });
72
73   while (todo > 0) {
74     xbt_assert(sg4::Engine::get_clock() < cfg_deadline,
75                "Failed to run all tasks in less than %d seconds. Is this an infinite loop?", (int)cfg_deadline);
76     try {
77       XBT_INFO("Waiting a message on %s", mailbox->get_cname());
78       auto payload = mailbox->get_unique<double>(10);
79       xbt_assert(payload != nullptr, "mailbox->get() failed");
80       double comp_size = *payload;
81       if (comp_size < 0) { /* - Exit when -1.0 is received */
82         XBT_INFO("I'm done. See you!");
83         break;
84       }
85       /*  - Otherwise, process the task */
86       XBT_INFO("Start execution...");
87       sg4::this_actor::execute(comp_size);
88       XBT_INFO("Execution complete.");
89       todo--;
90     } catch (const simgrid::TimeoutException&) {
91       XBT_INFO("Timeouted while getting a task.");
92     } catch (const simgrid::NetworkFailureException&) {
93       XBT_INFO("Got a NetworkFailureException. Wait a second before starting again.");
94       sg4::this_actor::sleep_for(1);
95     }
96   }
97 }
98
99 int main(int argc, char* argv[])
100 {
101   sg4::Engine e(&argc, argv);
102
103   XBT_INFO("host count: %d ", (int)cfg_host_count);
104
105   auto* rootzone = sg4::create_full_zone("root");
106   sg4::Host* main; // First host created, where the master will stay
107   std::vector<sg4::Host*> worker_hosts;
108
109   xbt_assert(cfg_host_count > 2, "You need at least 2 workers (i.e., 3 hosts) or the master will be auto-killed when "
110                                  "the only worker gets killed.");
111   for (int i = 0; i < cfg_host_count; i++) {
112     auto hostname = std::string("lilibeth ") + std::to_string(i);
113     auto* host    = rootzone->create_host(hostname, 1e9);
114     if (i == 0) {
115       main = host;
116     } else {
117       sg4::LinkInRoute link(rootzone->create_link(hostname, "1MBps")->set_latency("24us")->seal());
118       rootzone->add_route(main->get_netpoint(), host->get_netpoint(), nullptr, nullptr, {link}, true);
119       worker_hosts.push_back(host);
120     }
121   }
122   rootzone->seal();
123   sg4::Engine::on_platform_created(); // FIXME this should not be necessary
124
125   sg4::Actor::create("master", main, master)->set_auto_restart(true);
126   int id = 0;
127   for (auto* h : worker_hosts) {
128     sg4::Actor::create("worker", h, worker, id)->set_auto_restart(true);
129     id++;
130   }
131
132   todo = cfg_task_count;
133   xbt_assert(todo > 0, "Please give more than %d tasks to run", todo);
134   mailbox = sg4::Mailbox::by_name("mailbox");
135
136   e.run();
137
138   XBT_INFO("WE SURVIVED!");
139   return 0;
140 }