#pragma once
-#include "WaitForConn.hpp"
+#include "common.hpp"
#include <csignal>
-#include <functional>
-#include <iostream>
-#include <string>
-#include <variant>
-#include <vector>
-
-using namespace std;
-
class Server {
- friend class Cluster;
-
public:
- using str_args_t = vector<string>;
- using dyn_args_t = unordered_map<string, function<string(string)>>;
- using socket_or_port_t = variant<string, int>;
-private:
- string binary;
- str_args_t str_args;
- dyn_args_t dyn_args;
- pid_t pid = 0;
+ friend class Cluster;
- int status = 0;
- unordered_map<int, unsigned> signalled;
- socket_or_port_t socket_or_port{11211};
+ using arg_func_t = function<string(string)>;
+ using arg_t = variant<string, arg_func_t>;
+ using arg_pair_t = pair<arg_t, arg_t>;
+ using argv_t = vector<variant<arg_t, arg_pair_t>>;
-public:
explicit
- Server(string &&binary_, str_args_t &&str_args_ = {}, dyn_args_t &&dyn_args_ = {})
- : binary{binary_}
- , str_args{str_args_}
- , dyn_args{dyn_args_}
- {}
-
- Server(string &&binary_, dyn_args_t &&dyn_args_)
- : binary{binary_}
- , str_args{}
- , dyn_args{dyn_args_}
- {}
-
- ~Server() {
- stop();
- wait();
- }
-
- Server &operator = (const Server &s) = default;
- Server(const Server &s) = default;
-
- Server &operator = (Server &&s) = default;
- Server(Server &&s) = default;
-
- pid_t getPid() const {
- return pid;
- }
-
- const string &getBinary() const {
- return binary;
- }
-
- const socket_or_port_t &getSocketOrPort() const {
- return socket_or_port;
- }
-
- optional<pid_t> start();
+ Server(string binary_ = "false", argv_t args_ = {});
+
+ ~Server();
+
+ Server(const Server &s);
+ Server &operator = (const Server &s);
+
+ Server(Server &&s) {
+ *this = move(s);
+ };
+ Server &operator = (Server &&s) {
+ binary = exchange(s.binary, "false");
+ args = exchange(s.args, {});
+ pid = exchange(s.pid, 0);
+ pipe = exchange(s.pipe, -1);
+ status = exchange(s.status, 0);
+ signalled = exchange(s.signalled, {});
+ socket_or_port = exchange(s.socket_or_port, {});
+ output = exchange(s.output, {});
+ return *this;
+ };
+
+ pid_t getPid() const;
+ int getPipe() const;
+ const string &getBinary() const;
+ const argv_t &getArgs() const;
+ const socket_or_port_t &getSocketOrPort() const;
+
+ struct ChildProc {
+ pid_t pid;
+ int pipe;
+ ChildProc(pid_t pid_, int pipe_)
+ : pid{pid_}
+ , pipe{pipe_}
+ {
+ }
+ };
+ optional<ChildProc> start();
bool stop();
bool signal(int signo = SIGTERM);
bool check();
- bool isListening(int max_timeout = 1000);
+ bool isListening();
bool wait(int flags = 0);
bool tryWait();
+ string &drain();
+
private:
- [[nodiscard]]
- auto createArgv();
+ string binary;
+ argv_t args;
+ pid_t pid = 0;
+ int pipe = -1;
+ int status = 0;
+ unordered_map<int, unsigned> signalled;
+ socket_or_port_t socket_or_port = 11211;
+ string output;
[[nodiscard]]
- optional<WaitForConn::conn_t> createSocket();
+ vector<char *> createArgv();
+ optional<string> handleArg(vector<char *> &arr, const string &arg, const arg_func_t &next_arg);
};
+
+inline ostream &operator << (ostream &out, const socket_or_port_t sop) {
+ if (holds_alternative<string>(sop)) {
+ out << get<string>(sop);
+ } else {
+ out << ":" << get<int>(sop);
+ }
+ return out;
+}
+
+inline ostream &operator << (ostream &out, const Server &server) {
+ out << "Server{binary=" << server.getBinary() << ",pid=" << server.getPid() << ",conn=" << server.getSocketOrPort() << "}";
+ return out;
+}