2 #include "Connection.hpp"
3 #include "ForkAndExec.hpp"
8 Server::Server(string binary_
, Server::argv_t args_
)
9 : binary
{move(binary_
)}
19 if (holds_alternative
<string
>(socket_or_port
)) {
20 unlink(get
<string
>(socket_or_port
).c_str());
24 static inline string
extractArg(const Server::arg_t
&arg_cont
, const string
&func_arg
) {
25 if (holds_alternative
<string
>(arg_cont
)) {
26 return get
<string
>(arg_cont
);
28 return get
<Server::arg_func_t
>(arg_cont
)(func_arg
);
32 static inline void pushArg(vector
<char *> &arr
, const string
&arg
) {
33 auto len
= arg
.size();
34 auto str
= arg
.data(), end
= str
+ len
+ 1;
35 auto ptr
= new char[len
+ 1];
40 optional
<string
> Server::handleArg(vector
<char *> &arr
, const string
&arg
, const arg_func_t
&next_arg
) {
42 if (arg
== "-p" || arg
== "--port") {
43 auto port
= next_arg(arg
);
47 socket_or_port
= stoi(port
);
49 } else if (arg
== "-s" || arg
== "--unix-socket") {
50 auto sock
= next_arg(arg
);
52 socket_or_port
= sock
;
59 vector
<char *> Server::createArgv() {
65 for (auto it
= args
.cbegin(); it
!= args
.cend(); ++it
) {
66 if (holds_alternative
<arg_t
>(*it
)) {
68 auto arg
= extractArg(get
<arg_t
>(*it
), binary
);
69 handleArg(arr
, arg
, [&it
](const string
&arg_
) {
70 return extractArg(get
<arg_t
>(*++it
), arg_
);
74 auto &[one
, two
] = get
<arg_pair_t
>(*it
);
75 auto arg_one
= extractArg(one
, binary
);
76 auto arg_two
= extractArg(two
, arg_one
);
78 auto next
= handleArg(arr
, arg_one
, [&arg_two
](const string
&) {
82 if (!next
.has_value()) {
83 pushArg(arr
, arg_two
);
88 arr
.push_back(nullptr);
93 optional
<Server::ChildProc
> Server::start() {
95 auto argv
= createArgv();
96 ForkAndExec fork_and_exec
{binary
.c_str(), argv
.data()};
98 pipe
= fork_and_exec
.createPipe();
99 pid
= fork_and_exec();
101 for (auto argp
: argv
) {
109 return ChildProc
{pid
, pipe
};
112 bool Server::isListening() {
115 if (holds_alternative
<string
>(socket_or_port
)) {
116 if (memcached_server_add_unix_socket(*memc
, get
<string
>(socket_or_port
).c_str())) {
120 if (memcached_server_add(*memc
, "localhost", get
<int>(socket_or_port
))) {
125 Malloced
stat(memcached_stat(*memc
, nullptr, nullptr));
126 if (!*stat
|| !stat
->pid
|| stat
->pid
!= pid
) {
133 bool Server::stop() {
137 if (signalled
[SIGTERM
]) {
138 return signal(SIGKILL
);
140 return signal(SIGTERM
);
144 bool Server::signal(int signo
) {
148 signalled
[signo
] += 1;
149 return 0 <= kill(pid
, signo
);
152 bool Server::check() {
156 bool Server::wait(int flags
) {
157 if (pid
&& pid
== waitpid(pid
, &status
, flags
)) {
158 if (drain().length()) {
159 cerr
<< "Ouput of " << *this << ":\n" << output
<< endl
;
172 bool Server::tryWait() {
173 return wait(WNOHANG
);
176 Server::Server(const Server
&s
) {
179 socket_or_port
= s
.socket_or_port
;
182 Server
&Server::operator=(const Server
&s
) {
185 socket_or_port
= s
.socket_or_port
;
189 pid_t
Server::getPid() const {
193 const string
&Server::getBinary() const {
197 const Server::argv_t
&Server::getArgs() const {
201 const socket_or_port_t
&Server::getSocketOrPort() const {
202 return socket_or_port
;
205 int Server::getPipe() const {
209 string
&Server::drain() {
212 char read_buf
[1<<12];
213 auto read_len
= read(pipe
, read_buf
, sizeof(read_buf
));
216 output
.append(read_buf
, read_len
);
219 if (read_len
== -1) {
224 perror("Server::drain read()");
227 #if EWOULDBLOCK != EAGAIN