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, 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 #include <ndb_global.h>
26 #include <ndb_opts.h>
27 #include <kernel/NodeBitmask.hpp>
28 #include <portlib/ndb_daemon.h>
29 
30 #include "ndbd.hpp"
31 #include "angel.hpp"
32 
33 #include <EventLogger.hpp>
34 extern EventLogger * g_eventLogger;
35 
36 static int opt_daemon, opt_no_daemon, opt_foreground,
37   opt_initialstart, opt_verbose;
38 static const char* opt_nowait_nodes = 0;
39 static const char* opt_bind_address = 0;
40 static int opt_report_fd;
41 static int opt_initial;
42 static int opt_no_start;
43 static unsigned opt_allocated_nodeid;
44 
45 extern NdbNodeBitmask g_nowait_nodes;
46 
47 static struct my_option my_long_options[] =
48 {
49   NDB_STD_OPTS("ndbd"),
50   { "initial", NDB_OPT_NOSHORT,
51     "Perform initial start of ndbd, including cleaning the file system. "
52     "Consult documentation before using this",
53     (uchar**) &opt_initial, (uchar**) &opt_initial, 0,
54     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
55   { "nostart", 'n',
56     "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd",
57     (uchar**) &opt_no_start, (uchar**) &opt_no_start, 0,
58     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
59   { "daemon", 'd', "Start ndbd as daemon (default)",
60     (uchar**) &opt_daemon, (uchar**) &opt_daemon, 0,
61     GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
62   { "nodaemon", NDB_OPT_NOSHORT,
63     "Do not start ndbd as daemon, provided for testing purposes",
64     (uchar**) &opt_no_daemon, (uchar**) &opt_no_daemon, 0,
65     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
66   { "foreground", NDB_OPT_NOSHORT,
67     "Run real ndbd in foreground, provided for debugging purposes"
68     " (implies --nodaemon)",
69     (uchar**) &opt_foreground, (uchar**) &opt_foreground, 0,
70     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
71   { "nowait-nodes", NDB_OPT_NOSHORT,
72     "Nodes that will not be waited for during start",
73     (uchar**) &opt_nowait_nodes, (uchar**) &opt_nowait_nodes, 0,
74     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
75   { "initial-start", NDB_OPT_NOSHORT,
76     "Perform a partial initial start of the cluster.  "
77     "Each node should be started with this option, as well as --nowait-nodes",
78     (uchar**) &opt_initialstart, (uchar**) &opt_initialstart, 0,
79     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
80   { "bind-address", NDB_OPT_NOSHORT,
81     "Local bind address",
82     (uchar**) &opt_bind_address, (uchar**) &opt_bind_address, 0,
83     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
84   { "verbose", 'v',
85     "Write more log messages",
86     (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0,
87     GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
88   { "report-fd", 256,
89     "INTERNAL: fd where to write extra shutdown status",
90     (uchar**) &opt_report_fd, (uchar**) &opt_report_fd, 0,
91     GET_UINT, REQUIRED_ARG, 0, 0, ~0, 0, 0, 0 },
92   { "allocated-nodeid", 256,
93     "INTERNAL: nodeid allocated by angel process",
94     (uchar**) &opt_allocated_nodeid, (uchar**) &opt_allocated_nodeid, 0,
95     GET_UINT, REQUIRED_ARG, 0, 0, ~0, 0, 0, 0 },
96   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
97 };
98 
99 const char *load_default_groups[]= { "mysql_cluster", "ndbd", 0 };
100 
101 
short_usage_sub(void)102 static void short_usage_sub(void)
103 {
104   ndb_short_usage_sub(NULL);
105   ndb_service_print_options("ndbd");
106 }
107 
usage()108 static void usage()
109 {
110   ndb_usage(short_usage_sub, load_default_groups, my_long_options);
111 }
112 
113 extern int g_ndb_init_need_monotonic;
114 
115 #include "../common/util/parse_mask.hpp"
116 
117 /**
118  * C++ Standard 3.6.1/3:
119  *  The function main shall not be used (3.2) within a program.
120  *
121  * So call "main" "real_main" to avoid this rule...
122  */
123 int
real_main(int argc,char ** argv)124 real_main(int argc, char** argv)
125 {
126   g_ndb_init_need_monotonic = 1;
127   NDB_INIT(argv[0]);
128 
129   // Print to stdout/console
130   g_eventLogger->createConsoleHandler();
131 
132 #ifdef _WIN32
133   /* Output to Windows event log */
134   g_eventLogger->createEventLogHandler("MySQL Cluster Data Node Daemon");
135 #endif
136 
137   g_eventLogger->setCategory("ndbd");
138 
139   // Turn on max loglevel for startup messages
140   g_eventLogger->m_logLevel.setLogLevel(LogLevel::llStartUp, 15);
141 
142   ndb_opt_set_usage_funcs(short_usage_sub, usage);
143   load_defaults("my",load_default_groups,&argc,&argv);
144 
145 #ifndef DBUG_OFF
146   opt_debug= "d:t:O,/tmp/ndbd.trace";
147 #endif
148 
149   // Save the original program name and arguments for angel
150   const char* progname = argv[0];
151   Vector<BaseString> original_args;
152   for (int i = 0; i < argc; i++)
153   {
154     if (ndb_is_load_default_arg_separator(argv[i]))
155       continue;
156     original_args.push_back(argv[i]);
157   }
158 
159   int ho_error;
160   if ((ho_error=handle_options(&argc, &argv, my_long_options,
161                                ndb_std_get_one_option)))
162     exit(ho_error);
163 
164   if (opt_no_daemon || opt_foreground) {
165     // --nodaemon or --forground implies --daemon=0
166     opt_daemon= 0;
167   }
168 
169   // Turn on debug printouts if --verbose
170   if (opt_verbose)
171     g_eventLogger->enable(Logger::LL_DEBUG);
172 
173   if (opt_nowait_nodes)
174   {
175     int res = parse_mask(opt_nowait_nodes, g_nowait_nodes);
176     if(res == -2 || (res > 0 && g_nowait_nodes.get(0)))
177     {
178       g_eventLogger->error("Invalid nodeid specified in nowait-nodes: %s",
179                            opt_nowait_nodes);
180       exit(-1);
181     }
182     else if (res < 0)
183     {
184       g_eventLogger->error("Unable to parse nowait-nodes argument: %s",
185                            opt_nowait_nodes);
186       exit(-1);
187     }
188   }
189 
190   if (opt_foreground ||
191       opt_allocated_nodeid ||
192       opt_report_fd)
193   {
194     ndbd_run(opt_foreground, opt_report_fd,
195              opt_ndb_connectstring, opt_ndb_nodeid, opt_bind_address,
196              opt_no_start, opt_initial, opt_initialstart,
197              opt_allocated_nodeid);
198   }
199 
200   angel_run(progname,
201             original_args,
202             opt_ndb_connectstring,
203             opt_ndb_nodeid,
204             opt_bind_address,
205             opt_initial,
206             opt_no_start,
207             opt_daemon);
208 
209   return 1; // Never reached
210 }
211 
212 int
main(int argc,char ** argv)213 main(int argc, char** argv)
214 {
215   return ndb_daemon_init(argc, argv, real_main, angel_stop,
216                          "ndbd", "MySQL Cluster Data Node Daemon");
217 }
218