main.cpp 9.75 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

17
#include <ndb_global.h>
unknown's avatar
unknown committed
18
#include <my_sys.h>
19

20 21
#include "MgmtSrvr.hpp"
#include "EventLogger.hpp"
unknown's avatar
unknown committed
22
#include <Config.hpp>
23 24 25 26 27 28 29 30 31 32 33 34 35
#include "InitConfigFileParser.hpp"
#include <SocketServer.hpp>
#include "Services.hpp"
#include <version.h>
#include <kernel_types.h>
#include <Properties.hpp>
#include <NdbOut.hpp>
#include <NdbMain.h>
#include <NdbDaemon.h>
#include <NdbConfig.h>
#include <NdbHost.h>
#include <ndb_version.h>
#include <ConfigRetriever.hpp>
36
#include <mgmapi_config_parameters.h>
37 38
#include <getarg.h>

39 40
#include <NdbAutoPtr.hpp>

41 42 43 44 45 46
#if defined NDB_OSE || defined NDB_SOFTOSE
#include <efs.h>
#else
#include "CommandInterpreter.hpp"
#endif

unknown's avatar
unknown committed
47
#undef DEBUG
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#define DEBUG(x) ndbout << x << endl;

const char progname[] = "mgmtsrvr";


/**
 * @struct  MgmGlobals
 * @brief   Global Variables used in the management server
 ******************************************************************************/
struct MgmGlobals {
  MgmGlobals();
  ~MgmGlobals();
  
  /** Command line arguments  */
  int daemon;   // NOT bool, bool need not be int
  int non_interactive;
unknown's avatar
unknown committed
64
  int interactive;
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  const char * config_filename;
  const char * local_config_filename;
  
  /** Stuff found in environment or in local config  */
  NodeId localNodeId;
  bool use_specific_ip;
  char * interface_name;
  int port;
  int port_stats;
  
  /** The configuration of the cluster */
  Config * cluster_config;
  
  /** The Mgmt Server */
  MgmtSrvr * mgmObject;
  
  /** The Socket Server */
  SocketServer * socketServer;
};

static MgmGlobals glob;


/******************************************************************************
 * Function prototypes
 ******************************************************************************/
static bool readLocalConfig();
static bool readGlobalConfig();

/**
 * Global variables
 */
bool g_StopServer;
extern EventLogger g_EventLogger;

extern int global_mgmt_server_check;
int _print_version = 0;
unknown's avatar
unknown committed
102 103 104
#ifndef DBUG_OFF
const char *debug_option= 0;
#endif
105 106

struct getargs args[] = {
107 108 109
  { "version", 'v', arg_flag, &_print_version,
    "Print ndb_mgmd version"},
  { "config-file", 'c', arg_string, &glob.config_filename,
110
    "Specify cluster configuration file (will default use config.ini if available)", "filename" },
unknown's avatar
unknown committed
111 112
#ifndef DBUG_OFF
  { "debug", 0, arg_string, &debug_option,
113
    "Specify debug options e.g. d:t:i:o,out.trace", "options" },
unknown's avatar
unknown committed
114
#endif
115
  { "daemon", 'd', arg_flag, &glob.daemon,
unknown's avatar
unknown committed
116
    "Run ndb_mgmd in daemon mode (default)" },
117
  { NULL, 'l', arg_string, &glob.local_config_filename,
118
    "Specify configuration file connect string (will default use Ndb.cfg if available)",
119
    "filename" },
unknown's avatar
unknown committed
120 121
  { "interactive", 0, arg_flag, &glob.interactive,
    "Run interactive. Not supported but provided for testing purposes", "" },
unknown's avatar
unknown committed
122
  { "nodaemon", 0, arg_flag, &glob.non_interactive,
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    "Don't run as daemon, but don't read from stdin", "non-interactive" }
};

int num_args = sizeof(args) / sizeof(args[0]);

/*
 *  MAIN 
 */
