1 /*
2 Copyright (c) 2003, 2018, 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 "my_alloc.h"
31 #include "ndbd.hpp"
32 #include "angel.hpp"
33
34 #include "../common/util/parse_mask.hpp"
35 #include "OwnProcessInfo.hpp"
36
37 #include <EventLogger.hpp>
38
39 #define JAM_FILE_ID 485
40
41 extern EventLogger * g_eventLogger;
42
43 static int opt_daemon, opt_no_daemon, opt_foreground,
44 opt_initialstart, opt_verbose;
45 static const char* opt_nowait_nodes = 0;
46 static const char* opt_bind_address = 0;
47 static int opt_report_fd;
48 static int opt_initial;
49 static int opt_no_start;
50 static unsigned opt_allocated_nodeid;
51 static int opt_angel_pid;
52 static int opt_retries;
53 static int opt_delay;
54 static unsigned long opt_logbuffer_size;
55
56 extern NdbNodeBitmask g_nowait_nodes;
57
58 static struct my_option my_long_options[] =
59 {
60 NDB_STD_OPTS("ndbd"),
61 { "initial", NDB_OPT_NOSHORT,
62 "Perform initial start of ndbd, including cleaning the file system. "
63 "Consult documentation before using this",
64 (uchar**) &opt_initial, (uchar**) &opt_initial, 0,
65 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
66 { "nostart", 'n',
67 "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd",
68 (uchar**) &opt_no_start, (uchar**) &opt_no_start, 0,
69 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
70 { "daemon", 'd', "Start ndbd as daemon (default)",
71 (uchar**) &opt_daemon, (uchar**) &opt_daemon, 0,
72 GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
73 { "nodaemon", NDB_OPT_NOSHORT,
74 "Do not start ndbd as daemon, provided for testing purposes",
75 (uchar**) &opt_no_daemon, (uchar**) &opt_no_daemon, 0,
76 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
77 { "foreground", NDB_OPT_NOSHORT,
78 "Run real ndbd in foreground, provided for debugging purposes"
79 " (implies --nodaemon)",
80 (uchar**) &opt_foreground, (uchar**) &opt_foreground, 0,
81 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
82 { "nowait-nodes", NDB_OPT_NOSHORT,
83 "Nodes that will not be waited for during start",
84 (uchar**) &opt_nowait_nodes, (uchar**) &opt_nowait_nodes, 0,
85 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
86 { "initial-start", NDB_OPT_NOSHORT,
87 "Perform a partial initial start of the cluster. "
88 "Each node should be started with this option, as well as --nowait-nodes",
89 (uchar**) &opt_initialstart, (uchar**) &opt_initialstart, 0,
90 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
91 { "bind-address", NDB_OPT_NOSHORT,
92 "Local bind address",
93 (uchar**) &opt_bind_address, (uchar**) &opt_bind_address, 0,
94 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
95 { "verbose", 'v',
96 "Write more log messages",
97 (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0,
98 GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
99 { "report-fd", 256,
100 "INTERNAL: fd where to write extra shutdown status",
101 (uchar**) &opt_report_fd, (uchar**) &opt_report_fd, 0,
102 GET_UINT, REQUIRED_ARG, 0, 0, INT_MAX, 0, 0, 0 },
103 { "allocated-nodeid", 256,
104 "INTERNAL: nodeid allocated by angel process",
105 (uchar**) &opt_allocated_nodeid, (uchar**) &opt_allocated_nodeid, 0,
106 GET_UINT, REQUIRED_ARG, 0, 0, UINT_MAX, 0, 0, 0 },
107 { "angel-pid", NDB_OPT_NOSHORT,
108 "INTERNAL: angel process id",
109 (uchar**) &opt_angel_pid, (uchar **) &opt_angel_pid, 0,
110 GET_UINT, REQUIRED_ARG, 0, 0, UINT_MAX, 0, 0, 0 },
111 { "connect-retries", 'r',
112 "Number of times mgmd is contacted at start. -1: eternal retries",
113 (uchar**) &opt_retries, (uchar**) &opt_retries, 0,
114 GET_INT, REQUIRED_ARG, 12, -1, 65535, 0, 0, 0 },
115 { "connect-delay", NDB_OPT_NOSHORT,
116 "Number of seconds between each connection attempt",
117 (uchar**) &opt_delay, (uchar**) &opt_delay, 0,
118 GET_INT, REQUIRED_ARG, 5, 0, 3600, 0, 0, 0 },
119 { "logbuffer-size", NDB_OPT_NOSHORT,
120 "Size of the log buffer for data node ndb_x_out.log",
121 (uchar**) &opt_logbuffer_size, (uchar**) &opt_logbuffer_size, 0,
122 GET_ULONG, REQUIRED_ARG, 32768, 2048, ULONG_MAX, 0, 0, 0
123 },
124 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
125 };
126
127 const char *load_default_groups[]= { "mysql_cluster", "ndbd", 0 };
128
129
short_usage_sub(void)130 static void short_usage_sub(void)
131 {
132 ndb_short_usage_sub(NULL);
133 ndb_service_print_options("ndbd");
134 }
135
136 /**
137 * C++ Standard 3.6.1/3:
138 * The function main shall not be used (3.2) within a program.
139 *
140 * So call "main" "real_main" to avoid this rule...
141 */
142 int
real_main(int argc,char ** argv)143 real_main(int argc, char** argv)
144 {
145 NDB_INIT(argv[0]);
146 Ndb_opts::release(); // because ndbd can fork and call real_main() again
147 Ndb_opts opts(argc, argv, my_long_options, load_default_groups);
148
149 // Print to stdout/console
150 g_eventLogger->createConsoleHandler();
151
152 #ifdef _WIN32
153 /* Output to Windows event log */
154 g_eventLogger->createEventLogHandler("MySQL Cluster Data Node Daemon");
155 #endif
156
157 g_eventLogger->setCategory("ndbd");
158
159 // Turn on max loglevel for startup messages
160 g_eventLogger->m_logLevel.setLogLevel(LogLevel::llStartUp, 15);
161
162 opts.set_usage_funcs(short_usage_sub);
163
164 #ifndef DBUG_OFF
165 opt_debug= "d:t:O,/tmp/ndbd.trace";
166 #endif
167
168 // Save the original program name and arguments for angel
169 const char* progname = argv[0];
170 Vector<BaseString> original_args;
171 for (int i = 0; i < argc; i++)
172 {
173 if (ndb_is_load_default_arg_separator(argv[i]))
174 continue;
175 original_args.push_back(argv[i]);
176 }
177
178 int ho_error;
179 if ((ho_error=opts.handle_options()))
180 exit(ho_error);
181
182 if (opt_no_daemon || opt_foreground) {
183 // --nodaemon or --forground implies --daemon=0
184 opt_daemon= 0;
185 }
186
187 // Turn on debug printouts if --verbose
188 if (opt_verbose)
189 g_eventLogger->enable(Logger::LL_DEBUG);
190
191 if (opt_nowait_nodes)
192 {
193 int res = parse_mask(opt_nowait_nodes, g_nowait_nodes);
194 if(res == -2 || (res > 0 && g_nowait_nodes.get(0)))
195 {
196 g_eventLogger->error("Invalid nodeid specified in nowait-nodes: %s",
197 opt_nowait_nodes);
198 exit(-1);
199 }
200 else if (res < 0)
201 {
202 g_eventLogger->error("Unable to parse nowait-nodes argument: %s",
203 opt_nowait_nodes);
204 exit(-1);
205 }
206 }
207
208 if(opt_angel_pid)
209 {
210 setOwnProcessInfoAngelPid(opt_angel_pid);
211 }
212
213 if (opt_foreground ||
214 opt_allocated_nodeid ||
215 opt_report_fd)
216 {
217 /**
218 This is where we start running the real data node process after
219 reading options. This function will never return.
220 */
221 ndbd_run(opt_foreground, opt_report_fd,
222 opt_ndb_connectstring, opt_ndb_nodeid, opt_bind_address,
223 opt_no_start, opt_initial, opt_initialstart,
224 opt_allocated_nodeid, opt_retries, opt_delay,
225 opt_logbuffer_size);
226 }
227
228 /**
229 The angel process takes care of automatic restarts, by default this is
230 the default to have an angel process. When an angel process is used the
231 program will enter into angel_run from where we fork off the real data
232 node process, the real process will always have opt_allocated_nodeid
233 set since we don't want the nodeid to change between restarts.
234 */
235 angel_run(progname,
236 original_args,
237 opt_ndb_connectstring,
238 opt_ndb_nodeid,
239 opt_bind_address,
240 opt_initial,
241 opt_no_start,
242 opt_daemon,
243 opt_retries,
244 opt_delay);
245
246 return 1; // Never reached
247 }
248
249 int
main(int argc,char ** argv)250 main(int argc, char** argv)
251 {
252 return ndb_daemon_init(argc, argv, real_main, angel_stop,
253 "ndbd", "MySQL Cluster Data Node Daemon");
254 }
255