1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <ndb_global.h>
19
#include "MgmtSrvr.hpp"
20
#include "EventLogger.hpp"
22
#include "InitConfigFileParser.hpp"
23
#include <SocketServer.hpp>
24
#include "Services.hpp"
26
#include <kernel_types.h>
27
#include <Properties.hpp>
30
#include <NdbDaemon.h>
31
#include <NdbConfig.h>
33
#include <ndb_version.h>
34
#include <ConfigRetriever.hpp>
35
#include <mgmapi_config_parameters.h>
37
#include <NdbAutoPtr.hpp>
39
#include <ndb_mgmclient.hpp>
42
#define DEBUG(x) ndbout << x << endl;
44
const char progname[] = "mgmtsrvr";
45
const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
47
// copied from mysql.cc to get readline
52
#include <readline/readline.h>
53
extern "C" int add_history(const char *command); /* From readline directory */
59
read_and_execute(Ndb_mgmclient* com, const char * prompt, int _try_reconnect)
61
static char *line_read = (char *)NULL;
63
/* If the buffer has already been allocated, return the memory
68
line_read = (char *)NULL;
71
/* Get a line from the user. */
72
line_read = readline (prompt);
73
/* If the line has any text in it, save it on the history. */
74
if (line_read && *line_read)
75
add_history (line_read);
77
static char linebuffer[254];
78
fputs(prompt, stdout);
79
linebuffer[sizeof(linebuffer)-1]=0;
80
line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
81
if (line_read == linebuffer) {
85
line_read= strdup(linebuffer);
88
return com->execute(line_read,_try_reconnect);
93
* @brief Global Variables used in the management server
94
*****************************************************************************/
96
/** Command line arguments */
97
static int opt_daemon; // NOT bool, bool need not be int
98
static int opt_non_interactive;
99
static int opt_interactive;
100
static const char * opt_config_filename= 0;
101
static int opt_mycnf = 0;
107
/** Stuff found in environment or in local config */
109
bool use_specific_ip;
110
char * interface_name;
111
short unsigned int port;
113
/** The Mgmt Server */
114
MgmtSrvr * mgmObject;
116
/** The Socket Server */
117
SocketServer * socketServer;
120
int g_no_nodeid_checks= 0;
121
int g_print_full_config;
122
static MgmGlobals *glob= 0;
124
/******************************************************************************
125
* Function prototypes
126
******************************************************************************/
131
bool g_RestartServer;
132
extern EventLogger g_eventLogger;
134
enum ndb_mgmd_options {
135
OPT_INTERACTIVE = NDB_STD_OPTIONS_LAST,
136
OPT_NO_NODEID_CHECKS,
141
static struct my_option my_long_options[] =
143
NDB_STD_OPTS("ndb_mgmd"),
144
{ "config-file", 'f', "Specify cluster configuration file",
145
&opt_config_filename, &opt_config_filename, 0,
146
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
147
{ "print-full-config", 'P', "Print full config and exit",
148
&g_print_full_config, &g_print_full_config, 0,
149
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
150
{ "daemon", 'd', "Run ndb_mgmd in daemon mode (default)",
151
&opt_daemon, &opt_daemon, 0,
152
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
153
{ "interactive", OPT_INTERACTIVE,
154
"Run interactive. Not supported but provided for testing purposes",
155
&opt_interactive, &opt_interactive, 0,
156
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
157
{ "no-nodeid-checks", OPT_NO_NODEID_CHECKS,
158
"Do not provide any node id checks",
159
&g_no_nodeid_checks, &g_no_nodeid_checks, 0,
160
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
161
{ "nodaemon", OPT_NO_DAEMON,
162
"Don't run as daemon, but don't read from stdin",
163
&opt_non_interactive, &opt_non_interactive, 0,
164
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
166
"Read cluster config from my.cnf",
167
&opt_mycnf, &opt_mycnf, 0,
168
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
169
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
172
static void short_usage_sub(void)
174
printf("Usage: %s [OPTIONS]\n", my_progname);
179
ndb_std_print_version();
180
print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
182
my_print_help(my_long_options);
183
my_print_variables(my_long_options);
189
int main(int argc, char** argv)
194
load_defaults("my",load_default_groups,&argc,&argv);
198
opt_debug= "d:t:O,/tmp/ndb_mgmd.trace";
200
if ((ho_error=handle_options(&argc, &argv, my_long_options,
201
ndb_std_get_one_option)))
205
glob= new MgmGlobals;
207
if (opt_interactive ||
208
opt_non_interactive ||
209
g_print_full_config) {
213
if (opt_mycnf && opt_config_filename)
215
ndbout_c("Both --mycnf and -f is not supported");
219
if (opt_mycnf == 0 && opt_config_filename == 0)
222
if (stat("config.ini", &buf) != -1)
223
opt_config_filename = "config.ini";
226
glob->socketServer = new SocketServer();
228
MgmApiService * mapi = new MgmApiService();
230
glob->mgmObject = new MgmtSrvr(glob->socketServer,
234
if (g_print_full_config)
237
if (glob->mgmObject->init())
240
my_setwd(NdbConfig_get_path(0), MYF(0));
242
glob->localNodeId= glob->mgmObject->getOwnNodeId();
243
if (glob->localNodeId == 0) {
247
glob->port= glob->mgmObject->getPort();
252
glob->interface_name = 0;
253
glob->use_specific_ip = false;
255
if(!glob->use_specific_ip){
256
int count= 5; // no of retries for tryBind
257
while(!glob->socketServer->tryBind(glob->port, glob->interface_name)){
259
NdbSleep_MilliSleep(1000);
262
ndbout_c("Unable to setup port: %s:%d!\n"
263
"Please check if the port is already used,\n"
264
"(perhaps a ndb_mgmd is already running),\n"
265
"and if you are executing on the correct computer",
266
(glob->interface_name ? glob->interface_name : "*"), glob->port);
269
free(glob->interface_name);
270
glob->interface_name = 0;
273
if(!glob->socketServer->setup(mapi, &glob->port, glob->interface_name))
275
ndbout_c("Unable to setup management port: %d!\n"
276
"Please check if the port is already used,\n"
277
"(perhaps a ndb_mgmd is already running),\n"
278
"and if you are executing on the correct computer",
284
if(!glob->mgmObject->check_start()){
285
ndbout_c("Unable to check start management server.");
286
ndbout_c("Probably caused by illegal initial configuration file.");
292
char *lockfile= NdbConfig_PidFileName(glob->localNodeId);
293
char *logfile= NdbConfig_StdoutFileName(glob->localNodeId);
294
NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
296
if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
297
ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
303
signal(SIGPIPE, SIG_IGN);
306
BaseString error_string;
307
if(!glob->mgmObject->start(error_string)){
308
ndbout_c("Unable to start management server.");
309
ndbout_c("Probably caused by illegal initial configuration file.");
310
ndbout_c(error_string.c_str());
315
//glob->mgmObject->saveConfig();
316
mapi->setMgm(glob->mgmObject);
319
BaseString::snprintf(msg, sizeof(msg),
320
"NDB Cluster Management Server. %s", NDB_VERSION_STRING);
322
g_eventLogger.info(msg);
324
BaseString::snprintf(msg, 256, "Id: %d, Command port: %d",
325
glob->localNodeId, glob->port);
327
g_eventLogger.info(msg);
329
g_StopServer = false;
330
g_RestartServer= false;
331
glob->socketServer->startServer();
333
if(opt_interactive) {
335
if(glob->interface_name)
336
con_str.appfmt("host=%s:%d", glob->interface_name, glob->port);
338
con_str.appfmt("localhost:%d", glob->port);
339
Ndb_mgmclient com(con_str.c_str(), 1);
340
while(g_StopServer != true && read_and_execute(&com, "ndb_mgm> ", 1));
343
while(g_StopServer != true)
344
NdbSleep_MilliSleep(500);
348
g_eventLogger.info("Restarting server...");
350
g_eventLogger.info("Shutting down server...");
351
glob->socketServer->stopServer();
352
// We disconnect from the ConfigRetreiver mgmd when we delete glob below
353
glob->socketServer->stopSessions(true);
354
g_eventLogger.info("Shutdown complete");
359
ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
363
ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
367
MgmGlobals::MgmGlobals(){
375
MgmGlobals::~MgmGlobals(){
381
free(interface_name);