5d2ab42a7eb3e5f42fbf18078b3099e086d99bb1
[awesomized/libmemcached] / testing / lib / Cluster.cpp
1 #include "Cluster.hpp"
2
3 #include <sys/wait.h>
4
5 Cluster::Cluster(Server &&serv, uint16_t cnt)
6 : count{cnt}
7 , proto{forward<Server>(serv)}
8 {
9 if (!cnt) {
10 count = thread::hardware_concurrency()/2 ?: 4;
11 }
12 reset();
13 }
14
15 Cluster::~Cluster() {
16 stop();
17 wait();
18 }
19
20 const vector<Server> &Cluster::getServers() const {
21 return cluster;
22 }
23
24 void Cluster::reset() {
25 pids.clear();
26 cluster.clear();
27 for (int i = 0; i < count; ++i) {
28 cluster.push_back(proto);
29 }
30 }
31
32 bool Cluster::start() {
33 bool started = true;
34
35 for (auto &server : cluster) {
36 auto pid = server.start();
37 if (pid.has_value()) {
38 pids[*pid] = &server;
39 } else {
40 started = false;
41 }
42 }
43
44 return started;
45 }
46
47 void Cluster::stop() {
48 for (auto &server : cluster) {
49 // no cookies for memcached; TERM is just too slow
50 server.signal(SIGKILL);
51 }
52 }
53
54 bool Cluster::isStopped() {
55 for (auto &server : cluster) {
56 if (server.getPid() && !server.tryWait()) {
57 return false;
58 }
59 }
60 return true;
61 }
62
63 bool Cluster::isListening() {
64 for (auto &server : cluster) {
65 if (!server.isListening()) {
66 // zombie?
67 auto old_pid = server.getPid();
68 if (server.tryWait()) {
69 pids.erase(old_pid);
70 auto pid = server.start();
71 if (pid.has_value()) {
72 pids[*pid] = &server;
73 }
74 }
75 return server.isListening();
76 }
77 }
78
79 return true;
80 }
81
82 void Cluster::wait() {
83 siginfo_t inf;
84
85 while (!isStopped()) {
86 if (waitid(P_ALL, 0, &inf, WEXITED | WNOWAIT)) {
87 perror("Cluster::wait waitid()");
88 return;
89 }
90
91 auto server = pids.find(inf.si_pid);
92 if (server != pids.end()) {
93 server->second->wait();
94 }
95 }
96 }
97