NDB_MAIN(mgmsrv){
  /**
   * OSE specific. Enable shared ownership of file system resources. 
   * This is needed in order to use the cluster log since the events 
   * from the cluster is written from the 'ndb_receive'(NDBAPI) thread/process.
   */
#if defined NDB_OSE || defined NDB_SOFTOSE
  efs_segment_share();
#endif

  global_mgmt_server_check = 1;

  int optind = 0;
  if(getarg(args, num_args, argc, argv, &optind)) {
    arg_printusage(args, num_args, progname, "");
    exit(1);
  }

unknown's avatar
unknown committed
149 150 151 152 153
  if (glob.interactive ||
      glob.non_interactive) {
    glob.daemon= 0;
  }

154
  my_init();
155
#ifndef DBUG_OFF
unknown's avatar
unknown committed
156 157 158 159
  if (debug_option)
    DBUG_PUSH(debug_option);
#endif

160 161 162 163 164 165
  if (_print_version) {
    ndbPrintVersion();
    exit(0);
  }

  if(glob.config_filename == NULL) {
unknown's avatar
unknown committed
166
    glob.config_filename= "config.ini";
167 168
  }
  glob.socketServer = new SocketServer();
unknown's avatar
unknown committed
169

170
  MgmApiService * mapi = new MgmApiService();
unknown's avatar
unknown committed
171

172 173 174 175 176 177 178 179 180 181
  MgmStatService * mstat = new MgmStatService();

  /****************************
   * Read configuration files *
   ****************************/
  if (!readLocalConfig())
    goto error_end;
  if (!readGlobalConfig())
    goto error_end;

unknown's avatar
unknown committed
182 183 184 185 186 187
  glob.mgmObject = new MgmtSrvr(glob.localNodeId,
				BaseString(glob.config_filename),
				BaseString(glob.local_config_filename == 0 ?
					   "" : glob.local_config_filename),
				glob.cluster_config);

unknown's avatar
unknown committed
188 189
  chdir(NdbConfig_get_path(0));

unknown's avatar
unknown committed
190 191 192
  glob.cluster_config = 0;
  glob.localNodeId= glob.mgmObject->getOwnNodeId();

unknown's avatar
unknown committed
193
  if (glob.localNodeId == 0) {
unknown's avatar
unknown committed
194
    goto error_end;
unknown's avatar
unknown committed
195
  }
unknown's avatar
unknown committed
196 197 198 199

  glob.port= glob.mgmObject->getPort();

  if (glob.port == 0)
200
    goto error_end;
unknown's avatar
unknown committed
201 202 203 204

  glob.interface_name = 0;
  glob.use_specific_ip = false;

205
  if(!glob.use_specific_ip){
206 207 208 209 210 211
    int count= 5; // no of retries for tryBind
    while(!glob.socketServer->tryBind(glob.port, glob.interface_name)){
      if (--count > 0) {
	NdbSleep_MilliSleep(1000);
	continue;
      }
212 213
      ndbout_c("Unable to setup port: %s:%d!\n"
	       "Please check if the port is already used,\n"
214
	       "(perhaps a ndb_mgmd is already running),\n"
215
	       "and if you are executing on the correct computer", 
unknown's avatar
unknown committed
216
	       (glob.interface_name ? glob.interface_name : "*"), glob.port);
217 218 219 220 221 222 223 224 225
      goto error_end;
    }
    free(glob.interface_name);
    glob.interface_name = 0;
  }

  if(!glob.socketServer->setup(mapi, glob.port, glob.interface_name)){
    ndbout_c("Unable to setup management port: %d!\n"
	     "Please check if the port is already used,\n"
226
	     "(perhaps a ndb_mgmd is already running),\n"
227 228 229 230 231 232 233 234 235 236 237 238 239 240
	     "and if you are executing on the correct computer", 
	     glob.port);
    delete mapi;
    goto error_end;
  }
  
  if(!glob.socketServer->setup(mstat, glob.port_stats, glob.interface_name)){
    ndbout_c("Unable to setup statistic port: %d!\nPlease check if the port"
	     " is already used.", glob.port_stats);
    delete mstat;
    goto error_end;
  }

  if(!glob.mgmObject->check_start()){
unknown's avatar
unknown committed
241
    ndbout_c("Unable to check start management server.");
242 243 244 245 246 247
    ndbout_c("Probably caused by illegal initial configuration file.");
    goto error_end;
  }

  if (glob.daemon) {
    // Become a daemon
248 249 250 251
    char *lockfile= NdbConfig_PidFileName(glob.localNodeId);
    char *logfile=  NdbConfig_StdoutFileName(glob.localNodeId);
    NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);

252 253 254 255 256 257
    if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
      ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
      return 1;
    }
  }

