MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
setup.cpp
1 /*
2  Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
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 as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include "atrt.hpp"
19 #include <ndb_global.h>
20 #include <util/ndb_opts.h>
21 #include <util/NdbOut.hpp>
22 #include <util/BaseString.hpp>
23 
24 extern int g_mt;
25 extern int g_mt_rr;
26 
27 static atrt_host * find(const char * hostname, Vector<atrt_host*>&);
28 static bool load_process(atrt_config&, atrt_cluster&, atrt_process::Type,
29  unsigned idx, const char * hostname);
30 static bool load_options(int argc, char** argv, int type, atrt_options&);
31 
32 enum {
33  PO_NDB = atrt_options::AO_NDBCLUSTER
34 
35  ,PO_REP_SLAVE = 256
36  ,PO_REP_MASTER = 512
37  ,PO_REP = (atrt_options::AO_REPLICATION | PO_REP_SLAVE | PO_REP_MASTER)
38 };
39 
41 {
42  const char * name;
43  int type;
44  int options;
45 };
46 
47 static
48 struct proc_option f_options[] = {
49  { "--FileSystemPath=", atrt_process::AP_NDBD, 0 }
50  ,{ "--PortNumber=", atrt_process::AP_NDB_MGMD, 0 }
51  ,{ "--datadir=", atrt_process::AP_MYSQLD, 0 }
52  ,{ "--socket=", atrt_process::AP_MYSQLD | atrt_process::AP_CLIENT, 0 }
53  ,{ "--port=", atrt_process::AP_MYSQLD | atrt_process::AP_CLIENT, 0 }
54  ,{ "--host=", atrt_process::AP_CLIENT, 0 }
55  ,{ "--server-id=", atrt_process::AP_MYSQLD, PO_REP }
56  ,{ "--log-bin", atrt_process::AP_MYSQLD, PO_REP_MASTER }
57  ,{ "--master-host=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
58  ,{ "--master-port=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
59  ,{ "--master-user=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
60  ,{ "--master-password=", atrt_process::AP_MYSQLD, PO_REP_SLAVE }
61  ,{ "--ndb-connectstring=", atrt_process::AP_MYSQLD | atrt_process::AP_CLUSTER
62  ,PO_NDB }
63  ,{ "--ndbcluster", atrt_process::AP_MYSQLD, PO_NDB }
64  ,{ 0, 0, 0 }
65 };
66 const char * ndbcs = "--ndb-connectstring=";
67 
68 bool
69 setup_config(atrt_config& config, const char* atrt_mysqld)
70 {
71  BaseString tmp(g_clusters);
72 
73  if (atrt_mysqld)
74  {
75  tmp.appfmt(",.atrt");
76  }
77  Vector<BaseString> clusters;
78  tmp.split(clusters, ",");
79 
80  bool fqpn = clusters.size() > 1 || g_fqpn;
81 
82  size_t j,k;
83  for (size_t i = 0; i<clusters.size(); i++)
84  {
85  struct atrt_cluster *cluster = new atrt_cluster;
86  config.m_clusters.push_back(cluster);
87 
88  cluster->m_name = clusters[i];
89  cluster->m_options.m_features = 0;
90  if (fqpn)
91  {
92  cluster->m_dir.assfmt("cluster%s/", cluster->m_name.c_str());
93  }
94  else
95  {
96  cluster->m_dir = "";
97  }
98  cluster->m_next_nodeid= 1;
99 
100  int argc = 1;
101  const char * argv[] = { "atrt", 0, 0 };
102 
103  BaseString buf;
104  buf.assfmt("--defaults-group-suffix=%s", clusters[i].c_str());
105  argv[argc++] = buf.c_str();
106  char ** tmp = (char**)argv;
107  const char *groups[] = { "cluster_config", 0 };
108  int ret = load_defaults(g_my_cnf, groups, &argc, &tmp);
109  if (ret)
110  {
111  g_logger.error("Unable to load defaults for cluster: %s",
112  clusters[i].c_str());
113  return false;
114  }
115 
116  struct
117  {
118  atrt_process::Type type;
119  const char * name;
120  const char * value;
121  } proc_args[] = {
122  { atrt_process::AP_NDB_MGMD, "--ndb_mgmd=", 0 },
123  { atrt_process::AP_NDBD, "--ndbd=", 0 },
124  { atrt_process::AP_NDB_API, "--ndbapi=", 0 },
125  { atrt_process::AP_NDB_API, "--api=", 0 },
126  { atrt_process::AP_MYSQLD, "--mysqld=", 0 },
127  { atrt_process::AP_ALL, 0, 0}
128  };
129 
133  for (j = 0; j<(size_t)argc; j++)
134  {
135  if (my_getopt_is_args_separator(tmp[j])) /* skip arguments separator */
136  continue;
137  for (k = 0; proc_args[k].name; k++)
138  {
139  if (!strncmp(tmp[j], proc_args[k].name, strlen(proc_args[k].name)))
140  {
141  proc_args[k].value = tmp[j] + strlen(proc_args[k].name);
142  break;
143  }
144  }
145  }
146 
147  if (strcmp(clusters[i].c_str(), ".atrt") == 0)
148  {
152  proc_args[0].value = 0;
153  proc_args[1].value = 0;
154  proc_args[2].value = 0;
155  proc_args[3].value = 0;
156  proc_args[4].value = atrt_mysqld;
157  }
158 
162  for (j = 0; proc_args[j].name; j++)
163  {
164  if (proc_args[j].value)
165  {
166  BaseString tmp(proc_args[j].value);
167  Vector<BaseString> list;
168  tmp.split(list, ",");
169  for (k = 0; k<list.size(); k++)
170  if (!load_process(config, *cluster, proc_args[j].type,
171  k + 1, list[k].c_str()))
172  return false;
173  }
174  }
175 
176  {
180  int argc = 1;
181  const char * argv[] = { "atrt", 0, 0 };
182  argv[argc++] = buf.c_str();
183  const char *groups[] = { "mysql_cluster", 0 };
184  char ** tmp = (char**)argv;
185  ret = load_defaults(g_my_cnf, groups, &argc, &tmp);
186 
187  if (ret)
188  {
189  g_logger.error("Unable to load defaults for cluster: %s",
190  clusters[i].c_str());
191  return false;
192  }
193 
194  load_options(argc, tmp, atrt_process::AP_CLUSTER, cluster->m_options);
195  }
196  }
197  return true;
198 }
199 
200 static
201 atrt_host *
202 find(const char * hostname, Vector<atrt_host*> & hosts){
203  for (size_t i = 0; i<hosts.size(); i++){
204  if (hosts[i]->m_hostname == hostname){
205  return hosts[i];
206  }
207  }
208 
209  atrt_host* host = new atrt_host;
210  host->m_index = hosts.size();
211  host->m_cpcd = new SimpleCpcClient(hostname, 1234);
212  host->m_basedir = g_basedir;
213  host->m_user = g_user;
214  host->m_hostname = hostname;
215  hosts.push_back(host);
216  return host;
217 }
218 
219 static
220 bool
221 load_process(atrt_config& config, atrt_cluster& cluster,
222  atrt_process::Type type,
223  unsigned idx,
224  const char * hostname)
225 {
226  atrt_host * host_ptr = find(hostname, config.m_hosts);
227  atrt_process *proc_ptr = new atrt_process;
228 
229  const unsigned proc_no = (unsigned)config.m_processes.size();
230  config.m_processes.push_back(proc_ptr);
231  host_ptr->m_processes.push_back(proc_ptr);
232  cluster.m_processes.push_back(proc_ptr);
233 
234  atrt_process& proc = *proc_ptr;
235 
236  proc.m_index = idx;
237  proc.m_type = type;
238  proc.m_host = host_ptr;
239  proc.m_save.m_saved = false;
240  proc.m_nodeid= -1;
241  proc.m_cluster = &cluster;
242  proc.m_options.m_features = 0;
243  proc.m_rep_src = 0;
244  proc.m_proc.m_id = -1;
245  proc.m_proc.m_type = "temporary";
246  proc.m_proc.m_owner = "atrt";
247  proc.m_proc.m_group = cluster.m_name.c_str();
248  proc.m_proc.m_stdout = "log.out";
249  proc.m_proc.m_stderr = "2>&1";
250  proc.m_proc.m_runas = proc.m_host->m_user;
251  proc.m_proc.m_ulimit = "c:unlimited";
252  proc.m_proc.m_env.assfmt("MYSQL_BASE_DIR=%s", g_prefix);
253  proc.m_proc.m_env.appfmt(" MYSQL_HOME=%s", g_basedir);
254  proc.m_proc.m_env.appfmt(" ATRT_PID=%u", (unsigned)proc_no);
255  proc.m_proc.m_shutdown_options = "";
256 
257  int argc = 1;
258  const char * argv[] = { "atrt", 0, 0 };
259 
260  BaseString buf[10];
261  char ** tmp = (char**)argv;
262  const char *groups[] = { 0, 0, 0, 0 };
263  switch(type){
264  case atrt_process::AP_NDB_MGMD:
265  proc.m_nodeid= cluster.m_next_nodeid++; // always specify node-id
266 
267  groups[0] = "cluster_config";
268  buf[1].assfmt("cluster_config.ndb_mgmd.%u", idx);
269  groups[1] = buf[1].c_str();
270  buf[0].assfmt("--defaults-group-suffix=%s", cluster.m_name.c_str());
271  argv[argc++] = buf[0].c_str();
272  break;
273  case atrt_process::AP_NDBD:
274  if (g_fix_nodeid)
275  proc.m_nodeid= cluster.m_next_nodeid++;
276 
277  groups[0] = "cluster_config";
278  buf[1].assfmt("cluster_config.ndbd.%u", idx);
279  groups[1] = buf[1].c_str();
280  buf[0].assfmt("--defaults-group-suffix=%s", cluster.m_name.c_str());
281  argv[argc++] = buf[0].c_str();
282  break;
283  case atrt_process::AP_MYSQLD:
284  if (g_fix_nodeid)
285  proc.m_nodeid= cluster.m_next_nodeid++;
286 
287  groups[0] = "mysqld";
288  groups[1] = "mysql_cluster";
289  buf[0].assfmt("--defaults-group-suffix=.%u%s",idx,cluster.m_name.c_str());
290  argv[argc++] = buf[0].c_str();
291  break;
292  case atrt_process::AP_CLIENT:
293  buf[0].assfmt("client.%u%s", idx, cluster.m_name.c_str());
294  groups[0] = buf[0].c_str();
295  break;
296  case atrt_process::AP_NDB_API:
297  if (g_fix_nodeid)
298  proc.m_nodeid= cluster.m_next_nodeid++;
299  break;
300  default:
301  g_logger.critical("Unhandled process type: %d", type);
302  return false;
303  }
304 
305  int ret = load_defaults(g_my_cnf, groups, &argc, &tmp);
306  if (ret)
307  {
308  g_logger.error("Unable to load defaults for cluster: %s",
309  cluster.m_name.c_str());
310  return false;
311  }
312 
313  load_options(argc, tmp, type, proc.m_options);
314 
315  BaseString dir;
316  dir.assfmt("%s/%s",
317  proc.m_host->m_basedir.c_str(),
318  cluster.m_dir.c_str());
319 
320  switch(type){
321  case atrt_process::AP_NDB_MGMD:
322  {
323  proc.m_proc.m_name.assfmt("%u-%s", proc_no, "ndb_mgmd");
324  proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndb_mgmd");
325  proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
326  proc.m_host->m_basedir.c_str());
327  proc.m_proc.m_args.appfmt(" --defaults-group-suffix=%s",
328  cluster.m_name.c_str());
329  proc.m_proc.m_args.append(" --nodaemon --mycnf");
330  proc.m_proc.m_args.appfmt(" --ndb-nodeid=%u", proc.m_nodeid);
331  proc.m_proc.m_cwd.assfmt("%sndb_mgmd.%u", dir.c_str(), proc.m_index);
332  proc.m_proc.m_args.appfmt(" --configdir=%s", proc.m_proc.m_cwd.c_str());
333  proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=%s",
334  cluster.m_name.c_str());
335  break;
336  }
337  case atrt_process::AP_NDBD:
338  {
339  if (g_mt == 0 || (g_mt == 1 && ((g_mt_rr++) & 1) == 0))
340  {
341  proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndbd");
342  }
343  else
344  {
345  proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndbmtd");
346  }
347 
348  proc.m_proc.m_name.assfmt("%u-%s", proc_no, "ndbd");
349  proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
350  proc.m_host->m_basedir.c_str());
351  proc.m_proc.m_args.appfmt(" --defaults-group-suffix=%s",
352  cluster.m_name.c_str());
353  proc.m_proc.m_args.append(" --nodaemon --initial -n");
354  if (g_fix_nodeid)
355  proc.m_proc.m_args.appfmt(" --ndb-nodeid=%u", proc.m_nodeid);
356  proc.m_proc.m_cwd.assfmt("%sndbd.%u", dir.c_str(), proc.m_index);
357  proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=%s",
358  cluster.m_name.c_str());
359  break;
360  }
361  case atrt_process::AP_MYSQLD:
362  {
363  proc.m_proc.m_name.assfmt("%u-%s", proc_no, "mysqld");
364  proc.m_proc.m_path.assign(g_prefix).append("/libexec/mysqld");
365  proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
366  proc.m_host->m_basedir.c_str());
367  proc.m_proc.m_args.appfmt(" --defaults-group-suffix=.%d%s",
368  proc.m_index,
369  cluster.m_name.c_str());
370  proc.m_proc.m_args.append(" --core-file");
371  if (g_fix_nodeid)
372  proc.m_proc.m_args.appfmt(" --ndb-nodeid=%d", proc.m_nodeid);
373 
374  // Add ndb connect string
375  const char * val;
376  if (cluster.m_options.m_loaded.get(ndbcs, &val)) {
377  proc.m_proc.m_args.appfmt(" %s=%s", ndbcs, val);
378  }
379 
380  proc.m_proc.m_cwd.appfmt("%smysqld.%u", dir.c_str(), proc.m_index);
381  proc.m_proc.m_shutdown_options = "SIGKILL"; // not nice
382  proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=.%u%s",
383  proc.m_index,
384  cluster.m_name.c_str());
385  break;
386  }
387  case atrt_process::AP_NDB_API:
388  {
389  proc.m_proc.m_name.assfmt("%u-%s", proc_no, "ndb_api");
390  proc.m_proc.m_path = "";
391  proc.m_proc.m_args = "";
392  proc.m_proc.m_cwd.appfmt("%sndb_api.%u", dir.c_str(), proc.m_index);
393  proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=%s",
394  cluster.m_name.c_str());
395  break;
396  }
397  case atrt_process::AP_CLIENT:
398  {
399  proc.m_proc.m_name.assfmt("%u-%s", proc_no, "mysql");
400  proc.m_proc.m_path = "";
401  proc.m_proc.m_args = "";
402  proc.m_proc.m_cwd.appfmt("%s/client.%u", dir.c_str(), proc.m_index);
403  proc.m_proc.m_env.appfmt(" MYSQL_GROUP_SUFFIX=.%d%s",
404  proc.m_index,
405  cluster.m_name.c_str());
406  break;
407  }
408  case atrt_process::AP_ALL:
409  case atrt_process::AP_CLUSTER:
410  g_logger.critical("Unhandled process type: %d", proc.m_type);
411  return false;
412  }
413 
414  if (type == atrt_process::AP_MYSQLD)
415  {
419  if (!load_process(config, cluster, atrt_process::AP_CLIENT, idx, hostname))
420  {
421  return false;
422  }
423  }
424 
425  if (type == atrt_process::AP_CLIENT)
426  {
427  proc.m_mysqld = cluster.m_processes[cluster.m_processes.size()-2];
428  }
429 
430  return true;
431 }
432 
433 static
434 bool
435 load_options(int argc, char** argv, int type, atrt_options& opts)
436 {
437  for (size_t i = 0; i<(size_t)argc; i++)
438  {
439  if (ndb_is_load_default_arg_separator(argv[i]))
440  continue;
441  for (size_t j = 0; f_options[j].name; j++)
442  {
443  const char * name = f_options[j].name;
444  const size_t len = strlen(name);
445 
446  if ((f_options[j].type & type) && strncmp(argv[i], name, len) == 0)
447  {
448  opts.m_loaded.put(name, argv[i]+len, true);
449  break;
450  }
451  }
452  }
453  return true;
454 }
455 
457 {
458  int m_setup;
459  atrt_config* m_config;
460  atrt_host * m_host;
461  atrt_cluster* m_cluster;
462  atrt_process* m_process;
463 };
464 
465 struct proc_rule
466 {
467  int type;
468  bool (* func)(Properties& prop, proc_rule_ctx&, int extra);
469  int extra;
470 };
471 
472 static bool pr_check_replication(Properties&, proc_rule_ctx&, int);
473 static bool pr_check_features(Properties&, proc_rule_ctx&, int);
474 static bool pr_fix_client(Properties&, proc_rule_ctx&, int);
475 static bool pr_proc_options(Properties&, proc_rule_ctx&, int);
476 static bool pr_fix_ndb_connectstring(Properties&, proc_rule_ctx&, int);
477 static bool pr_set_ndb_connectstring(Properties&, proc_rule_ctx&, int);
478 static bool pr_check_proc(Properties&, proc_rule_ctx&, int);
479 
480 static
481 proc_rule f_rules[] =
482 {
483  { atrt_process::AP_CLUSTER, pr_check_features, 0 }
484  ,{ atrt_process::AP_MYSQLD, pr_check_replication, 0 }
485  ,{ (atrt_process::AP_ALL & ~atrt_process::AP_CLIENT), pr_proc_options,
486  ~(PO_REP | PO_NDB) }
487  ,{ (atrt_process::AP_ALL & ~atrt_process::AP_CLIENT), pr_proc_options, PO_REP }
488  ,{ atrt_process::AP_CLIENT, pr_fix_client, 0 }
489  ,{ atrt_process::AP_CLUSTER, pr_fix_ndb_connectstring, 0 }
490  ,{ atrt_process::AP_MYSQLD, pr_set_ndb_connectstring, 0 }
491  ,{ atrt_process::AP_ALL, pr_check_proc, 0 }
492  ,{ 0, 0, 0 }
493 };
494 
495 bool
496 configure(atrt_config& config, int setup)
497 {
498  Properties props;
499 
500  for (size_t i = 0; f_rules[i].func; i++)
501  {
502  bool ok = true;
503  proc_rule_ctx ctx;
504  memset(&ctx, 0, sizeof(ctx));
505  ctx.m_setup = setup;
506  ctx.m_config = &config;
507 
508  for (size_t j = 0; j < config.m_clusters.size(); j++)
509  {
510  ctx.m_cluster = config.m_clusters[j];
511 
512  if (f_rules[i].type & atrt_process::AP_CLUSTER)
513  {
514  g_logger.debug("applying rule %u to cluster %s", (unsigned)i,
515  ctx.m_cluster->m_name.c_str());
516  if (! (* f_rules[i].func)(props, ctx, f_rules[i].extra))
517  ok = false;
518  }
519  else
520  {
521  atrt_cluster& cluster = *config.m_clusters[j];
522  for (size_t k = 0; k<cluster.m_processes.size(); k++)
523  {
524  atrt_process& proc = *cluster.m_processes[k];
525  ctx.m_process = cluster.m_processes[k];
526  if (proc.m_type & f_rules[i].type)
527  {
528  g_logger.debug("applying rule %u to %s", (unsigned)i,
529  proc.m_proc.m_cwd.c_str());
530  if (! (* f_rules[i].func)(props, ctx, f_rules[i].extra))
531  ok = false;
532  }
533  }
534  }
535  }
536 
537  if (!ok)
538  {
539  return false;
540  }
541  }
542 
543  return true;
544 }
545 
546 static
548 find(atrt_config& config, int type, const char * name)
549 {
550  BaseString tmp(name);
551  Vector<BaseString> src;
552  Vector<BaseString> dst;
553  tmp.split(src, ".");
554 
555  if (src.size() != 2)
556  {
557  return 0;
558  }
559  atrt_cluster* cluster = 0;
560  BaseString cl;
561  cl.appfmt(".%s", src[1].c_str());
562  for (size_t i = 0; i<config.m_clusters.size(); i++)
563  {
564  if (config.m_clusters[i]->m_name == cl)
565  {
566  cluster = config.m_clusters[i];
567  break;
568  }
569  }
570 
571  if (cluster == 0)
572  {
573  return 0;
574  }
575 
576  int idx = atoi(src[0].c_str()) - 1;
577  for (size_t i = 0; i<cluster->m_processes.size(); i++)
578  {
579  if (cluster->m_processes[i]->m_type & type)
580  {
581  if (idx == 0)
582  return cluster->m_processes[i];
583  else
584  idx --;
585  }
586  }
587 
588  return 0;
589 }
590 
591 static
592 bool
593 pr_check_replication(Properties& props, proc_rule_ctx& ctx, int)
594 {
595  if (! (ctx.m_config->m_replication == ""))
596  {
597  Vector<BaseString> list;
598  ctx.m_config->m_replication.split(list, ";");
599  atrt_config& config = *ctx.m_config;
600 
601  ctx.m_config->m_replication = "";
602 
603  const char * msg = "Invalid replication specification";
604  for (size_t i = 0; i<list.size(); i++)
605  {
606  Vector<BaseString> rep;
607  list[i].split(rep, ":");
608  if (rep.size() != 2)
609  {
610  g_logger.error("%s: %s (split: %d)", msg, list[i].c_str(), rep.size());
611  return false;
612  }
613 
614  atrt_process* src = find(config, atrt_process::AP_MYSQLD,rep[0].c_str());
615  atrt_process* dst = find(config, atrt_process::AP_MYSQLD,rep[1].c_str());
616 
617  if (src == 0 || dst == 0)
618  {
619  g_logger.error("%s: %s (%d %d)",
620  msg, list[i].c_str(), src != 0, dst != 0);
621  return false;
622  }
623 
624 
625  if (dst->m_rep_src != 0)
626  {
627  g_logger.error("%s: %s : %s already has replication src (%s)",
628  msg,
629  list[i].c_str(),
630  dst->m_proc.m_cwd.c_str(),
631  dst->m_rep_src->m_proc.m_cwd.c_str());
632  return false;
633  }
634 
635  dst->m_rep_src = src;
636  src->m_rep_dst.push_back(dst);
637 
638  src->m_options.m_features |= PO_REP_MASTER;
639  dst->m_options.m_features |= PO_REP_SLAVE;
640  }
641  }
642  return true;
643 }
644 
645 static
646 bool
647 pr_check_features(Properties& props, proc_rule_ctx& ctx, int)
648 {
649  int features = 0;
650  atrt_cluster& cluster = *ctx.m_cluster;
651  for (size_t i = 0; i<cluster.m_processes.size(); i++)
652  {
653  if (cluster.m_processes[i]->m_type == atrt_process::AP_NDB_MGMD ||
654  cluster.m_processes[i]->m_type == atrt_process::AP_NDB_API ||
655  cluster.m_processes[i]->m_type == atrt_process::AP_MYSQLD ||
656  cluster.m_processes[i]->m_type == atrt_process::AP_NDBD)
657  {
658  features |= atrt_options::AO_NDBCLUSTER;
659  break;
660  }
661  }
662 
663  if (features)
664  {
665  cluster.m_options.m_features |= features;
666  for (size_t i = 0; i<cluster.m_processes.size(); i++)
667  {
668  cluster.m_processes[i]->m_options.m_features |= features;
669  }
670  }
671  return true;
672 }
673 
674 static
675 bool
676 pr_fix_client(Properties& props, proc_rule_ctx& ctx, int)
677 {
678  atrt_process& proc = *ctx.m_process;
679  const char * val, *name = "--host=";
680  if (!proc.m_options.m_loaded.get(name, &val))
681  {
682  val = proc.m_mysqld->m_host->m_hostname.c_str();
683  proc.m_options.m_loaded.put(name, val);
684  proc.m_options.m_generated.put(name, val);
685  }
686 
687  for (size_t i = 0; f_options[i].name; i++)
688  {
689  proc_option& opt = f_options[i];
690  const char * name = opt.name;
691  if (opt.type & atrt_process::AP_CLIENT)
692  {
693  const char * val;
694  if (!proc.m_options.m_loaded.get(name, &val))
695  {
696  require(proc.m_mysqld->m_options.m_loaded.get(name, &val));
697  proc.m_options.m_loaded.put(name, val);
698  proc.m_options.m_generated.put(name, val);
699  }
700  }
701  }
702 
703  return true;
704 }
705 
706 static
707 Uint32
708 try_default_port(atrt_process& proc, const char * name)
709 {
710  Uint32 port =
711  strcmp(name, "--port=") == 0 ? 3306 :
712  strcmp(name, "--PortNumber=") == 0 ? 1186 :
713  0;
714 
715  atrt_host * host = proc.m_host;
716  for (size_t i = 0; i<host->m_processes.size(); i++)
717  {
718  const char * val;
719  if (host->m_processes[i]->m_options.m_loaded.get(name, &val))
720  {
721  if ((Uint32)atoi(val) == port)
722  return 0;
723  }
724  }
725  return port;
726 }
727 
728 static
729 bool
730 generate(atrt_process& proc, const char * name, Properties& props)
731 {
732  atrt_options& opts = proc.m_options;
733  if (strcmp(name, "--port=") == 0 ||
734  strcmp(name, "--PortNumber=") == 0)
735  {
736  Uint32 val;
737  if (g_default_ports == 0 || (val = try_default_port(proc, name)) == 0)
738  {
739  val = g_baseport;
740  props.get("--PortNumber=", &val);
741  props.put("--PortNumber=", (val + 1), true);
742  }
743 
744  char buf[255];
745  BaseString::snprintf(buf, sizeof(buf), "%u", val);
746  opts.m_loaded.put(name, buf);
747  opts.m_generated.put(name, buf);
748  return true;
749  }
750  else if (strcmp(name, "--datadir=") == 0)
751  {
752  opts.m_loaded.put(name, proc.m_proc.m_cwd.c_str());
753  opts.m_generated.put(name, proc.m_proc.m_cwd.c_str());
754  return true;
755  }
756  else if (strcmp(name, "--FileSystemPath=") == 0)
757  {
758  opts.m_loaded.put(name, proc.m_proc.m_cwd.c_str());
759  opts.m_generated.put(name, proc.m_proc.m_cwd.c_str());
760  return true;
761  }
762  else if (strcmp(name, "--socket=") == 0)
763  {
764  const char * sock = 0;
765  if (g_default_ports)
766  {
767  sock = "/tmp/mysql.sock";
768  atrt_host * host = proc.m_host;
769  for (size_t i = 0; i<host->m_processes.size(); i++)
770  {
771  const char * val;
772  if (host->m_processes[i]->m_options.m_loaded.get(name, &val))
773  {
774  if (strcmp(sock, val) == 0)
775  {
776  sock = 0;
777  break;
778  }
779  }
780  }
781  }
782 
783  BaseString tmp;
784  if (sock == 0)
785  {
786  tmp.assfmt("%s/mysql.sock", proc.m_proc.m_cwd.c_str());
787  sock = tmp.c_str();
788  }
789 
790  opts.m_loaded.put(name, sock);
791  opts.m_generated.put(name, sock);
792  return true;
793  }
794  else if (strcmp(name, "--server-id=") == 0)
795  {
796  Uint32 val = 1;
797  props.get(name, &val);
798  char buf[255];
799  BaseString::snprintf(buf, sizeof(buf), "%u", val);
800  opts.m_loaded.put(name, buf);
801  opts.m_generated.put(name, buf);
802  props.put(name, (val + 1), true);
803  return true;
804  }
805  else if (strcmp(name, "--log-bin") == 0)
806  {
807  opts.m_loaded.put(name, "");
808  opts.m_generated.put(name, "");
809  return true;
810  }
811  else if (strcmp(name, "--master-host=") == 0)
812  {
813  require(proc.m_rep_src != 0);
814  opts.m_loaded.put(name, proc.m_rep_src->m_host->m_hostname.c_str());
815  opts.m_generated.put(name, proc.m_rep_src->m_host->m_hostname.c_str());
816  return true;
817  }
818  else if (strcmp(name, "--master-port=") == 0)
819  {
820  const char* val;
821  require(proc.m_rep_src->m_options.m_loaded.get("--port=", &val));
822  opts.m_loaded.put(name, val);
823  opts.m_generated.put(name, val);
824  return true;
825  }
826  else if (strcmp(name, "--master-user=") == 0)
827  {
828  opts.m_loaded.put(name, "root");
829  opts.m_generated.put(name, "root");
830  return true;
831  }
832  else if (strcmp(name, "--master-password=") == 0)
833  {
834  opts.m_loaded.put(name, "\"\"");
835  opts.m_generated.put(name, "\"\"");
836  return true;
837  }
838 
839  g_logger.warning("Unknown parameter: %s", name);
840  return true;
841 }
842 
843 static
844 bool
845 pr_proc_options(Properties& props, proc_rule_ctx& ctx, int extra)
846 {
847  for (size_t i = 0; f_options[i].name; i++)
848  {
849  proc_option& opt = f_options[i];
850  atrt_process& proc = *ctx.m_process;
851  const char * name = opt.name;
852  if (opt.type & proc.m_type)
853  {
854  if (opt.options == 0 ||
855  (opt.options & extra & proc.m_options.m_features))
856  {
857  const char * val;
858  if (!proc.m_options.m_loaded.get(name, &val))
859  {
860  generate(proc, name, props);
861  }
862  }
863  }
864  }
865  return true;
866 }
867 
868 static
869 bool
870 pr_fix_ndb_connectstring(Properties& props, proc_rule_ctx& ctx, int)
871 {
872  const char * val;
873  atrt_cluster& cluster = *ctx.m_cluster;
874 
875  if (cluster.m_options.m_features & atrt_options::AO_NDBCLUSTER)
876  {
877  if (!cluster.m_options.m_loaded.get(ndbcs, &val))
878  {
882  BaseString str;
883  for (size_t i = 0; i<cluster.m_processes.size(); i++)
884  {
885  atrt_process* tmp = cluster.m_processes[i];
886  if (tmp->m_type == atrt_process::AP_NDB_MGMD)
887  {
888  if (str.length())
889  {
890  str.append(";");
891  }
892  const char * port;
893  require(tmp->m_options.m_loaded.get("--PortNumber=", &port));
894  str.appfmt("%s:%s", tmp->m_host->m_hostname.c_str(), port);
895  }
896  }
897  cluster.m_options.m_loaded.put(ndbcs, str.c_str());
898  cluster.m_options.m_generated.put(ndbcs, str.c_str());
899  cluster.m_options.m_loaded.get(ndbcs, &val);
900  }
901 
902  for (size_t i = 0; i<cluster.m_processes.size(); i++)
903  {
904  cluster.m_processes[i]->m_proc.m_env.appfmt(" NDB_CONNECTSTRING=%s",
905  val);
906  }
907  }
908  return true;
909 }
910 
911 static
912 bool
913 pr_set_ndb_connectstring(Properties& props, proc_rule_ctx& ctx, int)
914 {
915  const char * val;
916 
917  atrt_process& proc = *ctx.m_process;
918  if (proc.m_options.m_features & atrt_options::AO_NDBCLUSTER)
919  {
920  if (!proc.m_options.m_loaded.get(ndbcs, &val))
921  {
922  require(proc.m_cluster->m_options.m_loaded.get(ndbcs, &val));
923  proc.m_options.m_loaded.put(ndbcs, val);
924  proc.m_options.m_generated.put(ndbcs, val);
925  }
926 
927  if (!proc.m_options.m_loaded.get("--ndbcluster", &val))
928  {
929  proc.m_options.m_loaded.put("--ndbcluster", "");
930  proc.m_options.m_generated.put("--ndbcluster", "");
931  }
932  }
933  return true;
934 }
935 
936 static
937 bool
938 pr_check_proc(Properties& props, proc_rule_ctx& ctx, int)
939 {
940  bool ok = true;
941  bool generated = false;
942  const int setup = ctx.m_setup;
943  atrt_process& proc = *ctx.m_process;
944  for (size_t i = 0; f_options[i].name; i++)
945  {
946  proc_option& opt = f_options[i];
947  const char * name = opt.name;
948  if ((ctx.m_process->m_type & opt.type) &&
949  (opt.options == 0 || (ctx.m_process->m_options.m_features & opt.options)))
950  {
951  const char * val;
952  if (!proc.m_options.m_loaded.get(name, &val))
953  {
954  ok = false;
955  g_logger.warning("Missing parameter: %s for %s",
956  name, proc.m_proc.m_cwd.c_str());
957  }
958  else if (proc.m_options.m_generated.get(name, &val))
959  {
960  if (setup == 0)
961  {
962  ok = false;
963  g_logger.warning("Missing parameter: %s for %s",
964  name, proc.m_proc.m_cwd.c_str());
965  }
966  else
967  {
968  generated = true;
969  }
970  }
971  }
972  }
973 
974  if (generated)
975  {
976  ctx.m_config->m_generated = true;
977  }
978 
979  //ndbout << proc << endl;
980 
981  return ok;
982 }
983 
984 
985 NdbOut&
986 operator<<(NdbOut& out, const atrt_process& proc)
987 {
988  out << "[ atrt_process: ";
989  switch(proc.m_type){
990  case atrt_process::AP_NDB_MGMD:
991  out << "ndb_mgmd";
992  break;
993  case atrt_process::AP_NDBD:
994  out << "ndbd";
995  break;
996  case atrt_process::AP_MYSQLD:
997  out << "mysqld";
998  break;
999  case atrt_process::AP_NDB_API:
1000  out << "ndbapi";
1001  break;
1002  case atrt_process::AP_CLIENT:
1003  out << "client";
1004  break;
1005  default:
1006  out << "<unknown: " << (int)proc.m_type << " >";
1007  }
1008 
1009  out << " cluster: " << proc.m_cluster->m_name.c_str()
1010  << " host: " << proc.m_host->m_hostname.c_str()
1011  << endl << " cwd: " << proc.m_proc.m_cwd.c_str()
1012  << endl << " path: " << proc.m_proc.m_path.c_str()
1013  << endl << " args: " << proc.m_proc.m_args.c_str()
1014  << endl << " env: " << proc.m_proc.m_env.c_str() << endl;
1015 
1016  proc.m_options.m_generated.print(stdout, "generated: ");
1017 
1018  out << " ]";
1019 
1020 #if 0
1021  proc.m_index = 0; //idx;
1022  proc.m_host = host_ptr;
1023  proc.m_cluster = cluster;
1024  proc.m_proc.m_id = -1;
1025  proc.m_proc.m_type = "temporary";
1026  proc.m_proc.m_owner = "atrt";
1027  proc.m_proc.m_group = cluster->m_name.c_str();
1028  proc.m_proc.m_cwd.assign(dir).append("/atrt/").append(cluster->m_dir);
1029  proc.m_proc.m_stdout = "log.out";
1030  proc.m_proc.m_stderr = "2>&1";
1031  proc.m_proc.m_runas = proc.m_host->m_user;
1032  proc.m_proc.m_ulimit = "c:unlimited";
1033  proc.m_proc.m_env.assfmt("MYSQL_BASE_DIR=%s", dir);
1034  proc.m_proc.m_shutdown_options = "";
1035 #endif
1036 
1037  return out;
1038 }
1039