MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ndb_config.cpp
1 /*
2  Copyright (c) 2005, 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 
64 #include <ndb_global.h>
65 #include <ndb_opts.h>
66 
67 #include <my_sys.h>
68 #include <my_getopt.h>
69 #include <mysql_version.h>
70 
71 #include <NdbOut.hpp>
72 #include <mgmapi.h>
73 #include "../src/mgmapi/mgmapi_configuration.hpp"
74 #include "../src/mgmsrv/ConfigInfo.hpp"
75 #include <NdbAutoPtr.hpp>
76 #include <NdbTCP.h>
77 
78 static int g_verbose = 0;
79 static int try_reconnect = 3;
80 
81 static int g_nodes, g_connections, g_system, g_section;
82 static const char * g_query = 0;
83 
84 static int g_nodeid = 0;
85 static const char * g_type = 0;
86 static const char * g_host = 0;
87 static const char * g_field_delimiter=",";
88 static const char * g_row_delimiter=" ";
89 static const char * g_config_file = 0;
90 static int g_mycnf = 0;
91 static int g_configinfo = 0;
92 static int g_xml = 0;
93 static int g_config_from_node = 0;
94 
95 const char *load_default_groups[]= { "mysql_cluster",0 };
96 
98 
99 static struct my_option my_long_options[] =
100 {
101  NDB_STD_OPTS("ndb_config"),
102  { "nodes", NDB_OPT_NOSHORT, "Print nodes",
103  (uchar**) &g_nodes, (uchar**) &g_nodes,
104  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
105  { "connections", NDB_OPT_NOSHORT, "Print connections",
106  (uchar**) &g_connections, (uchar**) &g_connections,
107  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
108  { "system", NDB_OPT_NOSHORT, "Print system",
109  (uchar**) &g_system, (uchar**) &g_system,
110  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
111  { "query", 'q', "Query option(s)",
112  (uchar**) &g_query, (uchar**) &g_query,
113  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
114  { "host", NDB_OPT_NOSHORT, "Host",
115  (uchar**) &g_host, (uchar**) &g_host,
116  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
117  { "type", NDB_OPT_NOSHORT, "Type of node/connection",
118  (uchar**) &g_type, (uchar**) &g_type,
119  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
120  { "id", NDB_OPT_NOSHORT, "Nodeid",
121  (uchar**) &g_nodeid, (uchar**) &g_nodeid,
122  0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
123  { "nodeid", NDB_OPT_NOSHORT, "Nodeid",
124  (uchar**) &g_nodeid, (uchar**) &g_nodeid,
125  0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
126  { "fields", 'f', "Field separator",
127  (uchar**) &g_field_delimiter, (uchar**) &g_field_delimiter,
128  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
129  { "rows", 'r', "Row separator",
130  (uchar**) &g_row_delimiter, (uchar**) &g_row_delimiter,
131  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
132  { "config-file", NDB_OPT_NOSHORT, "Path to config.ini",
133  (uchar**) &g_config_file, (uchar**) &g_config_file,
134  0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
135  { "mycnf", NDB_OPT_NOSHORT, "Read config from my.cnf",
136  (uchar**) &g_mycnf, (uchar**) &g_mycnf,
137  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
138  { "configinfo", NDB_OPT_NOSHORT, "Print configinfo",
139  (uchar**) &g_configinfo, (uchar**) &g_configinfo,
140  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
141  { "xml", NDB_OPT_NOSHORT, "Print configinfo in xml format",
142  (uchar**) &g_xml, (uchar**) &g_xml,
143  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
144  { "config_from_node", NDB_OPT_NOSHORT, "Use current config from node with given nodeid",
145  (uchar**) &g_config_from_node, (uchar**) &g_config_from_node,
146  0, GET_INT, REQUIRED_ARG, INT_MIN, INT_MIN, 0, 0, 0, 0},
147  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
148 };
149 
150 static void short_usage_sub(void)
151 {
152  ndb_short_usage_sub(NULL);
153 }
154 
155 static void usage()
156 {
157  char desc[] =
158  "This program will retreive config options for a ndb cluster\n";
159  puts(desc);
160  ndb_usage(short_usage_sub, load_default_groups, my_long_options);
161 }
162 
166 struct Match
167 {
168  int m_key;
169  BaseString m_value;
170  Match() {}
171  virtual int eval(const Iter&);
172  virtual ~Match() {}
173 };
174 
175 struct HostMatch : public Match
176 {
177  HostMatch() {}
178  virtual int eval(const Iter&);
179 };
180 
181 struct Apply
182 {
183  Apply() {}
184  Apply(int val) { m_key = val;}
185  int m_key;
186  virtual int apply(const Iter&);
187  virtual ~Apply() {}
188 };
189 
190 struct NodeTypeApply : public Apply
191 {
192  NodeTypeApply() {}
193  virtual int apply(const Iter&);
194 };
195 
196 struct ConnectionTypeApply : public Apply
197 {
199  virtual int apply(const Iter&);
200 };
201 
202 static int parse_query(Vector<Apply*>&, int &argc, char**& argv);
203 static int parse_where(Vector<Match*>&, int &argc, char**& argv);
204 static int eval(const Iter&, const Vector<Match*>&);
205 static int apply(const Iter&, const Vector<Apply*>&);
206 static ndb_mgm_configuration* fetch_configuration(int from_node);
207 static ndb_mgm_configuration* load_configuration();
208 
209 
210 int
211 main(int argc, char** argv){
212  NDB_INIT(argv[0]);
213  ndb_opt_set_usage_funcs(short_usage_sub, usage);
214  load_defaults("my",load_default_groups,&argc,&argv);
215  int ho_error;
216  if ((ho_error=handle_options(&argc, &argv, my_long_options,
217  ndb_std_get_one_option)))
218  exit(255);
219 
220  if (g_configinfo)
221  {
222  ConfigInfo info;
223  if (g_xml)
224  info.print_xml();
225  else
226  info.print();
227  exit(0);
228  }
229 
230  if ((g_nodes && g_connections) ||
231  (g_system && (g_nodes || g_connections)))
232  {
233  fprintf(stderr,
234  "Error: Only one of the section-options: --nodes, --connections, --system is allowed.\n");
235  exit(255);
236  }
237 
238  /* There is no explicit option for the user to set
239  * 'retrieving config from mgmd', but this is the default.
240  * Therefore will not contradict with other sources.
241  */
242 
243  if ((g_config_file && g_mycnf) ||
244  ((g_config_from_node != INT_MIN) && (g_config_file || g_mycnf)))
245  {
246  fprintf(stderr,
247  "Error: Config should be retrieved from only one of the following sources:\n");
248  fprintf(stderr,
249  "\tconfig stored at mgmd (default),\n");
250  fprintf(stderr,
251  "\tconfig stored at a data node (--config_from_node=<nodeid>), \n");
252  fprintf(stderr,
253  "\tmy.cnf(--mycnf=<my.cnf file>),\n");
254  fprintf(stderr,
255  "\tconfig.file (--config_file=<config file>).\n");
256  exit(255);
257  }
258 
259  g_section = CFG_SECTION_NODE; //default
260  if (g_connections)
261  g_section = CFG_SECTION_CONNECTION;
262  else if (g_system)
263  g_section = CFG_SECTION_SYSTEM;
264 
265  ndb_mgm_configuration * conf = 0;
266 
267  if (g_config_file || g_mycnf)
268  conf = load_configuration();
269  else
270  conf = fetch_configuration(g_config_from_node);
271 
272  if (conf == 0)
273  {
274  exit(255);
275  }
276 
277  Vector<Apply*> select_list;
278  Vector<Match*> where_clause;
279 
280  if(strcmp(g_row_delimiter, "\\n") == 0)
281  g_row_delimiter = "\n";
282  if(strcmp(g_field_delimiter, "\\n") == 0)
283  g_field_delimiter = "\n";
284 
285  if(parse_query(select_list, argc, argv))
286  {
287  exit(0);
288  }
289 
290  if(parse_where(where_clause, argc, argv))
291  {
292  exit(0);
293  }
294 
295  Iter iter(* conf, g_section);
296  bool prev= false;
297  iter.first();
298  for(iter.first(); iter.valid(); iter.next())
299  {
300  if(eval(iter, where_clause))
301  {
302  if(prev)
303  printf("%s", g_row_delimiter);
304  prev= true;
305  apply(iter, select_list);
306  }
307  }
308  printf("\n");
309  return 0;
310 }
311 
312 static
313 int
314 parse_query(Vector<Apply*>& select, int &argc, char**& argv)
315 {
316  if(g_query)
317  {
318  BaseString q(g_query);
319  Vector<BaseString> list;
320  q.split(list, ",");
321  for(unsigned i = 0; i<list.size(); i++)
322  {
323  const char * str= list[i].c_str();
324  if(g_section == CFG_SECTION_NODE)
325  {
326  if(strcasecmp(str, "id") == 0 || strcasecmp(str, "nodeid") == 0)
327  {
328  select.push_back(new Apply(CFG_NODE_ID));
329  continue;
330  }
331  else if(strncasecmp(str, "host", 4) == 0)
332  {
333  select.push_back(new Apply(CFG_NODE_HOST));
334  continue;
335  }
336  else if(strcasecmp(str, "type") == 0)
337  {
338  select.push_back(new NodeTypeApply());
339  continue;
340  }
341  }
342  else if (g_section == CFG_SECTION_CONNECTION)
343  {
344  if(strcasecmp(str, "type") == 0)
345  {
346  select.push_back(new ConnectionTypeApply());
347  continue;
348  }
349  }
350  {
351  bool found = false;
352  for(int p = 0; p<ConfigInfo::m_NoOfParams; p++)
353  {
354  if(0)ndbout_c("%s %s",
355  ConfigInfo::m_ParamInfo[p]._section,
356  ConfigInfo::m_ParamInfo[p]._fname);
357  if((g_section == CFG_SECTION_CONNECTION &&
358  (strcmp(ConfigInfo::m_ParamInfo[p]._section, "TCP") == 0 ||
359  strcmp(ConfigInfo::m_ParamInfo[p]._section, "SCI") == 0 ||
360  strcmp(ConfigInfo::m_ParamInfo[p]._section, "SHM") == 0))
361  ||
362  (g_section == CFG_SECTION_NODE &&
363  (strcmp(ConfigInfo::m_ParamInfo[p]._section, "DB") == 0 ||
364  strcmp(ConfigInfo::m_ParamInfo[p]._section, "API") == 0 ||
365  strcmp(ConfigInfo::m_ParamInfo[p]._section, "MGM") == 0))
366  ||
367  (g_section == CFG_SECTION_SYSTEM))
368  {
369  if(strcasecmp(ConfigInfo::m_ParamInfo[p]._fname, str) == 0)
370  {
371  select.push_back(new Apply(ConfigInfo::m_ParamInfo[p]._paramId));
372  found = true;
373  break;
374  }
375  }
376  }
377  if(!found)
378  {
379  fprintf(stderr, "Unknown query option: %s\n", str);
380  return 1;
381  }
382  }
383  }
384  }
385  return 0;
386 }
387 
388 static
389 int
390 parse_where(Vector<Match*>& where, int &argc, char**& argv)
391 {
392  Match m;
393  if(g_host)
394  {
395  HostMatch *tmp = new HostMatch;
396  tmp->m_key = CFG_NODE_HOST;
397  tmp->m_value.assfmt("%s", g_host);
398  where.push_back(tmp);
399  }
400 
401  if(g_type)
402  {
403  m.m_key = CFG_TYPE_OF_SECTION;
404  m.m_value.assfmt("%d", ndb_mgm_match_node_type(g_type));
405  where.push_back(new Match(m));
406  }
407 
408  if(g_nodeid)
409  {
410  m.m_key = CFG_NODE_ID;
411  m.m_value.assfmt("%d", g_nodeid);
412  where.push_back(new Match(m));
413  }
414  return 0;
415 }
416 
417 template class Vector<Apply*>;
418 template class Vector<Match*>;
419 
420 static
421 int
422 eval(const Iter& iter, const Vector<Match*>& where)
423 {
424  for(unsigned i = 0; i<where.size(); i++)
425  {
426  if(where[i]->eval(iter) == 0)
427  return 0;
428  }
429 
430  return 1;
431 }
432 
433 static
434 int
435 apply(const Iter& iter, const Vector<Apply*>& list)
436 {
437  for(unsigned i = 0; i<list.size(); i++)
438  {
439  list[i]->apply(iter);
440  if(i + 1 != list.size())
441  printf("%s", g_field_delimiter);
442  }
443  return 0;
444 }
445 
446 int
447 Match::eval(const Iter& iter)
448 {
449  Uint32 val32;
450  Uint64 val64;
451  const char* valc;
452  if (iter.get(m_key, &val32) == 0)
453  {
454  if(atoi(m_value.c_str()) != (int)val32)
455  return 0;
456  }
457  else if(iter.get(m_key, &val64) == 0)
458  {
459  if(strtoll(m_value.c_str(), (char **)NULL, 10) != (long long)val64)
460  return 0;
461  }
462  else if(iter.get(m_key, &valc) == 0)
463  {
464  if(strcmp(m_value.c_str(), valc) != 0)
465  return 0;
466  }
467  else
468  {
469  return 0;
470  }
471  return 1;
472 }
473 
474 int
475 HostMatch::eval(const Iter& iter)
476 {
477  const char* valc;
478 
479  if(iter.get(m_key, &valc) == 0)
480  {
481  struct hostent *h1, *h2, copy1;
482  char *addr1;
483 
484  h1 = gethostbyname(m_value.c_str());
485  if (h1 == NULL) {
486  return 0;
487  }
488 
489  // gethostbyname returns a pointer to a static structure
490  // so we need to copy the results before doing the next call
491  memcpy(&copy1, h1, sizeof(struct hostent));
492  addr1 = (char *)malloc(copy1.h_length);
493  NdbAutoPtr<char> tmp_aptr(addr1);
494  memcpy(addr1, h1->h_addr, copy1.h_length);
495 
496  h2 = gethostbyname(valc);
497  if (h2 == NULL) {
498  return 0;
499  }
500 
501  if (copy1.h_addrtype != h2->h_addrtype) {
502  return 0;
503  }
504 
505  if (copy1.h_length != h2->h_length)
506  {
507  return 0;
508  }
509 
510  return 0 == memcmp(addr1, h2->h_addr, copy1.h_length);
511  }
512 
513  return 0;
514 }
515 
516 int
517 Apply::apply(const Iter& iter)
518 {
519  Uint32 val32;
520  Uint64 val64;
521  const char* valc;
522  if (iter.get(m_key, &val32) == 0)
523  {
524  printf("%u", val32);
525  }
526  else if(iter.get(m_key, &val64) == 0)
527  {
528  printf("%llu", val64);
529  }
530  else if(iter.get(m_key, &valc) == 0)
531  {
532  printf("%s", valc);
533  }
534  return 0;
535 }
536 
537 int
538 NodeTypeApply::apply(const Iter& iter)
539 {
540  Uint32 val32;
541  if (iter.get(CFG_TYPE_OF_SECTION, &val32) == 0)
542  {
543  printf("%s", ndb_mgm_get_node_type_alias_string((ndb_mgm_node_type)val32, 0));
544  }
545  return 0;
546 }
547 
548 int
549 ConnectionTypeApply::apply(const Iter& iter)
550 {
551  Uint32 val32;
552  if (iter.get(CFG_TYPE_OF_SECTION, &val32) == 0)
553  {
554  switch (val32)
555  {
556  case CONNECTION_TYPE_TCP:
557  printf("tcp");
558  break;
559  case CONNECTION_TYPE_SCI:
560  printf("sci");
561  break;
562  case CONNECTION_TYPE_SHM:
563  printf("shm");
564  break;
565  default:
566  printf("<unknown>");
567  break;
568  }
569  }
570  return 0;
571 }
572 
573 static ndb_mgm_configuration*
574 fetch_configuration(int from_node)
575 {
576  ndb_mgm_configuration* conf = 0;
578  if(mgm == NULL) {
579  fprintf(stderr, "Cannot create handle to management server.\n");
580  return 0;
581  }
582 
583  ndb_mgm_set_error_stream(mgm, stderr);
584 
585  if (ndb_mgm_set_connectstring(mgm, opt_ndb_connectstring))
586  {
587  fprintf(stderr, "* %5d: %s\n",
590  fprintf(stderr,
591  "* %s", ndb_mgm_get_latest_error_desc(mgm));
592  goto noconnect;
593  }
594 
595  if(ndb_mgm_connect(mgm, try_reconnect-1, 5, 1))
596  {
597  fprintf(stderr, "Connect failed");
598  fprintf(stderr, " code: %d, msg: %s\n",
601  goto noconnect;
602  }
603  else if(g_verbose)
604  {
605  fprintf(stderr, "Connected to %s:%d\n",
608  }
609 
610  if (from_node == INT_MIN)
611  {
612  // from_node option is not requested.
613  // Retrieve config from the default src: mgmd
614  conf = ndb_mgm_get_configuration(mgm, 0);
615  }
616  else if (from_node < 1)
617  {
618  fprintf(stderr, "Invalid node number %d is given for --config_from_node.\n", from_node);
619  goto noconnect;
620  }
621  else
622  {
623  // Retrieve config from the given data node
624  conf = ndb_mgm_get_configuration_from_node(mgm, from_node);
625  }
626 
627  if(conf == 0)
628  {
629  fprintf(stderr, "Could not get configuration, ");
630  fprintf(stderr, "error code: %d, error msg: %s\n",
633  }
634  else if(g_verbose)
635  {
636  fprintf(stderr, "Fetched configuration\n");
637  }
638 
639  ndb_mgm_disconnect(mgm);
640 noconnect:
642 
643  return conf;
644 }
645 
646 #include "../src/mgmsrv/Config.hpp"
647 #include <EventLogger.hpp>
648 
649 extern EventLogger *g_eventLogger;
650 
651 static ndb_mgm_configuration*
652 load_configuration()
653 {
654  g_eventLogger->removeAllHandlers();
655  g_eventLogger->createConsoleHandler(ndberr);
656  g_eventLogger->setCategory("ndb_config");
657  InitConfigFileParser parser;
658  if (g_config_file)
659  {
660  if (g_verbose)
661  fprintf(stderr, "Using config.ini : %s\n", g_config_file);
662 
663  Config* conf = parser.parseConfig(g_config_file);
664  if (conf)
665  return conf->m_configValues;
666  return 0;
667  }
668 
669  if (g_verbose)
670  fprintf(stderr, "Using my.cnf\n");
671 
672  Config* conf = parser.parse_mycnf();
673  if (conf)
674  return conf->m_configValues;
675 
676  return 0;
677 }