1 /*
2 Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #ifndef atrt_config_hpp
26 #define atrt_config_hpp
27
28 #include <ndb_global.h>
29 #include <Vector.hpp>
30 #include <BaseString.hpp>
31 #include <NdbAutoPtr.hpp>
32 #include <Logger.hpp>
33 #include <mgmapi.h>
34 #include <CpcClient.hpp>
35 #include <Properties.hpp>
36 #include <mysql.h>
37 #include <my_sys.h>
38 #include <my_getopt.h>
39 #ifdef HAVE_MY_DEFAULT_H
40 #include <my_default.h>
41 #endif
42 #include <my_dir.h>
43
44 enum ErrorCodes
45 {
46 ERR_OK = 0,
47 ERR_NDB_FAILED = 101,
48 ERR_SERVERS_FAILED = 102,
49 ERR_MAX_TIME_ELAPSED = 103,
50 ERR_COMMAND_FAILED = 104,
51 ERR_FAILED_TO_START = 105
52 };
53
54 struct atrt_host
55 {
56 unsigned m_index;
57 BaseString m_user;
58 BaseString m_basedir;
59 BaseString m_hostname;
60 SimpleCpcClient * m_cpcd;
61 Vector<struct atrt_process*> m_processes;
62 };
63
64 struct atrt_options
65 {
66 enum Feature {
67 AO_REPLICATION = 1,
68 AO_NDBCLUSTER = 2
69 };
70
71 int m_features;
72 Properties m_loaded;
73 Properties m_generated;
74 };
75
76 struct atrt_process
77 {
78 unsigned m_index;
79 struct atrt_host * m_host;
80 struct atrt_cluster * m_cluster;
81
82 enum Type {
83 AP_ALL = 255
84 ,AP_NDBD = 1
85 ,AP_NDB_API = 2
86 ,AP_NDB_MGMD = 4
87 ,AP_MYSQLD = 16
88 ,AP_CLIENT = 32
89 ,AP_CLUSTER = 256 // Used for options parsing for "cluster" options
90 } m_type;
91
92 SimpleCpcClient::Process m_proc;
93
94 NdbMgmHandle m_ndb_mgm_handle; // if type == ndb_mgm
95 atrt_process * m_mysqld; // if type == client
96 atrt_process * m_rep_src; // if type == mysqld
97 Vector<atrt_process*> m_rep_dst; // if type == mysqld
98 MYSQL m_mysql; // if type == mysqld
99 atrt_options m_options;
100 uint m_nodeid; // if m_fix_nodeid
101
102 struct {
103 bool m_saved;
104 SimpleCpcClient::Process m_proc;
105 } m_save;
106
107 };
108
109 struct atrt_cluster
110 {
111 BaseString m_name;
112 BaseString m_dir;
113 Vector<atrt_process*> m_processes;
114 atrt_options m_options;
115 uint m_next_nodeid; // if m_fix_nodeid
116 };
117
118 struct atrt_config
119 {
120 bool m_generated;
121 BaseString m_key;
122 BaseString m_replication;
123 Vector<atrt_host*> m_hosts;
124 Vector<atrt_cluster*> m_clusters;
125 Vector<atrt_process*> m_processes;
126 };
127
128 struct atrt_testcase
129 {
130 bool m_report;
131 bool m_run_all;
132 time_t m_max_time;
133 BaseString m_name;
134 BaseString m_mysqld_options;
135
136 struct Command
137 {
138 atrt_process::Type m_cmd_type;
139 BaseString m_exe;
140 BaseString m_args;
141 } m_cmd; // Todo make array of these...
142 };
143
144 extern Logger g_logger;
145
146 bool parse_args(int argc, char** argv);
147 bool setup_config(atrt_config&, const char * mysqld);
148 bool configure(atrt_config&, int setup);
149 bool setup_directories(atrt_config&, int setup);
150 bool setup_files(atrt_config&, int setup, int sshx);
151
152 bool deploy(int, atrt_config&);
153 bool sshx(atrt_config&, unsigned procmask);
154 bool start(atrt_config&, unsigned procmask);
155
156 bool remove_dir(const char *, bool incl = true);
157 bool connect_hosts(atrt_config&);
158 bool connect_ndb_mgm(atrt_config&);
159 bool wait_ndb(atrt_config&, int ndb_mgm_node_status);
160 bool start_processes(atrt_config&, int);
161 bool stop_processes(atrt_config&, int);
162 bool update_status(atrt_config&, int);
163 int is_running(atrt_config&, int);
164 bool gather_result(atrt_config&, int * result);
165
166 bool read_test_case(FILE *, atrt_testcase&, int& line);
167 bool setup_test_case(atrt_config&, const atrt_testcase&);
168
169 bool setup_hosts(atrt_config&);
170
171 bool do_command(atrt_config& config);
172
173 bool start_process(atrt_process & proc);
174 bool stop_process(atrt_process & proc);
175
176 bool connect_mysqld(atrt_process & proc);
177 bool disconnect_mysqld(atrt_process & proc);
178
179 /**
180 * check configuration if any changes has been
181 * done for the duration of the latest running test
182 * if so, return true, and reset those changes
183 * (true, indicates that a restart is needed to actually
184 * reset the running processes)
185 */
186 bool reset_config(atrt_config&);
187
188 NdbOut&
189 operator<<(NdbOut& out, const atrt_process& proc);
190
191 /**
192 * SQL
193 */
194 bool setup_db(atrt_config&);
195
196 /**
197 * Global variables...
198 */
199 extern Logger g_logger;
200
201 extern const char * g_cwd;
202 extern const char * g_my_cnf;
203 extern const char * g_user;
204 extern const char * g_basedir;
205 extern const char * g_prefix;
206 extern const char * g_prefix1;
207 extern int g_baseport;
208 extern int g_fqpn;
209 extern int g_fix_nodeid;
210 extern int g_default_ports;
211 extern int g_restart;
212
213 extern const char * g_clusters;
214
215 /**
216 * Since binaries move location between 5.1 and 5.5
217 * we keep full path to them here
218 */
219 char * find_bin_path(const char * basename);
220 char * find_bin_path(const char * prefix, const char * basename);
221 extern const char * g_ndb_mgmd_bin_path;
222 extern const char * g_ndbd_bin_path;
223 extern const char * g_ndbmtd_bin_path;
224 extern const char * g_mysqld_bin_path;
225 extern const char * g_mysql_install_db_bin_path;
226 extern const char * g_libmysqlclient_so_path;
227
228 extern const char * g_search_path[];
229
230 #ifdef _WIN32
231 #include <direct.h>
232
lstat(const char * name,struct stat * buf)233 inline int lstat(const char *name, struct stat *buf) {
234 return stat(name, buf);
235 }
236
S_ISREG(int x)237 inline int S_ISREG(int x) {
238 return x & _S_IFREG;
239 }
240
S_ISDIR(int x)241 inline int S_ISDIR(int x) {
242 return x & _S_IFDIR;
243 }
244
245 #endif
246
247
248 /* in-place replace */
replace_chars(char * str,char from,char to)249 static inline char* replace_chars(char *str, char from, char to)
250 {
251 int i;
252
253 for(i = 0; str[i]; i++) {
254 if(i && str[i]==from && str[i-1]!=' ') {
255 str[i]=to;
256 }
257 }
258 return str;
259 }
260
replace_chars(BaseString & bs,char from,char to)261 static inline BaseString &replace_chars(BaseString &bs, char from, char to)
262 {
263 replace_chars((char*)bs.c_str(), from, to);
264 return bs;
265 }
to_native(BaseString & bs)266 static inline BaseString &to_native(BaseString &bs) {
267 return replace_chars(bs, DIR_SEPARATOR[0]=='/'?'\\':'/', DIR_SEPARATOR[0]);
268 }
to_fwd_slashes(BaseString & bs)269 static inline BaseString &to_fwd_slashes(BaseString &bs) {
270 return replace_chars(bs, '\\', '/');
271 }
to_fwd_slashes(char * bs)272 static inline char* to_fwd_slashes(char* bs) {
273 return replace_chars(bs, '\\', '/');
274 }
275
276 //you must free() the result
replace_drive_letters(const char * path)277 static inline char* replace_drive_letters(const char* path) {
278
279 int i, j;
280 int count; // number of ':'s in path
281 char *retval; // return value
282 const char cygdrive[] = "/cygdrive";
283 size_t cyglen = strlen(cygdrive), retval_len;
284
285 for(i = 0, count = 0; path[i]; i++) {
286 count += path[i] == ':';
287 }
288 retval_len = strlen(path) + count * cyglen + 1;
289 retval = (char*)malloc(retval_len);
290
291 for(i = j = 0; path[i]; i++) {
292 if(path[i] && path[i+1]) {
293 if( (!i || isspace(path[i-1]) || ispunct(path[i-1])) && path[i+1] == ':')
294 {
295 require(path[i+2] == '/');
296 j += BaseString::snprintf(retval + j, retval_len - 1, "%s/%c", cygdrive, path[i]);
297 i++;
298 continue;
299 }
300 }
301 retval[j++] = path[i];
302 }
303 retval[j] = 0;
304
305 return retval;
306 }
307
sh(const char * script)308 static inline int sh(const char *script){
309
310 #ifdef _WIN32
311 g_logger.debug("sh('%s')", script);
312
313 /*
314 Running sh script on Windows
315 1) Write the command to run into temporary file
316 2) Run the temporary file with 'sh <temp_file_name>'
317 */
318
319 char tmp_path[MAX_PATH];
320 if (GetTempPath(sizeof(tmp_path), tmp_path) == 0)
321 {
322 g_logger.error( "GetTempPath failed, error: %d", GetLastError());
323 return -1;
324 }
325
326 char tmp_file[MAX_PATH];
327 if (GetTempFileName(tmp_path, "sh_", 0, tmp_file) == 0)
328 {
329 g_logger.error( "GetTempFileName failed, error: %d", GetLastError());
330 return -1;
331 }
332
333 FILE* fp = fopen(tmp_file, "w");
334 if (fp == NULL)
335 {
336 g_logger.error( "Cannot open file '%s', error: %d", tmp_file, errno);
337 return -1;
338 }
339
340 // cygwin'ify the script and write it to temp file
341 {
342 char* cygwin_script = replace_drive_letters(script);
343 g_logger.debug(" - cygwin_script: '%s' ", cygwin_script);
344 fprintf(fp, "%s", cygwin_script);
345 free(cygwin_script);
346 }
347
348 fclose(fp);
349
350 // Run the temp file with "sh"
351 BaseString command;
352 command.assfmt("sh %s", tmp_file);
353 g_logger.debug(" - running '%s' ", command.c_str());
354
355 int ret = system(command.c_str());
356 if (ret == 0)
357 g_logger.debug(" - OK!");
358 else
359 g_logger.warning("Running the command '%s' as '%s' failed, ret: %d",
360 script, command.c_str(), ret);
361
362 // Remove the temp file
363 unlink(tmp_file);
364
365 return ret;
366
367 #else
368
369 return system(script);
370
371 #endif
372
373 }
374 #endif
375