MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
main.cpp
1 /*
2  Copyright (c) 2003, 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 <ndb_global.h>
19 #include <ndb_opts.h>
20 
21 #include "MgmtSrvr.hpp"
22 #include "EventLogger.hpp"
23 #include "Config.hpp"
24 
25 #include <version.h>
26 #include <kernel_types.h>
27 #include <portlib/ndb_daemon.h>
28 #include <NdbConfig.h>
29 #include <NdbSleep.h>
30 #include <portlib/NdbDir.hpp>
31 #include <ndb_version.h>
32 #include <mgmapi_config_parameters.h>
33 #include <NdbAutoPtr.hpp>
34 #include <ndb_mgmclient.hpp>
35 
36 #include <EventLogger.hpp>
37 extern EventLogger * g_eventLogger;
38 
39 
40 const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
41 
42 // copied from mysql.cc to get readline
43 extern "C" {
44 #if defined( __WIN__)
45 #include <conio.h>
46 #elif !defined(__NETWARE__)
47 #include <readline/readline.h>
48 extern "C" int add_history(const char *command); /* From readline directory */
49 #define HAVE_READLINE
50 #endif
51 }
52 
53 static int
54 read_and_execute(Ndb_mgmclient* com, const char * prompt, int _try_reconnect)
55 {
56  static char *line_read = (char *)NULL;
57 
58  /* If the buffer has already been allocated, return the memory
59  to the free pool. */
60  if (line_read)
61  {
62  free (line_read);
63  line_read = (char *)NULL;
64  }
65 #ifdef HAVE_READLINE
66  /* Get a line from the user. */
67  line_read = readline (prompt);
68  /* If the line has any text in it, save it on the history. */
69  if (line_read && *line_read)
70  add_history (line_read);
71 #else
72  static char linebuffer[254];
73  fputs(prompt, stdout);
74  linebuffer[sizeof(linebuffer)-1]=0;
75  line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
76  if (line_read == linebuffer) {
77  char *q=linebuffer;
78  while (*q > 31) q++;
79  *q=0;
80  line_read= strdup(linebuffer);
81  }
82 #endif
83  return com->execute(line_read,_try_reconnect);
84 }
85 
86 /* Global variables */
87 bool g_StopServer= false;
88 bool g_RestartServer= false;
89 static MgmtSrvr* mgm;
90 static MgmtSrvr::MgmtOpts opts;
91 static const char* opt_logname = "MgmtSrvr";
92 static const char* opt_nowait_nodes = 0;
93 
94 static struct my_option my_long_options[] =
95 {
96  NDB_STD_OPTS("ndb_mgmd"),
97  { "config-file", 'f', "Specify cluster configuration file",
98  (uchar**) &opts.config_filename, (uchar**) &opts.config_filename, 0,
99  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
100  { "print-full-config", 'P', "Print full config and exit",
101  (uchar**) &opts.print_full_config, (uchar**) &opts.print_full_config, 0,
102  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
103  { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)",
104  (uchar**) &opts.daemon, (uchar**) &opts.daemon, 0,
105  GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
106  { "interactive", NDB_OPT_NOSHORT,
107  "Run interactive. Not supported but provided for testing purposes",
108  (uchar**) &opts.interactive, (uchar**) &opts.interactive, 0,
109  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
110  { "no-nodeid-checks", NDB_OPT_NOSHORT,
111  "Do not provide any node id checks",
112  (uchar**) &opts.no_nodeid_checks, (uchar**) &opts.no_nodeid_checks, 0,
113  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
114  { "nodaemon", NDB_OPT_NOSHORT,
115  "Don't run as daemon, but don't read from stdin",
116  (uchar**) &opts.non_interactive, (uchar**) &opts.non_interactive, 0,
117  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
118  { "mycnf", NDB_OPT_NOSHORT,
119  "Read cluster config from my.cnf",
120  (uchar**) &opts.mycnf, (uchar**) &opts.mycnf, 0,
121  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
122  { "bind-address", NDB_OPT_NOSHORT,
123  "Local bind address",
124  (uchar**) &opts.bind_address, (uchar**) &opts.bind_address, 0,
125  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
126  { "configdir", NDB_OPT_NOSHORT,
127  "Directory for the binary configuration files (alias for --config-dir)",
128  (uchar**) &opts.configdir, (uchar**) &opts.configdir, 0,
129  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
130  { "config-dir", NDB_OPT_NOSHORT,
131  "Directory for the binary configuration files",
132  (uchar**) &opts.configdir, (uchar**) &opts.configdir, 0,
133  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
134  { "config-cache", NDB_OPT_NOSHORT,
135  "Enable configuration cache and change management",
136  (uchar**) &opts.config_cache, (uchar**) &opts.config_cache, 0,
137  GET_BOOL, NO_ARG, 1, 0, 1, 0, 0, 0 },
138  { "verbose", 'v',
139  "Write more log messages",
140  (uchar**) &opts.verbose, (uchar**) &opts.verbose, 0,
141  GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
142  { "reload", NDB_OPT_NOSHORT,
143  "Reload config from config.ini or my.cnf if it has changed on startup",
144  (uchar**) &opts.reload, (uchar**) &opts.reload, 0,
145  GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
146  { "initial", NDB_OPT_NOSHORT,
147  "Delete all binary config files and start from config.ini or my.cnf",
148  (uchar**) &opts.initial, (uchar**) &opts.initial, 0,
149  GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
150  { "log-name", NDB_OPT_NOSHORT,
151  "Name to use when logging messages for this node",
152  (uchar**) &opt_logname, (uchar**) &opt_logname, 0,
153  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
154  { "nowait-nodes", NDB_OPT_NOSHORT,
155  "Nodes that will not be waited for during start",
156  (uchar**) &opt_nowait_nodes, (uchar**) &opt_nowait_nodes, 0,
157  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
158  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
159 };
160 
161 static void short_usage_sub(void)
162 {
163  ndb_short_usage_sub(NULL);
164  ndb_service_print_options("ndb_mgmd");
165 }
166 
167 static void usage()
168 {
169  ndb_usage(short_usage_sub, load_default_groups, my_long_options);
170 }
171 
172 static char **defaults_argv;
173 
174 static void mgmd_exit(int result)
175 {
176  g_eventLogger->close();
177 
178  /* Free memory allocated by 'load_defaults' */
179  free_defaults(defaults_argv);
180 
181  ndb_end(opt_ndb_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
182 
183  ndb_daemon_exit(result);
184 }
185 
186 #include "../common/util/parse_mask.hpp"
187 
188 static int mgmd_main(int argc, char** argv)
189 {
190  NDB_INIT(argv[0]);
191 
192  printf("MySQL Cluster Management Server %s\n", NDB_VERSION_STRING);
193 
194  ndb_opt_set_usage_funcs(short_usage_sub, usage);
195 
196  load_defaults("my",load_default_groups,&argc,&argv);
197  defaults_argv= argv; /* Must be freed by 'free_defaults' */
198 
199  int ho_error;
200 #ifndef DBUG_OFF
201  opt_debug= IF_WIN("d:t:i:F:o,c:\\ndb_mgmd.trace",
202  "d:t:i:F:o,/tmp/ndb_mgmd.trace");
203 #endif
204 
205  if ((ho_error=handle_options(&argc, &argv, my_long_options,
206  ndb_std_get_one_option)))
207  mgmd_exit(ho_error);
208 
209  if (opts.interactive ||
210  opts.non_interactive ||
211  opts.print_full_config) {
212  opts.daemon= 0;
213  }
214 
215  if (opts.mycnf && opts.config_filename)
216  {
217  fprintf(stderr, "ERROR: Both --mycnf and -f is not supported\n");
218  mgmd_exit(1);
219  }
220 
221  if (opt_nowait_nodes)
222  {
223  int res = parse_mask(opt_nowait_nodes, opts.nowait_nodes);
224  if(res == -2 || (res > 0 && opts.nowait_nodes.get(0)))
225  {
226  fprintf(stderr, "ERROR: Invalid nodeid specified in nowait-nodes: '%s'\n",
227  opt_nowait_nodes);
228  mgmd_exit(1);
229  }
230  else if (res < 0)
231  {
232  fprintf(stderr, "ERROR: Unable to parse nowait-nodes argument: '%s'\n",
233  opt_nowait_nodes);
234  mgmd_exit(1);
235  }
236  }
237 
238  /* Setup use of event logger */
239  g_eventLogger->setCategory(opt_logname);
240 
241  /* Output to console initially */
242  g_eventLogger->createConsoleHandler();
243 
244 #ifdef _WIN32
245  /* Output to Windows event log */
246  g_eventLogger->createEventLogHandler("MySQL Cluster Management Server");
247 #endif
248 
249  if (opts.verbose)
250  g_eventLogger->enable(Logger::LL_ALL); // --verbose turns on everything
251 
256 #if !defined NDB_WIN32
257  signal(SIGPIPE, SIG_IGN);
258 #endif
259 
260  while (!g_StopServer)
261  {
262  mgm= new MgmtSrvr(opts);
263  if (mgm == NULL) {
264  g_eventLogger->critical("Out of memory, couldn't create MgmtSrvr");
265  mgmd_exit(1);
266  }
267 
268  /* Init mgm, load or fetch config */
269  if (!mgm->init()) {
270  delete mgm;
271  mgmd_exit(1);
272  }
273 
274  if (NdbDir::chdir(NdbConfig_get_path(NULL)) != 0)
275  {
276  g_eventLogger->warning("Cannot change directory to '%s', error: %d",
277  NdbConfig_get_path(NULL), errno);
278  // Ignore error
279  }
280 
281  if (opts.daemon)
282  {
283  NodeId localNodeId= mgm->getOwnNodeId();
284  if (localNodeId == 0) {
285  g_eventLogger->error("Couldn't get own node id");
286  delete mgm;
287  mgmd_exit(1);
288  }
289 
290  char *lockfile= NdbConfig_PidFileName(localNodeId);
291  char *logfile= NdbConfig_StdoutFileName(localNodeId);
292  if (ndb_daemonize(lockfile, logfile))
293  {
294  g_eventLogger->error("Couldn't start as daemon, error: '%s'",
295  ndb_daemon_error);
296  mgmd_exit(1);
297  }
298  }
299 
300  /* Start mgm services */
301  if (!mgm->start()) {
302  delete mgm;
303  mgmd_exit(1);
304  }
305 
306  if (opts.interactive) {
307  int port= mgm->getPort();
308  BaseString con_str;
309  if(opts.bind_address)
310  con_str.appfmt("host=%s:%d", opts.bind_address, port);
311  else
312  con_str.appfmt("localhost:%d", port);
313  Ndb_mgmclient com(con_str.c_str(), 1);
314  while(!g_StopServer){
315  if (!read_and_execute(&com, "ndb_mgm> ", 1))
316  g_StopServer = true;
317  }
318  }
319  else
320  {
321  g_eventLogger->info("MySQL Cluster Management Server %s started",
322  NDB_VERSION_STRING);
323 
324  while (!g_StopServer)
325  NdbSleep_MilliSleep(500);
326  }
327 
328  g_eventLogger->info("Shutting down server...");
329  delete mgm;
330  g_eventLogger->info("Shutdown complete");
331 
332  if(g_RestartServer){
333  g_eventLogger->info("Restarting server...");
334  g_RestartServer= g_StopServer= false;
335  }
336  }
337 
338  mgmd_exit(0);
339  return 0;
340 }
341 
342 
343 static void mgmd_stop(void)
344 {
345  g_StopServer= true;
346 }
347 
348 
349 int main(int argc, char** argv)
350 {
351  return ndb_daemon_init(argc, argv, mgmd_main, mgmd_stop,
352  "ndb_mgmd", "MySQL Cluster Management Server");
353 }