fix segfault: dtrace build on solaris
[m6w6/libmemcached] / test / lib / Server.hpp
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #pragma once
17
18 #include "common.hpp"
19
20 #include <csignal>
21 #include <unordered_map>
22
23 class Server {
24 public:
25 friend class Cluster;
26
27 using arg_func_t = function<string(string)>;
28 using arg_t = variant<string, arg_func_t>;
29 using arg_pair_t = pair<arg_t, arg_t>;
30 using argv_t = vector<variant<arg_t, arg_pair_t>>;
31
32 explicit Server(string binary_ = "false", argv_t args_ = {});
33
34 ~Server();
35
36 Server(const Server &s);
37 Server &operator=(const Server &s);
38
39 Server(Server &&s) noexcept {
40 *this = move(s);
41 };
42 Server &operator=(Server &&s) noexcept {
43 binary = exchange(s.binary, "false");
44 args = exchange(s.args, {});
45 pid = exchange(s.pid, 0);
46 pipe = exchange(s.pipe, -1);
47 status = exchange(s.status, 0);
48 signalled = exchange(s.signalled, {});
49 socket_or_port = exchange(s.socket_or_port, {});
50 output = exchange(s.output, {});
51 return *this;
52 };
53
54 pid_t getPid() const;
55 int getPipe() const;
56 const string &getBinary() const;
57 const argv_t &getArgs() const;
58 const socket_or_port_t &getSocketOrPort() const;
59
60 struct ChildProc {
61 pid_t pid;
62 int pipe;
63 ChildProc(pid_t pid_, int pipe_)
64 : pid{pid_}
65 , pipe{pipe_} {}
66 };
67 optional<ChildProc> start();
68 bool stop();
69
70 bool signal(int signo = SIGTERM);
71 bool check();
72 bool isListening() const;
73 bool ensureListening();
74
75 bool wait(int flags = 0);
76 bool tryWait();
77 string &drain();
78
79 private:
80 string binary;
81 argv_t args;
82 bool sasl = false;
83 pid_t pid = 0;
84 int pipe = -1;
85 int status = 0;
86 unordered_map<int, unsigned> signalled;
87 socket_or_port_t socket_or_port = 11211;
88 string output;
89
90 [[nodiscard]] vector<char *> createArgv();
91 optional<string> handleArg(vector<char *> &arr, const string &arg, const arg_func_t &next_arg);
92 };
93
94 inline ostream &operator<<(ostream &out, const socket_or_port_t &sop) {
95 if (holds_alternative<string>(sop)) {
96 out << get<string>(sop);
97 } else {
98 out << ":" << get<int>(sop);
99 }
100 return out;
101 }
102
103 inline ostream &operator<<(ostream &out, const Server &server) {
104 out << "Server{binary=" << server.getBinary() << ",pid=" << server.getPid()
105 << ",conn=" << server.getSocketOrPort() << "}";
106 return out;
107 }