Merge in build.
[m6w6/libmemcached] / libtest / server.h
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * libtest
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #pragma once
23
24 #include <libtest/cmdline.h>
25
26 #include <cassert>
27 #include <cstdio>
28 #include <cstring>
29 #include <netdb.h>
30 #include <netinet/in.h>
31 #include <string>
32 #include <unistd.h>
33 #include <vector>
34
35 namespace libtest {
36
37 struct Server {
38 private:
39 typedef std::vector< std::pair<std::string, std::string> > Options;
40
41 private:
42 bool _is_socket;
43 std::string _socket;
44 std::string _sasl;
45 std::string _pid_file;
46 std::string _log_file;
47 std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
48 std::string _running; // Current string being used for system()
49 pid_t _pid;
50
51 protected:
52 in_port_t _port;
53 std::string _hostname;
54 std::string _extra_args;
55
56 public:
57 Server(const std::string& hostname, const in_port_t port_arg, const bool is_socket_arg= false);
58
59 virtual ~Server();
60
61 virtual const char *name()= 0;
62 virtual const char *executable()= 0;
63 virtual const char *daemon_file_option()= 0;
64 virtual bool is_libtool()= 0;
65
66 virtual bool has_socket_file_option() const
67 {
68 return false;
69 }
70
71 virtual void socket_file_option(Application& app, const std::string& socket_arg)
72 {
73 if (socket_arg.empty() == false)
74 {
75 std::string buffer("--socket=");
76 buffer+= socket_arg;
77 app.add_option(buffer);
78 }
79 }
80
81 virtual bool has_log_file_option() const
82 {
83 return false;
84 }
85
86 virtual void log_file_option(Application& app, const std::string& arg)
87 {
88 if (arg.empty() == false)
89 {
90 std::string buffer("--log-file=");
91 buffer+= arg;
92 app.add_option(buffer);
93 }
94 }
95
96 virtual void pid_file_option(Application& app, const std::string& arg)
97 {
98 if (arg.empty() == false)
99 {
100 std::string buffer("--pid-file=");
101 buffer+= arg;
102 app.add_option(buffer);
103 }
104 }
105
106 virtual bool has_port_option() const
107 {
108 return false;
109 }
110
111 virtual void port_option(Application& app, in_port_t arg)
112 {
113 if (arg > 0)
114 {
115 char buffer[1024];
116 snprintf(buffer, sizeof(buffer), "--port=%d", int(arg));
117 app.add_option(buffer);
118 }
119 }
120
121 virtual bool broken_socket_cleanup()
122 {
123 return false;
124 }
125
126 virtual bool broken_pid_file()
127 {
128 return false;
129 }
130
131 const std::string& pid_file() const
132 {
133 return _pid_file;
134 }
135
136 const std::string& base_command() const
137 {
138 return _base_command;
139 }
140
141 const std::string& log_file() const
142 {
143 return _log_file;
144 }
145
146 const std::string& hostname() const
147 {
148 return _hostname;
149 }
150
151 const std::string& socket() const
152 {
153 return _socket;
154 }
155
156 bool has_socket() const
157 {
158 return _is_socket;
159 }
160
161 bool cycle();
162
163 virtual bool ping()= 0;
164
165 virtual pid_t get_pid(bool error_is_ok= false)= 0;
166
167 virtual bool build(size_t argc, const char *argv[])= 0;
168
169 void add_option(const std::string&);
170 void add_option(const std::string&, const std::string&);
171
172 in_port_t port() const
173 {
174 return _port;
175 }
176
177 bool has_port() const
178 {
179 return (_port != 0);
180 }
181
182 virtual bool has_syslog() const
183 {
184 return false;
185 }
186
187 // Reset a server if another process has killed the server
188 void reset()
189 {
190 _pid= -1;
191 _pid_file.clear();
192 _log_file.clear();
193 }
194
195 bool args(Application&);
196
197 pid_t pid();
198
199 pid_t pid() const
200 {
201 return _pid;
202 }
203
204 bool has_pid() const
205 {
206 return (_pid > 1);
207 }
208
209 bool wait_for_pidfile() const;
210
211 bool check_pid(pid_t pid_arg) const
212 {
213 return (pid_arg > 1);
214 }
215
216 bool is_socket() const
217 {
218 return _hostname[0] == '/';
219 }
220
221 const std::string running() const
222 {
223 return _running;
224 }
225
226 std::string log_and_pid();
227
228 bool kill(pid_t pid_arg);
229 bool start();
230 bool command(libtest::Application& app);
231
232 protected:
233 bool set_pid_file();
234 Options _options;
235
236 private:
237 bool is_helgrind() const;
238 bool is_valgrind() const;
239 bool is_debug() const;
240 bool set_log_file();
241 bool set_socket_file();
242 void reset_pid();
243 };
244
245 std::ostream& operator<<(std::ostream& output, const libtest::Server &arg);
246
247 } // namespace libtest
248
249