unknown's avatar
unknown committed
258
  signal(SIGPIPE, SIG_IGN);
259 260 261 262 263 264 265 266
  {
    BaseString error_string;
    if(!glob.mgmObject->start(error_string)){
      ndbout_c("Unable to start management server.");
      ndbout_c("Probably caused by illegal initial configuration file.");
      ndbout_c(error_string.c_str());
      goto error_end;
    }
267 268 269 270 271 272 273 274 275 276 277 278 279 280
  }

  //glob.mgmObject->saveConfig();

  mstat->setMgm(glob.mgmObject);
  mapi->setMgm(glob.mgmObject);
  glob.mgmObject->setStatisticsListner(mstat);

  char msg[256];
  snprintf(msg, sizeof(msg),
	   "NDB Cluster Management Server. %s", NDB_VERSION_STRING);
  ndbout_c(msg);
  g_EventLogger.info(msg);

unknown's avatar
unknown committed
281 282
  snprintf(msg, 256, "Id: %d, Command port: %d, Statistics port: %d",
	   glob.localNodeId, glob.port, glob.port_stats);
283 284 285 286 287 288 289
  ndbout_c(msg);
  g_EventLogger.info(msg);
  
  g_StopServer = false;
  glob.socketServer->startServer();

#if ! defined NDB_OSE && ! defined NDB_SOFTOSE
unknown's avatar
unknown committed
290
  if(glob.interactive) {
291 292 293 294 295 296 297 298 299
    CommandInterpreter com(* glob.mgmObject);
    while(com.readAndExecute());
  } else 
#endif
    {
      while(g_StopServer != true)
	NdbSleep_MilliSleep(500);
    }
  
300
  g_EventLogger.info("Shutting down server...");
301 302
  glob.socketServer->stopServer();
  glob.socketServer->stopSessions();
303
  g_EventLogger.info("Shutdown complete");
304 305 306 307 308 309 310 311 312 313 314 315 316
  return 0;
 error_end:
  return 1;
}

MgmGlobals::MgmGlobals(){
  // Default values
  port = 0;
  port_stats = 0;
  config_filename = NULL;
  local_config_filename = NULL;
  interface_name = 0;
  cluster_config = 0;
unknown's avatar
unknown committed
317
  daemon = 1;
318
  non_interactive = 0;
unknown's avatar
unknown committed
319
  interactive = 0;
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
  socketServer = 0;
  mgmObject = 0;
}

MgmGlobals::~MgmGlobals(){
  if (socketServer)
    delete socketServer;
  if (mgmObject)
    delete mgmObject;
  if (cluster_config) 
    delete cluster_config;
  if (interface_name)
    free(interface_name);
}

/**
 * @fn      readLocalConfig
 * @param   glob : Global variables
 * @return  true if success, false otherwise.
 *
 * How to get LOCAL CONFIGURATION FILE:
 * 1. Use local config file name (-l)
 * 2. Use environment NDB_HOME + Ndb.cfg
 *    If NDB_HOME is not set this results in reading from local dir
 */
static bool
readLocalConfig(){
  // Read local config file
unknown's avatar
unknown committed
348
  LocalConfig lc;
349 350
  if(!lc.init(glob.local_config_filename)){
    lc.printError();
351
    return false;
352
  }
353
  
unknown's avatar
unknown committed
354
  glob.localNodeId = lc._ownNodeId;
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
  return true;
}


/**
 * @fn      readGlobalConfig
 * @param   glob : Global variables
 * @return  true if success, false otherwise.
 *
 * How to get the GLOBAL CONFIGURATION:
 * 1. Use config file name (this is a text file)(-c)
 * 2. Use name from line 2 of local config file, ex: file:///c/ndb/Ndb_cfg.bin
 */
static bool
readGlobalConfig() {
  if(glob.config_filename == NULL)
    return false;

  /* Use config file */
374 375 376
  InitConfigFileParser parser;
  glob.cluster_config = parser.parseConfig(glob.config_filename);
  if(glob.cluster_config == 0){
unknown's avatar
unknown committed
377
    return false;
378 379 380
  }
  return true;
}