MgmtSrvr.cpp 67.9 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>
18
#include <my_pthread.h>
19

20 21
#include "MgmtSrvr.hpp"
#include "MgmtErrorReporter.hpp"
22
#include <ConfigRetriever.hpp>
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

#include <NdbOut.hpp>
#include <NdbApiSignal.hpp>
#include <kernel_types.h>
#include <RefConvert.hpp>
#include <BlockNumbers.h>
#include <GlobalSignalNumbers.h>
#include <signaldata/TestOrd.hpp>
#include <signaldata/TamperOrd.hpp>
#include <signaldata/StartOrd.hpp>
#include <signaldata/ApiVersion.hpp>
#include <signaldata/ResumeReq.hpp>
#include <signaldata/SetLogLevelOrd.hpp>
#include <signaldata/EventSubscribeReq.hpp>
#include <signaldata/EventReport.hpp>
#include <signaldata/DumpStateOrd.hpp>
#include <signaldata/BackupSignalData.hpp>
#include <signaldata/GrepImpl.hpp>
#include <signaldata/ManagementServer.hpp>
42 43
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/NodeFailRep.hpp>
44 45 46 47 48
#include <NdbSleep.h>
#include <EventLogger.hpp>
#include <DebuggerNames.hpp>
#include <ndb_version.h>

tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
49
#include <SocketServer.hpp>
50 51
#include <NdbConfig.h>

52 53
#include <NdbAutoPtr.hpp>

54 55
#include <ndberror.h>

56 57 58
#include <mgmapi.h>
#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters.h>
joreland@mysql.com's avatar
joreland@mysql.com committed
59
#include <m_string.h>
60

61 62
#include <SignalSender.hpp>

63 64 65
extern bool g_StopServer;
extern bool g_RestartServer;

66 67 68 69 70 71 72
//#define MGM_SRV_DEBUG
#ifdef MGM_SRV_DEBUG
#define DEBUG(x) do ndbout << x << endl; while(0)
#else
#define DEBUG(x)
#endif

73 74 75 76 77 78 79 80 81 82
#define INIT_SIGNAL_SENDER(ss,nodeId) \
  SignalSender ss(theFacade); \
  ss.lock(); /* lock will be released on exit */ \
  {\
    int result = okToSendTo(nodeId, true);\
    if (result != 0) {\
      return result;\
    }\
  }

tomas@poseidon.(none)'s avatar
tomas@poseidon.(none) committed
83
extern int global_flag_send_heartbeat_now;
84
extern int g_no_nodeid_checks;
85 86 87 88 89 90 91 92 93 94 95 96
extern my_bool opt_core;

static void require(bool v)
{
  if(!v)
  {
    if (opt_core)
      abort();
    else
      exit(-1);
  }
}
tomas@poseidon.(none)'s avatar
tomas@poseidon.(none) committed
97

98 99 100 101 102 103 104 105
void *
MgmtSrvr::logLevelThread_C(void* m)
{
  MgmtSrvr *mgm = (MgmtSrvr*)m;
  mgm->logLevelThreadRun();
  return 0;
}

106
extern EventLogger g_eventLogger;
107

joreland@mysql.com's avatar
joreland@mysql.com committed
108 109 110 111 112 113 114 115 116 117
static NdbOut&
operator<<(NdbOut& out, const LogLevel & ll)
{
  out << "[LogLevel: ";
  for(size_t i = 0; i<LogLevel::LOGLEVEL_CATEGORIES; i++)
    out << ll.getLogLevel((LogLevel::EventCategory)i) << " ";
  out << "]";
  return out;
}

118 119 120 121
void
MgmtSrvr::logLevelThreadRun() 
{
  while (!_isStopThread) {
joreland@mysql.com's avatar
joreland@mysql.com committed
122 123 124 125
    /**
     * Handle started nodes
     */
    EventSubscribeReq req;
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
126
    req = m_event_listner[0].m_logLevel;
joreland@mysql.com's avatar
joreland@mysql.com committed
127
    req.blockRef = _ownReference;
128

joreland@mysql.com's avatar
joreland@mysql.com committed
129 130 131 132 133 134 135
    SetLogLevelOrd ord;
    
    m_started_nodes.lock();
    while(m_started_nodes.size() > 0){
      Uint32 node = m_started_nodes[0];
      m_started_nodes.erase(0, false);
      m_started_nodes.unlock();
136

joreland@mysql.com's avatar
joreland@mysql.com committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
      setEventReportingLevelImpl(node, req);
      
      ord = m_nodeLogLevel[node];
      setNodeLogLevelImpl(node, ord);
      
      m_started_nodes.lock();
    }				 
    m_started_nodes.unlock();
    
    m_log_level_requests.lock();
    while(m_log_level_requests.size() > 0){
      req = m_log_level_requests[0];
      m_log_level_requests.erase(0, false);
      m_log_level_requests.unlock();
      
joreland@mysql.com's avatar
joreland@mysql.com committed
152 153 154
      LogLevel tmp;
      tmp = req;
      
joreland@mysql.com's avatar
joreland@mysql.com committed
155 156 157 158 159 160 161 162 163 164
      if(req.blockRef == 0){
	req.blockRef = _ownReference;
	setEventReportingLevelImpl(0, req);
      } else {
	ord = req;
	setNodeLogLevelImpl(req.blockRef, ord);
      }
      m_log_level_requests.lock();
    }      
    m_log_level_requests.unlock();
165
    NdbSleep_MilliSleep(_logLevelThreadSleep);  
joreland@mysql.com's avatar
joreland@mysql.com committed
166
  }
167 168 169 170 171
}

void
MgmtSrvr::startEventLog() 
{
172 173
  NdbMutex_Lock(m_configMutex);

174
  g_eventLogger.setCategory("MgmSrvr");
175

176 177 178 179 180 181
  ndb_mgm_configuration_iterator 
    iter(* _config->m_configValues, CFG_SECTION_NODE);

  if(iter.find(CFG_NODE_ID, _ownNodeId) != 0){
    NdbMutex_Unlock(m_configMutex);
    return;
182 183 184
  }
  
  const char * tmp;
185 186
  char errStr[100];
  int err= 0;
187
  BaseString logdest;
188 189 190
  char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId);
  NdbAutoPtr<char> tmp_aptr(clusterLog);

191
  if(iter.get(CFG_LOG_DESTINATION, &tmp) == 0){
192 193
    logdest.assign(tmp);
  }
194
  NdbMutex_Unlock(m_configMutex);
195
  
196
  if(logdest.length() == 0 || logdest == "") {
197 198
    logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6", 
		   clusterLog);
199
  }
200 201
  errStr[0]='\0';
  if(!g_eventLogger.addHandler(logdest, &err, sizeof(errStr), errStr)) {
202
    ndbout << "Warning: could not add log destination \""
203 204 205 206 207 208 209 210
           << logdest.c_str() << "\". Reason: ";
    if(err)
      ndbout << strerror(err);
    if(err && errStr[0]!='\0')
      ndbout << ", ";
    if(errStr[0]!='\0')
      ndbout << errStr;
    ndbout << endl;
211 212 213 214 215 216 217 218 219 220 221 222 223
  }
}

void 
MgmtSrvr::stopEventLog() 
{
  // Nothing yet
}

class ErrorItem 
{
public:
  int _errorCode;
joreland@mysql.com's avatar
joreland@mysql.com committed
224
  const char * _errorText;
225 226 227
};

bool
228
MgmtSrvr::setEventLogFilter(int severity, int enable)
229 230
{
  Logger::LoggerLevel level = (Logger::LoggerLevel)severity;
231
  if (enable > 0) {
232
    g_eventLogger.enable(level);
233
  } else if (enable == 0) {
234 235 236
    g_eventLogger.disable(level);
  } else if (g_eventLogger.isEnable(level)) {
    g_eventLogger.disable(level);
237
  } else {
238
    g_eventLogger.enable(level);
239
  }
240
  return g_eventLogger.isEnable(level);
241 242 243 244 245
}

bool 
MgmtSrvr::isEventLogFilterEnabled(int severity) 
{
246
  return g_eventLogger.isEnable((Logger::LoggerLevel)severity);
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
}

static ErrorItem errorTable[] = 
{
  {MgmtSrvr::NO_CONTACT_WITH_PROCESS, "No contact with the process (dead ?)."},
  {MgmtSrvr::PROCESS_NOT_CONFIGURED, "The process is not configured."},
  {MgmtSrvr::WRONG_PROCESS_TYPE, 
   "The process has wrong type. Expected a DB process."},
  {MgmtSrvr::COULD_NOT_ALLOCATE_MEMORY, "Could not allocate memory."},
  {MgmtSrvr::SEND_OR_RECEIVE_FAILED, "Send to process or receive failed."},
  {MgmtSrvr::INVALID_LEVEL, "Invalid level. Should be between 1 and 30."},
  {MgmtSrvr::INVALID_ERROR_NUMBER, "Invalid error number. Should be >= 0."},
  {MgmtSrvr::INVALID_TRACE_NUMBER, "Invalid trace number."},
  {MgmtSrvr::NOT_IMPLEMENTED, "Not implemented."},
  {MgmtSrvr::INVALID_BLOCK_NAME, "Invalid block name"},

  {MgmtSrvr::CONFIG_PARAM_NOT_EXIST, 
   "The configuration parameter does not exist for the process type."},
  {MgmtSrvr::CONFIG_PARAM_NOT_UPDATEABLE, 
   "The configuration parameter is not possible to update."},
  {MgmtSrvr::VALUE_WRONG_FORMAT_INT_EXPECTED, 
   "Incorrect value. Expected integer."},
  {MgmtSrvr::VALUE_TOO_LOW, "Value is too low."},
  {MgmtSrvr::VALUE_TOO_HIGH, "Value is too high."},
  {MgmtSrvr::VALUE_WRONG_FORMAT_BOOL_EXPECTED, 
   "Incorrect value. Expected TRUE or FALSE."},

  {MgmtSrvr::CONFIG_FILE_OPEN_WRITE_ERROR, 
   "Could not open configuration file for writing."},
  {MgmtSrvr::CONFIG_FILE_OPEN_READ_ERROR, 
   "Could not open configuration file for reading."},
  {MgmtSrvr::CONFIG_FILE_WRITE_ERROR, 
   "Write error when writing configuration file."},
  {MgmtSrvr::CONFIG_FILE_READ_ERROR, 
   "Read error when reading configuration file."},
  {MgmtSrvr::CONFIG_FILE_CLOSE_ERROR, "Could not close configuration file."},

  {MgmtSrvr::CONFIG_CHANGE_REFUSED_BY_RECEIVER, 
   "The change was refused by the receiving process."},
  {MgmtSrvr::COULD_NOT_SYNC_CONFIG_CHANGE_AGAINST_PHYSICAL_MEDIUM, 
   "The change could not be synced against physical medium."},
  {MgmtSrvr::CONFIG_FILE_CHECKSUM_ERROR, 
   "The config file is corrupt. Checksum error."},
  {MgmtSrvr::NOT_POSSIBLE_TO_SEND_CONFIG_UPDATE_TO_PROCESS_TYPE, 
   "It is not possible to send an update of a configuration variable "
   "to this kind of process."},
293 294 295 296 297 298 299
  {MgmtSrvr::NODE_SHUTDOWN_IN_PROGESS, "Node shutdown in progress" },
  {MgmtSrvr::SYSTEM_SHUTDOWN_IN_PROGRESS, "System shutdown in progress" },
  {MgmtSrvr::NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH,
   "Node shutdown would cause system crash" },
  {MgmtSrvr::NODE_NOT_API_NODE, "The specified node is not an API node." },
  {MgmtSrvr::OPERATION_NOT_ALLOWED_START_STOP, 
   "Operation not allowed while nodes are starting or stopping."},
300 301 302 303 304 305 306
  {MgmtSrvr::NO_CONTACT_WITH_DB_NODES, "No contact with database nodes" }
};

int MgmtSrvr::translateStopRef(Uint32 errCode)
{
  switch(errCode){
  case StopRef::NodeShutdownInProgress:
307
    return NODE_SHUTDOWN_IN_PROGESS;
308 309
    break;
  case StopRef::SystemShutdownInProgress:
310
    return SYSTEM_SHUTDOWN_IN_PROGRESS;
311 312
    break;
  case StopRef::NodeShutdownWouldCauseSystemCrash:
313
    return NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH;
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
    break;
  }
  return 4999;
}

static int noOfErrorCodes = sizeof(errorTable) / sizeof(ErrorItem);

int 
MgmtSrvr::getNodeCount(enum ndb_mgm_node_type type) const 
{
  int count = 0;
  NodeId nodeId = 0;

  while (getNextNodeId(&nodeId, type)) {
    count++;
  }
  return count;
}

tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
333
int 
334 335 336
MgmtSrvr::getPort() const
{
  if(NdbMutex_Lock(m_configMutex))
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
337 338
    return 0;

339 340 341 342
  ndb_mgm_configuration_iterator 
    iter(* _config->m_configValues, CFG_SECTION_NODE);

  if(iter.find(CFG_NODE_ID, getOwnNodeId()) != 0){
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
343 344 345
    ndbout << "Could not retrieve configuration for Node " 
	   << getOwnNodeId() << " in config file." << endl 
	   << "Have you set correct NodeId for this node?" << endl;
346
    NdbMutex_Unlock(m_configMutex);
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
347 348 349 350
    return 0;
  }

  unsigned type;
351
  if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0 ||
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
352 353 354 355
     type != NODE_TYPE_MGM){
    ndbout << "Local node id " << getOwnNodeId()
	   << " is not defined as management server" << endl
	   << "Have you set correct NodeId for this node?" << endl;
356
    NdbMutex_Unlock(m_configMutex);
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
357 358 359 360
    return 0;
  }
  
  Uint32 port = 0;
361
  if(iter.get(CFG_MGM_PORT, &port) != 0){
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
362
    ndbout << "Could not find PortNumber in the configuration file." << endl;
363
    NdbMutex_Unlock(m_configMutex);
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
364 365
    return 0;
  }
joreland@mysql.com's avatar
joreland@mysql.com committed
366

367 368
  NdbMutex_Unlock(m_configMutex);

tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
369 370 371
  return port;
}

372
/* Constructor */
373 374 375 376 377 378 379 380 381 382
int MgmtSrvr::init()
{
  if ( _ownNodeId > 0)
    return 0;
  return -1;
}

MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
		   const char *config_filename,
		   const char *connect_string) :
383 384
  _blockNumber(1), // Hard coded block number since it makes it easy to send
                   // signals to other management servers.
385
  m_socket_server(socket_server),
386 387 388
  _ownReference(0),
  theSignalIdleList(NULL),
  theWaitState(WAIT_SUBSCRIBE_CONF),
389 390
  m_event_listner(this),
  m_local_mgm_handle(0)
391
{
joreland@mysql.com's avatar
joreland@mysql.com committed
392
    
393 394
  DBUG_ENTER("MgmtSrvr::MgmtSrvr");

395 396
  _ownNodeId= 0;

397 398 399 400 401 402
  _config     = NULL;

  _isStopThread        = false;
  _logLevelThread      = NULL;
  _logLevelThreadSleep = 500;

tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
403 404
  theFacade = 0;

405
  m_newConfig = NULL;
406 407
  if (config_filename)
    m_configFilename.assign(config_filename);
408 409 410

  m_nextConfigGenerationNumber = 0;

411 412
  m_config_retriever= new ConfigRetriever(connect_string,
					  NDB_VERSION, NDB_MGM_NODE_TYPE_MGM);
413 414
  // if connect_string explicitly given or
  // no config filename is given then
415
  // first try to allocate nodeid from another management server
416 417
  if ((connect_string || config_filename == NULL) &&
      (m_config_retriever->do_connect(0,0,0) == 0))
418 419 420 421 422 423
  {
    int tmp_nodeid= 0;
    tmp_nodeid= m_config_retriever->allocNodeId(0 /*retry*/,0 /*delay*/);
    if (tmp_nodeid == 0)
    {
      ndbout_c(m_config_retriever->getErrorString());
424
      require(false);
425 426 427 428 429 430
    }
    // read config from other managent server
    _config= fetchConfig();
    if (_config == 0)
    {
      ndbout << m_config_retriever->getErrorString() << endl;
431
      require(false);
432 433 434 435 436 437 438 439 440 441
    }
    _ownNodeId= tmp_nodeid;
  }

  if (_ownNodeId == 0)
  {
    // read config locally
    _config= readConfig();
    if (_config == 0) {
      ndbout << "Unable to read config file" << endl;
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
442
      exit(-1);
443 444 445
    }
  }

446 447 448 449 450 451 452
  theMgmtWaitForResponseCondPtr = NdbCondition_Create();

  m_configMutex = NdbMutex_Create();

  /**
   * Fill the nodeTypes array
   */
453
  for(Uint32 i = 0; i<MAX_NODES; i++) {
454
    nodeTypes[i] = (enum ndb_mgm_node_type)-1;
455 456
    m_connect_address[i].s_addr= 0;
  }
457

458
  {
459
    ndb_mgm_configuration_iterator
460 461 462
      iter(* _config->m_configValues, CFG_SECTION_NODE);

    for(iter.first(); iter.valid(); iter.next()){
463
      unsigned type, id;
464
      if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0)
465 466
	continue;
      
467
      if(iter.get(CFG_NODE_ID, &id) != 0)
468
	continue;
469
      
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
      MGM_REQUIRE(id < MAX_NODES);
      
      switch(type){
      case NODE_TYPE_DB:
	nodeTypes[id] = NDB_MGM_NODE_TYPE_NDB;
	break;
      case NODE_TYPE_API:
	nodeTypes[id] = NDB_MGM_NODE_TYPE_API;
	break;
      case NODE_TYPE_MGM:
	nodeTypes[id] = NDB_MGM_NODE_TYPE_MGM;
	break;
      case NODE_TYPE_REP:
	nodeTypes[id] = NDB_MGM_NODE_TYPE_REP;
	break;
      case NODE_TYPE_EXT_REP:
      default:
	break;
      }
489 490
    }
  }
491

492
  _props = NULL;
493
  BaseString error_string;
494 495 496 497

  if ((m_node_id_mutex = NdbMutex_Create()) == 0)
  {
    ndbout << "mutex creation failed line = " << __LINE__ << endl;
498
    require(false);
499 500
  }

501 502 503 504 505 506 507 508
  if (_ownNodeId == 0) // we did not get node id from other server
  {
    NodeId tmp= m_config_retriever->get_configuration_nodeid();

    if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
		       0, 0, error_string)){
      ndbout << "Unable to obtain requested nodeid: "
	     << error_string.c_str() << endl;
509
      require(false);
510
    }
511
    _ownNodeId = tmp;
512
  }
513 514 515

  {
    DBUG_PRINT("info", ("verifyConfig"));
516 517 518 519
    if (!m_config_retriever->verifyConfig(_config->m_configValues,
					  _ownNodeId))
    {
      ndbout << m_config_retriever->getErrorString() << endl;
520
      require(false);
521 522 523
    }
  }

tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
524
  // Setup clusterlog as client[0] in m_event_listner
joreland@mysql.com's avatar
joreland@mysql.com committed
525
  {
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
526
    Ndb_mgmd_event_service::Event_listener se;
joreland@mysql.com's avatar
joreland@mysql.com committed
527
    se.m_socket = NDB_INVALID_SOCKET;
joreland@mysql.com's avatar
joreland@mysql.com committed
528
    for(size_t t = 0; t<LogLevel::LOGLEVEL_CATEGORIES; t++){
joreland@mysql.com's avatar
joreland@mysql.com committed
529
      se.m_logLevel.setLogLevel((LogLevel::EventCategory)t, 7);
joreland@mysql.com's avatar
joreland@mysql.com committed
530
    }
joreland@mysql.com's avatar
joreland@mysql.com committed
531
    se.m_logLevel.setLogLevel(LogLevel::llError, 15);
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
532
    se.m_logLevel.setLogLevel(LogLevel::llConnection, 8);
joreland@mysql.com's avatar
joreland@mysql.com committed
533
    se.m_logLevel.setLogLevel(LogLevel::llBackup, 15);
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
534 535
    m_event_listner.m_clients.push_back(se);
    m_event_listner.m_logLevel = se.m_logLevel;
joreland@mysql.com's avatar
joreland@mysql.com committed
536
  }
joreland@mysql.com's avatar
joreland@mysql.com committed
537
  
538
  DBUG_VOID_RETURN;
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
}


//****************************************************************************
//****************************************************************************
bool 
MgmtSrvr::check_start() 
{
  if (_config == 0) {
    DEBUG("MgmtSrvr.cpp: _config is NULL.");
    return false;
  }

  return true;
}

bool 
556
MgmtSrvr::start(BaseString &error_string)
557
{
558 559
  int mgm_connect_result;

560
  DBUG_ENTER("MgmtSrvr::start");
561
  if (_props == NULL) {
562 563
    if (!check_start()) {
      error_string.append("MgmtSrvr.cpp: check_start() failed.");
564
      DBUG_RETURN(false);
565
    }
566
  }
567
  theFacade= TransporterFacade::theFacadeInstance
568
    = new TransporterFacade();
569 570 571
  
  if(theFacade == 0) {
    DEBUG("MgmtSrvr.cpp: theFacade is NULL.");
572
    error_string.append("MgmtSrvr.cpp: theFacade is NULL.");
573
    DBUG_RETURN(false);
574
  }  
575 576 577
  if ( theFacade->start_instance
       (_ownNodeId, (ndb_mgm_configuration*)_config->m_configValues) < 0) {
    DEBUG("MgmtSrvr.cpp: TransporterFacade::start_instance < 0.");
578
    DBUG_RETURN(false);
579
  }
580 581 582 583 584 585 586 587

  MGM_REQUIRE(_blockNumber == 1);

  // Register ourself at TransporterFacade to be able to receive signals
  // and to be notified when a database process has died.
  _blockNumber = theFacade->open(this,
				 signalReceivedNotification,
				 nodeStatusNotification);
588
  
589 590
  if(_blockNumber == -1){
    DEBUG("MgmtSrvr.cpp: _blockNumber is -1.");
591
    error_string.append("MgmtSrvr.cpp: _blockNumber is -1.");
592 593
    theFacade->stop_instance();
    theFacade = 0;
594
    DBUG_RETURN(false);
595
  }
596

597 598 599 600 601 602 603
  if((mgm_connect_result= connect_to_self()) < 0)
  {
    ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)",
             mgm_connect_result);
    ndbout_c("This is probably a bug.");
  }

604 605 606
  TransporterRegistry *reg = theFacade->get_registry();
  for(unsigned int i=0;i<reg->m_transporter_interface.size();i++) {
    BaseString msg;
607
    DBUG_PRINT("info",("Setting dynamic port %d->%d : %d",
608 609
		       reg->get_localNodeId(),
		       reg->m_transporter_interface[i].m_remote_nodeId,
610
		       reg->m_transporter_interface[i].m_s_service_port
611 612 613 614 615 616
		       )
	       );
    int res = setConnectionDbParameter((int)reg->get_localNodeId(),
				       (int)reg->m_transporter_interface[i]
				            .m_remote_nodeId,
				       (int)CFG_CONNECTION_SERVER_PORT,
617 618
				       reg->m_transporter_interface[i]
				            .m_s_service_port,
619 620 621 622
					 msg);
    DBUG_PRINT("info",("Set result: %d: %s",res,msg.c_str()));
  }

623 624 625 626 627 628 629 630 631 632 633 634 635
  _ownReference = numberToRef(_blockNumber, _ownNodeId);
  
  startEventLog();
  // Set the initial confirmation count for subscribe requests confirm
  // from NDB nodes in the cluster.
  //
  // Loglevel thread
  _logLevelThread = NdbThread_Create(logLevelThread_C,
				     (void**)this,
				     32768,
				     "MgmtSrvr_Loglevel",
				     NDB_THREAD_PRIO_LOW);

636
  DBUG_RETURN(true);
637 638 639 640 641 642 643 644 645
}


//****************************************************************************
//****************************************************************************
MgmtSrvr::~MgmtSrvr() 
{
  if(theFacade != 0){
    theFacade->stop_instance();
646
    delete theFacade;
647 648 649 650 651
    theFacade = 0;
  }

  stopEventLog();

652 653 654
  NdbMutex_Destroy(m_node_id_mutex);
  NdbCondition_Destroy(theMgmtWaitForResponseCondPtr);
  NdbMutex_Destroy(m_configMutex);
655 656

  if(m_newConfig != NULL)
657 658 659 660 661
    free(m_newConfig);

  if(_config != NULL)
    delete _config;

662 663 664 665 666 667 668 669
  // End set log level thread
  void* res = 0;
  _isStopThread = true;

  if (_logLevelThread != NULL) {
    NdbThread_WaitFor(_logLevelThread, &res);
    NdbThread_Destroy(&_logLevelThread);
  }
joreland@mysql.com's avatar
joreland@mysql.com committed
670

671 672
  if (m_config_retriever)
    delete m_config_retriever;
673 674 675 676 677
}

//****************************************************************************
//****************************************************************************

678
int MgmtSrvr::okToSendTo(NodeId nodeId, bool unCond) 
679
{
680
  if(nodeId == 0)
joreland@mysql.com's avatar
joreland@mysql.com committed
681 682
    return 0;

683
  if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_NDB)
684 685 686 687
    return WRONG_PROCESS_TYPE;
  
  // Check if we have contact with it
  if(unCond){
688
    if(theFacade->theClusterMgr->getNodeInfo(nodeId).connected)
689 690 691
      return 0;
    return NO_CONTACT_WITH_PROCESS;
  }
692
  if (theFacade->get_node_alive(nodeId) == 0) {
693 694 695 696 697 698
    return NO_CONTACT_WITH_PROCESS;
  } else {
    return 0;
  }
}

699 700 701 702 703 704 705 706 707
void report_unknown_signal(SimpleSignal *signal)
{
  g_eventLogger.error("Unknown signal received. SignalNumber: "
		      "%i from (%d, %x)",
		      signal->readSignalNumber(),
		      refToNode(signal->header.theSendersBlockRef),
		      refToBlock(signal->header.theSendersBlockRef));
}

708 709 710 711 712
/*****************************************************************************
 * Starting and stopping database nodes
 ****************************************************************************/

int 
713
MgmtSrvr::start(int nodeId)
714
{
715
  INIT_SIGNAL_SENDER(ss,nodeId);
716
  
717 718 719
  SimpleSignal ssig;
  StartOrd* const startOrd = CAST_PTR(StartOrd, ssig.getDataPtrSend());
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_START_ORD, StartOrd::SignalLength);
720 721
  startOrd->restartInfo = 0;
  
722
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
723 724 725 726 727 728 729
}

/*****************************************************************************
 * Version handling
 *****************************************************************************/

int 
730
MgmtSrvr::versionNode(int nodeId, Uint32 &version, const char **address)
731
{
732 733
  version= 0;
  if (getOwnNodeId() == nodeId)
734
  {
735 736 737 738 739 740 741 742 743 744
    /**
     * If we're inquiring about our own node id,
     * We know what version we are (version implies connected for mgm)
     * but would like to find out from elsewhere what address they're using
     * to connect to us. This means that secondary mgm servers
     * can list ip addresses for mgm servers.
     *
     * If we don't get an address (i.e. no db nodes),
     * we get the address from the configuration.
     */
745
    sendVersionReq(nodeId, version, address);
746
    version= NDB_VERSION;
747 748 749 750 751 752 753 754 755 756 757 758 759 760
    if(!*address)
    {
      ndb_mgm_configuration_iterator
	iter(*_config->m_configValues, CFG_SECTION_NODE);
      unsigned tmp= 0;
      for(iter.first();iter.valid();iter.next())
      {
	if(iter.get(CFG_NODE_ID, &tmp)) require(false);
	if((unsigned)nodeId!=tmp)
	  continue;
	if(iter.get(CFG_NODE_HOST, address)) require(false);
	break;
      }
    }
761
  }
762
  else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB)
763
  {
764
    ClusterMgr::Node node= theFacade->theClusterMgr->getNodeInfo(nodeId);
765 766
    if(node.connected)
      version= node.m_info.m_version;
767
    *address= get_connect_address(nodeId);
768
  }
769 770
  else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API ||
	   getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM)
771
  {
772
    return sendVersionReq(nodeId, version, address);
773
  }
774 775

  return 0;
776 777 778
}

int 
779
MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address)
780
{
781 782
  SignalSender ss(theFacade);
  ss.lock();
783

784 785 786 787 788 789
  SimpleSignal ssig;
  ApiVersionReq* req = CAST_PTR(ApiVersionReq, ssig.getDataPtrSend());
  req->senderRef = ss.getOwnRef();
  req->nodeId = v_nodeId;
  ssig.set(ss, TestOrd::TraceAPI, QMGR, GSN_API_VERSION_REQ, 
	   ApiVersionReq::SignalLength);
790

791 792
  int do_send = 1;
  NodeId nodeId;
793

794 795 796 797 798 799
  while (1)
  {
    if (do_send)
    {
      bool next;
      nodeId = 0;
800

801 802
      while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
	    okToSendTo(nodeId, true) != 0);
803 804 805 806 807 808 809 810 811 812 813 814

      const ClusterMgr::Node &node=
	theFacade->theClusterMgr->getNodeInfo(nodeId);
      if(next && node.m_state.startLevel != NodeState::SL_STARTED)
      {
	NodeId tmp=nodeId;
	while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
	      okToSendTo(nodeId, true) != 0);
	if(!next)
	  nodeId= tmp;
      }

815
      if(!next) return NO_CONTACT_WITH_DB_NODES;
816

817 818 819 820
      if (ss.sendSignal(nodeId, &ssig) != SEND_OK) {
	return SEND_OR_RECEIVE_FAILED;
      }
      do_send = 0;
821
    }
822 823 824 825 826 827 828 829 830 831

    SimpleSignal *signal = ss.waitFor();

    int gsn = signal->readSignalNumber();
    switch (gsn) {
    case GSN_API_VERSION_CONF: {
      const ApiVersionConf * const conf = 
	CAST_CONSTPTR(ApiVersionConf, signal->getDataPtr());
      assert(conf->nodeId == v_nodeId);
      version = conf->version;
832 833 834
      struct in_addr in;
      in.s_addr= conf->inet_addr;
      *address= inet_ntoa(in);
835
      return 0;
836
    }
837 838 839 840 841 842
    case GSN_NF_COMPLETEREP:{
      const NFCompleteRep * const rep =
	CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
      if (rep->failedNodeId == nodeId)
	do_send = 1; // retry with other node
      continue;
843
    }
844 845 846
    case GSN_NODE_FAILREP:{
      const NodeFailRep * const rep =
	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
847
      if (NodeBitmask::get(rep->theNodes,nodeId))
848 849 850 851 852 853 854 855 856 857
	do_send = 1; // retry with other node
      continue;
    }
    default:
      report_unknown_signal(signal);
      return SEND_OR_RECEIVE_FAILED;
    }
    break;
  } // while(1)

858 859 860
  return 0;
}

861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
int MgmtSrvr::sendStopMgmd(NodeId nodeId,
			   bool abort,
			   bool stop,
			   bool restart,
			   bool nostart,
			   bool initialStart)
{
  const char* hostname;
  Uint32 port;
  BaseString connect_string;

  {
    Guard g(m_configMutex);
    {
      ndb_mgm_configuration_iterator
        iter(* _config->m_configValues, CFG_SECTION_NODE);

      if(iter.first())                       return SEND_OR_RECEIVE_FAILED;
      if(iter.find(CFG_NODE_ID, nodeId))     return SEND_OR_RECEIVE_FAILED;
      if(iter.get(CFG_NODE_HOST, &hostname)) return SEND_OR_RECEIVE_FAILED;
    }
    {
      ndb_mgm_configuration_iterator
        iter(* _config->m_configValues, CFG_SECTION_NODE);

      if(iter.first())                   return SEND_OR_RECEIVE_FAILED;
      if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED;
      if(iter.get(CFG_MGM_PORT, &port))  return SEND_OR_RECEIVE_FAILED;
    }
    if( strlen(hostname) == 0 )
      return SEND_OR_RECEIVE_FAILED;
  }
  connect_string.assfmt("%s:%u",hostname,port);

  DBUG_PRINT("info",("connect string: %s",connect_string.c_str()));

  NdbMgmHandle h= ndb_mgm_create_handle();
  if ( h && connect_string.length() > 0 )
  {
    ndb_mgm_set_connectstring(h,connect_string.c_str());
    if(ndb_mgm_connect(h,1,0,0))
    {
      DBUG_PRINT("info",("failed ndb_mgm_connect"));
      return SEND_OR_RECEIVE_FAILED;
    }
    if(!restart)
    {
      if(ndb_mgm_stop(h, 1, (const int*)&nodeId) < 0)
      {
        return SEND_OR_RECEIVE_FAILED;
      }
    }
    else
    {
      int nodes[1];
      nodes[0]= (int)nodeId;
      if(ndb_mgm_restart2(h, 1, nodes, initialStart, nostart, abort) < 0)
      {
        return SEND_OR_RECEIVE_FAILED;
      }
    }
  }
  ndb_mgm_destroy_handle(&h);

  return 0;
}

928 929 930
/*
 * Common method for handeling all STOP_REQ signalling that
 * is used by Stopping, Restarting and Single user commands
931 932 933 934 935
 *
 * In the event that we need to stop a mgmd, we create a mgm
 * client connection to that mgmd and stop it that way.
 * This allows us to stop mgm servers when there isn't any real
 * distributed communication up.
936
 */
937

938 939 940 941 942 943 944 945 946
int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
			   NodeBitmask &stoppedNodes,
			   Uint32 singleUserNodeId,
			   bool abort,
			   bool stop,
			   bool restart,
			   bool nostart,
			   bool initialStart)
{
947 948
  int error = 0;

949
  stoppedNodes.clear();
950

951 952
  SignalSender ss(theFacade);
  ss.lock(); // lock will be released on exit
953

954 955 956
  SimpleSignal ssig;
  StopReq* const stopReq = CAST_PTR(StopReq, ssig.getDataPtrSend());
  ssig.set(ss, TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength);
957 958 959 960 961 962 963

  stopReq->requestInfo = 0;
  stopReq->apiTimeout = 5000;
  stopReq->transactionTimeout = 1000;
  stopReq->readOperationTimeout = 1000;
  stopReq->operationTimeout = 1000;
  stopReq->senderData = 12;
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
  stopReq->senderRef = ss.getOwnRef();
  if (singleUserNodeId)
  {
    stopReq->singleuser = 1;
    stopReq->singleUserApi = singleUserNodeId;
    StopReq::setSystemStop(stopReq->requestInfo, false);
    StopReq::setPerformRestart(stopReq->requestInfo, false);
    StopReq::setStopAbort(stopReq->requestInfo, false);
  }
  else
  {
    stopReq->singleuser = 0;
    StopReq::setSystemStop(stopReq->requestInfo, stop);
    StopReq::setPerformRestart(stopReq->requestInfo, restart);
    StopReq::setStopAbort(stopReq->requestInfo, abort);
    StopReq::setNoStart(stopReq->requestInfo, nostart);
    StopReq::setInitialStart(stopReq->requestInfo, initialStart);
981 982
  }

983 984 985 986
  // send the signals
  NodeBitmask nodes;
  if (nodeId)
  {
987
    if(nodeId==getOwnNodeId())
988
    {
989 990 991 992
      if(restart)
        g_RestartServer= true;
      g_StopServer= true;
      return 0;
993
    }
994
    if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB)
995
    {
996 997 998
      int r;
      if((r= okToSendTo(nodeId, true)) != 0)
        return r;
999 1000 1001
      if (ss.sendSignal(nodeId, &ssig) != SEND_OK)
	return SEND_OR_RECEIVE_FAILED;
    }
1002 1003 1004 1005 1006 1007 1008 1009 1010
    else if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM)
    {
      error= sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart);
      if(error==0)
        stoppedNodes.set(nodeId);
      return error;
    }
    else
      return WRONG_PROCESS_TYPE;
1011
    nodes.set(nodeId);
1012
  }
1013
  else
1014
  {
1015 1016 1017 1018 1019 1020 1021 1022 1023
    while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
    {
      if(okToSendTo(nodeId, true) == 0)
      {
	SendStatus result = ss.sendSignal(nodeId, &ssig);
	if (result == SEND_OK)
	  nodes.set(nodeId);
      }
    }
1024 1025 1026 1027 1028 1029 1030 1031 1032
    nodeId= 0;
    while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM))
    {
      if(nodeId==getOwnNodeId())
        continue;
      if(sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart)==0)
        stoppedNodes.set(nodeId);
    }
  }
1033

1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
  // now wait for the replies
  while (!nodes.isclear())
  {
    SimpleSignal *signal = ss.waitFor();
    int gsn = signal->readSignalNumber();
    switch (gsn) {
    case GSN_STOP_REF:{
      const StopRef * const ref = CAST_CONSTPTR(StopRef, signal->getDataPtr());
      const NodeId nodeId = refToNode(signal->header.theSendersBlockRef);
#ifdef VM_TRACE
      ndbout_c("Node %d refused stop", nodeId);
#endif
      assert(nodes.get(nodeId));
      nodes.clear(nodeId);
      error = translateStopRef(ref->errorCode);
      break;
    }
    case GSN_STOP_CONF:{
      const StopConf * const ref = CAST_CONSTPTR(StopConf, signal->getDataPtr());
      const NodeId nodeId = refToNode(signal->header.theSendersBlockRef);
#ifdef VM_TRACE
      ndbout_c("Node %d single user mode", nodeId);
#endif
      assert(nodes.get(nodeId));
      assert(singleUserNodeId != 0);
      nodes.clear(nodeId);
      stoppedNodes.set(nodeId);
      break;
    }
    case GSN_NF_COMPLETEREP:{
      const NFCompleteRep * const rep =
	CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
      ndbout_c("Node %d fail completed", rep->failedNodeId);
#endif
      break;
    }
    case GSN_NODE_FAILREP:{
      const NodeFailRep * const rep =
	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
1074 1075
      NodeBitmask failedNodes;
      failedNodes.assign(NodeBitmask::Size, rep->theNodes);
1076
#ifdef VM_TRACE
1077 1078 1079 1080 1081 1082 1083
      {
	ndbout << "Failed nodes:";
	for (unsigned i = 0; i < 32*NodeBitmask::Size; i++)
	  if(failedNodes.get(i))
	    ndbout << " " << i;
	ndbout << endl;
      }
1084
#endif
1085 1086
      failedNodes.bitAND(nodes);
      if (!failedNodes.isclear())
1087
      {
1088
	nodes.bitANDC(failedNodes); // clear the failed nodes
1089
	if (singleUserNodeId == 0)
1090
	  stoppedNodes.bitOR(failedNodes);
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
      }
      break;
    }
    default:
      report_unknown_signal(signal);
#ifdef VM_TRACE
      ndbout_c("Unknown signal %d", gsn);
#endif
      return SEND_OR_RECEIVE_FAILED;
    }
1101
  }
1102
  return error;
1103 1104
}

1105 1106 1107 1108 1109
/*
 * Stop one node
 */

int MgmtSrvr::stopNode(int nodeId, bool abort)
1110
{
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
  if (!abort)
  {
    NodeId nodeId = 0;
    ClusterMgr::Node node;
    while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
    {
      node = theFacade->theClusterMgr->getNodeInfo(nodeId);
      if((node.m_state.startLevel != NodeState::SL_STARTED) && 
	 (node.m_state.startLevel != NodeState::SL_NOTHING))
	return OPERATION_NOT_ALLOWED_START_STOP;
    }
  }
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
  NodeBitmask nodes;
  return sendSTOP_REQ(nodeId,
		      nodes,
		      0,
		      abort,
		      false,
		      false,
		      false,
		      false);
}
1133

1134 1135 1136
/*
 * Perform system shutdown
 */
1137

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
int MgmtSrvr::stop(int * stopCount, bool abort)
{
  NodeBitmask nodes;
  int ret = sendSTOP_REQ(0,
			 nodes,
			 0,
			 abort,
			 true,
			 false,
			 false,
			 false);
  if (stopCount)
    *stopCount = nodes.count();
  return ret;
}

/*
 * Enter single user mode on all live nodes
 */
1157

1158 1159 1160
int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
{
  if (getNodeType(singleUserNodeId) != NDB_MGM_NODE_TYPE_API)
1161
    return NODE_NOT_API_NODE;
1162 1163 1164 1165 1166 1167 1168
  NodeId nodeId = 0;
  ClusterMgr::Node node;
  while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
  {
    node = theFacade->theClusterMgr->getNodeInfo(nodeId);
    if((node.m_state.startLevel != NodeState::SL_STARTED) && 
       (node.m_state.startLevel != NodeState::SL_NOTHING))
1169
      return OPERATION_NOT_ALLOWED_START_STOP;
1170
  }
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
  NodeBitmask nodes;
  int ret = sendSTOP_REQ(0,
			 nodes,
			 singleUserNodeId,
			 false,
			 false,
			 false,
			 false,
			 false);
  if (stopCount)
    *stopCount = nodes.count();
  return ret;
1183 1184
}

1185 1186 1187
/*
 * Perform node restart
 */
1188

1189 1190
int MgmtSrvr::restartNode(int nodeId, bool nostart, bool initialStart, 
			  bool abort)
1191
{
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
  NodeBitmask nodes;
  return sendSTOP_REQ(nodeId,
		      nodes,
		      0,
		      abort,
		      false,
		      true,
		      nostart,
		      initialStart);
}
1202

1203 1204 1205
/*
 * Perform system restart
 */
1206

1207 1208
int MgmtSrvr::restart(bool nostart, bool initialStart, 
		      bool abort, int * stopCount )
1209
{
1210 1211 1212 1213 1214 1215 1216 1217 1218
  NodeBitmask nodes;
  int ret = sendSTOP_REQ(0,
			 nodes,
			 0,
			 abort,
			 true,
			 true,
			 true,
			 initialStart);
1219

1220 1221
  if (ret)
    return ret;
1222

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
  if (stopCount)
    *stopCount = nodes.count();

#ifdef VM_TRACE
    ndbout_c("Stopped %d nodes", nodes.count());
#endif
  /**
   * Here all nodes were correctly stopped,
   * so we wait for all nodes to be contactable
   */
  int waitTime = 12000;
  NodeId nodeId = 0;
  NDB_TICKS maxTime = NdbTick_CurrentMillisecond() + waitTime;

  ndbout_c(" %d", nodes.get(1));
  ndbout_c(" %d", nodes.get(2));

  while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) {
    if (!nodes.get(nodeId))
      continue;
    enum ndb_mgm_node_status s;
    s = NDB_MGM_NODE_STATUS_NO_CONTACT;
#ifdef VM_TRACE
    ndbout_c("Waiting for %d not started", nodeId);
#endif
    while (s != NDB_MGM_NODE_STATUS_NOT_STARTED && waitTime > 0) {
      Uint32 startPhase = 0, version = 0, dynamicId = 0, nodeGroup = 0;
      Uint32 connectCount = 0;
      bool system;
1252
      const char *address;
1253
      status(nodeId, &s, &version, &startPhase, 
1254
	     &system, &dynamicId, &nodeGroup, &connectCount, &address);
1255 1256
      NdbSleep_MilliSleep(100);  
      waitTime = (maxTime - NdbTick_CurrentMillisecond());
1257 1258 1259
    }
  }
  
1260 1261
  if(nostart)
    return 0;
1262
  
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
  /**
   * Now we start all database nodes (i.e. we make them non-idle)
   * We ignore the result we get from the start command.
   */
  nodeId = 0;
  while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) {
    if (!nodes.get(nodeId))
      continue;
    int result;
    result = start(nodeId);
    DEBUG("Starting node " << nodeId << " with result " << result);
    /**
     * Errors from this call are deliberately ignored.
     * Maybe the user only wanted to restart a subset of the nodes.
     * It is also easy for the user to check which nodes have 
     * started and which nodes have not.
     */
1280
  }
1281 1282
  
  return 0;
1283 1284 1285
}

int
1286
MgmtSrvr::exitSingleUser(int * stopCount, bool abort)
1287 1288
{
  NodeId nodeId = 0;
1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
  int count = 0;

  SignalSender ss(theFacade);
  ss.lock(); // lock will be released on exit

  SimpleSignal ssig;
  ResumeReq* const resumeReq = 
    CAST_PTR(ResumeReq, ssig.getDataPtrSend());
  ssig.set(ss,TestOrd::TraceAPI, NDBCNTR, GSN_RESUME_REQ, 
	   ResumeReq::SignalLength);
  resumeReq->senderData = 12;
  resumeReq->senderRef = ss.getOwnRef();

1302 1303
  while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
    if(okToSendTo(nodeId, true) == 0){
1304 1305 1306
      SendStatus result = ss.sendSignal(nodeId, &ssig);
      if (result == SEND_OK)
	count++;
1307 1308 1309 1310
    }
  }

  if(stopCount != 0)
1311
    * stopCount = count;
1312

1313
  return 0;
1314 1315 1316 1317 1318 1319 1320 1321 1322
}

/*****************************************************************************
 * Status
 ****************************************************************************/

#include <ClusterMgr.hpp>

int 
1323
MgmtSrvr::status(int nodeId, 
1324 1325 1326 1327 1328
                 ndb_mgm_node_status * _status, 
		 Uint32 * version,
		 Uint32 * _phase, 
		 bool * _system,
		 Uint32 * dynamic,
1329
		 Uint32 * nodegroup,
1330 1331
		 Uint32 * connectCount,
		 const char **address)
1332
{
1333 1334
  if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API ||
      getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM) {
1335 1336 1337
    versionNode(nodeId, *version, address);
  } else {
    *address= get_connect_address(nodeId);
1338 1339 1340
  }

  const ClusterMgr::Node node = 
1341
    theFacade->theClusterMgr->getNodeInfo(nodeId);
1342 1343 1344 1345 1346 1347

  if(!node.connected){
    * _status = NDB_MGM_NODE_STATUS_NO_CONTACT;
    return 0;
  }
  
1348
  if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB) {
1349 1350 1351 1352 1353
    * version = node.m_info.m_version;
  }

  * dynamic = node.m_state.dynamicId;
  * nodegroup = node.m_state.nodeGroup;
1354 1355
  * connectCount = node.m_info.m_connectCount;
  
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
  switch(node.m_state.startLevel){
  case NodeState::SL_CMVMI:
    * _status = NDB_MGM_NODE_STATUS_NOT_STARTED;
    * _phase = 0;
    return 0;
    break;
  case NodeState::SL_STARTING:
    * _status     = NDB_MGM_NODE_STATUS_STARTING;
    * _phase = node.m_state.starting.startPhase;
    return 0;
    break;
  case NodeState::SL_STARTED:
    * _status = NDB_MGM_NODE_STATUS_STARTED;
    * _phase = 0;
    return 0;
    break;
  case NodeState::SL_STOPPING_1:
    * _status = NDB_MGM_NODE_STATUS_SHUTTING_DOWN;
    * _phase = 1;
    * _system = node.m_state.stopping.systemShutdown != 0;
    return 0;
    break;
  case NodeState::SL_STOPPING_2:
    * _status = NDB_MGM_NODE_STATUS_SHUTTING_DOWN;
    * _phase = 2;
    * _system = node.m_state.stopping.systemShutdown != 0;
    return 0;
    break;
  case NodeState::SL_STOPPING_3:
    * _status = NDB_MGM_NODE_STATUS_SHUTTING_DOWN;
    * _phase = 3;
    * _system = node.m_state.stopping.systemShutdown != 0;
    return 0;
    break;
  case NodeState::SL_STOPPING_4:
    * _status = NDB_MGM_NODE_STATUS_SHUTTING_DOWN;
    * _phase = 4;
    * _system = node.m_state.stopping.systemShutdown != 0;
    return 0;
    break;
  case NodeState::SL_SINGLEUSER:
    * _status = NDB_MGM_NODE_STATUS_SINGLEUSER;
    * _phase  = 0;
    return 0;
    break;
  default:
    * _status = NDB_MGM_NODE_STATUS_UNKNOWN;
    * _phase = 0;
    return 0;
  }
1406
  
1407 1408 1409 1410
  return -1;
}

int 
1411
MgmtSrvr::setEventReportingLevelImpl(int nodeId, 
joreland@mysql.com's avatar
joreland@mysql.com committed
1412
				     const EventSubscribeReq& ll)
1413
{
1414
  INIT_SIGNAL_SENDER(ss,nodeId);
1415

1416
  SimpleSignal ssig;
1417
  EventSubscribeReq * dst = 
1418 1419 1420 1421 1422
    CAST_PTR(EventSubscribeReq, ssig.getDataPtrSend());
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_EVENT_SUBSCRIBE_REQ,
	   EventSubscribeReq::SignalLength);
  *dst = ll;

1423
  send(ss,ssig,nodeId,NODE_TYPE_DB);
1424

1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446
#if 0
  while (1)
  {
    SimpleSignal *signal = ss.waitFor();
    int gsn = signal->readSignalNumber();
    switch (gsn) { 
    case GSN_EVENT_SUBSCRIBE_CONF:{
      break;
    }
    case GSN_EVENT_SUBSCRIBE_REF:{
      return SEND_OR_RECEIVE_FAILED;
    }
    case GSN_NF_COMPLETEREP:{
      const NFCompleteRep * const rep =
	CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
      if (rep->failedNodeId == nodeId)
	return SEND_OR_RECEIVE_FAILED;
      break;
    }
    case GSN_NODE_FAILREP:{
      const NodeFailRep * const rep =
	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
1447
      if (NodeBitmask::get(rep->theNodes,nodeId))
1448 1449 1450 1451 1452 1453 1454
	return SEND_OR_RECEIVE_FAILED;
      break;
    }
    default:
      report_unknown_signal(signal);
      return SEND_OR_RECEIVE_FAILED;
    }
1455

1456 1457
  }
#endif
1458 1459 1460 1461 1462 1463
  return 0;
}

//****************************************************************************
//****************************************************************************
int 
1464
MgmtSrvr::setNodeLogLevelImpl(int nodeId, const SetLogLevelOrd & ll)
1465
{
1466
  INIT_SIGNAL_SENDER(ss,nodeId);
1467

1468 1469 1470 1471 1472
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_SET_LOGLEVELORD,
	   SetLogLevelOrd::SignalLength);
  SetLogLevelOrd* const dst = CAST_PTR(SetLogLevelOrd, ssig.getDataPtrSend());
  *dst = ll;
joreland@mysql.com's avatar
joreland@mysql.com committed
1473
  
1474
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1475 1476
}

joreland@mysql.com's avatar
joreland@mysql.com committed
1477
int
1478
MgmtSrvr::send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type){
joreland@mysql.com's avatar
joreland@mysql.com committed
1479 1480 1481
  Uint32 max = (node == 0) ? MAX_NODES : node + 1;
  
  for(; node < max; node++){
joreland@mysql.com's avatar
joreland@mysql.com committed
1482 1483
    while(nodeTypes[node] != (int)node_type && node < max) node++;
    if(nodeTypes[node] != (int)node_type)
joreland@mysql.com's avatar
joreland@mysql.com committed
1484
      break;
1485
    ss.sendSignal(node, &ssig);
joreland@mysql.com's avatar
joreland@mysql.com committed
1486 1487 1488
  }
  return 0;
}
1489 1490 1491 1492 1493

//****************************************************************************
//****************************************************************************

int 
1494
MgmtSrvr::insertError(int nodeId, int errorNo) 
1495 1496 1497 1498 1499
{
  if (errorNo < 0) {
    return INVALID_ERROR_NUMBER;
  }

1500
  INIT_SIGNAL_SENDER(ss,nodeId);
1501
  
1502 1503 1504 1505
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TAMPER_ORD, 
	   TamperOrd::SignalLength);
  TamperOrd* const tamperOrd = CAST_PTR(TamperOrd, ssig.getDataPtrSend());
1506 1507
  tamperOrd->errorNo = errorNo;

1508
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1509 1510 1511 1512 1513 1514 1515 1516
}



//****************************************************************************
//****************************************************************************

int 
1517
MgmtSrvr::setTraceNo(int nodeId, int traceNo)
1518 1519 1520 1521 1522
{
  if (traceNo < 0) {
    return INVALID_TRACE_NUMBER;
  }

1523
  INIT_SIGNAL_SENDER(ss,nodeId);
1524

1525 1526 1527
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);
  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1528 1529 1530 1531 1532
  testOrd->clear();
  // Assume TRACE command causes toggling. Not really defined... ? TODO
  testOrd->setTraceCommand(TestOrd::Toggle, 
			   (TestOrd::TraceSpecification)traceNo);

1533
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551
}

//****************************************************************************
//****************************************************************************

int 
MgmtSrvr::getBlockNumber(const BaseString &blockName) 
{
  short bno = getBlockNo(blockName.c_str());
  if(bno != 0)
    return bno;
  return -1;
}

//****************************************************************************
//****************************************************************************

int 
1552
MgmtSrvr::setSignalLoggingMode(int nodeId, LogMode mode, 
1553 1554
			       const Vector<BaseString>& blocks)
{
1555
  INIT_SIGNAL_SENDER(ss,nodeId);
1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583

  // Convert from MgmtSrvr format...

  TestOrd::Command command;
  if (mode == Off) {
    command = TestOrd::Off;
  }
  else {
    command = TestOrd::On;
  }

  TestOrd::SignalLoggerSpecification logSpec;
  switch (mode) {
  case In:
    logSpec = TestOrd::InputSignals;
    break;
  case Out:
    logSpec = TestOrd::OutputSignals;
    break;
  case InOut:
    logSpec = TestOrd::InputOutputSignals;
    break;
  case Off:
    // In MgmtSrvr interface it's just possible to switch off all logging, both
    // "in" and "out" (this should probably be changed).
    logSpec = TestOrd::InputOutputSignals;
    break;
  default:
1584 1585 1586 1587
    ndbout_c("Unexpected value %d, MgmtSrvr::setSignalLoggingMode, line %d",
	     (unsigned)mode, __LINE__);
    assert(false);
    return -1;
1588 1589
  }

1590 1591
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);
1592

1593
  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608
  testOrd->clear();
  
  if (blocks.size() == 0 || blocks[0] == "ALL") {
    // Logg command for all blocks
    testOrd->addSignalLoggerCommand(command, logSpec);
  } else {
    for(unsigned i = 0; i < blocks.size(); i++){
      int blockNumber = getBlockNumber(blocks[i]);
      if (blockNumber == -1) {
        return INVALID_BLOCK_NAME;
      }
      testOrd->addSignalLoggerCommand(blockNumber, command, logSpec);
    } // for
  } // else

1609
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1610 1611 1612 1613 1614
}

/*****************************************************************************
 * Signal tracing
 *****************************************************************************/
1615
int MgmtSrvr::startSignalTracing(int nodeId)
1616
{
1617
  INIT_SIGNAL_SENDER(ss,nodeId);
1618
  
1619 1620 1621 1622
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);

  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1623 1624 1625
  testOrd->clear();
  testOrd->setTestCommand(TestOrd::On);

1626
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1627 1628 1629
}

int 
1630
MgmtSrvr::stopSignalTracing(int nodeId) 
1631
{
1632
  INIT_SIGNAL_SENDER(ss,nodeId);
1633

1634 1635 1636
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);
  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1637 1638 1639
  testOrd->clear();
  testOrd->setTestCommand(TestOrd::Off);

1640
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1641 1642 1643 1644 1645 1646 1647 1648
}


/*****************************************************************************
 * Dump state
 *****************************************************************************/

int
1649
MgmtSrvr::dumpState(int nodeId, const char* args)
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670
{
  // Convert the space separeted args 
  // string to an int array
  Uint32 args_array[25];
  Uint32 numArgs = 0;

  char buf[10];  
  int b  = 0;
  memset(buf, 0, 10);
  for (size_t i = 0; i <= strlen(args); i++){
    if (args[i] == ' ' || args[i] == 0){
      args_array[numArgs] = atoi(buf);
      numArgs++;
      memset(buf, 0, 10);
      b = 0;
    } else {
      buf[b] = args[i];
      b++;
    }    
  }
  
1671
  return dumpState(nodeId, args_array, numArgs);
1672 1673 1674
}

int
1675
MgmtSrvr::dumpState(int nodeId, const Uint32 args[], Uint32 no)
1676
{
1677
  INIT_SIGNAL_SENDER(ss,nodeId);
1678 1679 1680

  const Uint32 len = no > 25 ? 25 : no;
  
1681
  SimpleSignal ssig;
1682
  DumpStateOrd * const dumpOrd = 
1683 1684
    CAST_PTR(DumpStateOrd, ssig.getDataPtrSend());
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_DUMP_STATE_ORD, len);
1685 1686 1687 1688 1689 1690 1691
  for(Uint32 i = 0; i<25; i++){
    if (i < len)
      dumpOrd->args[i] = args[i];
    else
      dumpOrd->args[i] = 0;
  }
  
1692
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1693 1694 1695 1696 1697 1698
}


//****************************************************************************
//****************************************************************************

1699
const char* MgmtSrvr::getErrorText(int errorCode, char *buf, int buf_sz)
1700 1701 1702 1703
{

  for (int i = 0; i < noOfErrorCodes; ++i) {
    if (errorCode == errorTable[i]._errorCode) {
1704 1705 1706
      BaseString::snprintf(buf, buf_sz, errorTable[i]._errorText);
      buf[buf_sz-1]= 0;
      return buf;
1707 1708
    }
  }
1709 1710 1711 1712 1713

  ndb_error_string(errorCode, buf, buf_sz);
  buf[buf_sz-1]= 0;

  return buf;
1714 1715 1716 1717 1718 1719 1720
}

void 
MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
{
  // The way of handling a received signal is taken from the Ndb class.
  int gsn = signal->readSignalNumber();
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1721

1722 1723 1724
  switch (gsn) {
  case GSN_EVENT_SUBSCRIBE_CONF:
    break;
1725 1726
  case GSN_EVENT_SUBSCRIBE_REF:
    break;
1727
  case GSN_EVENT_REP:
1728 1729 1730 1731 1732
  {
    EventReport *rep = CAST_PTR(EventReport, signal->getDataPtrSend());
    if (rep->getNodeId() == 0)
      rep->setNodeId(refToNode(signal->theSendersBlockRef));
    eventReport(signal->getDataPtr());
1733
    break;
1734
  }
1735

1736
  case GSN_NF_COMPLETEREP:
1737
    break;
1738
  case GSN_NODE_FAILREP:
1739 1740 1741
    break;

  default:
1742
    g_eventLogger.error("Unknown signal received. SignalNumber: "
1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
			"%i from (%d, %x)",
			gsn,
			refToNode(signal->theSendersBlockRef),
			refToBlock(signal->theSendersBlockRef));
  }
  
  if (theWaitState == NO_WAIT) {
    NdbCondition_Signal(theMgmtWaitForResponseCondPtr);
  }
}

void
joreland@mysql.com's avatar
joreland@mysql.com committed
1755
MgmtSrvr::handleStatus(NodeId nodeId, bool alive, bool nfComplete)
1756
{
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
1757 1758
  DBUG_ENTER("MgmtSrvr::handleStatus");
  Uint32 theData[25];
1759 1760
  EventReport *rep = (EventReport *)theData;

tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
1761
  theData[1] = nodeId;
1762
  if (alive) {
joreland@mysql.com's avatar
joreland@mysql.com committed
1763
    m_started_nodes.push_back(nodeId);
1764
    rep->setEventType(NDB_LE_Connected);
1765
  } else {
1766
    rep->setEventType(NDB_LE_Connected);
joreland@mysql.com's avatar
joreland@mysql.com committed
1767 1768
    if(nfComplete)
    {
1769
      DBUG_VOID_RETURN;
joreland@mysql.com's avatar
joreland@mysql.com committed
1770
    }
1771
  }
joreland@mysql.com's avatar
joreland@mysql.com committed
1772
  
1773 1774
  rep->setNodeId(_ownNodeId);
  eventReport(theData);
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
1775
  DBUG_VOID_RETURN;
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792
}

//****************************************************************************
//****************************************************************************

void 
MgmtSrvr::signalReceivedNotification(void* mgmtSrvr, 
                                     NdbApiSignal* signal,
				     LinearSectionPtr ptr[3]) 
{
  ((MgmtSrvr*)mgmtSrvr)->handleReceivedSignal(signal);
}


//****************************************************************************
//****************************************************************************
void 
1793
MgmtSrvr::nodeStatusNotification(void* mgmSrv, Uint32 nodeId, 
1794 1795
				 bool alive, bool nfComplete)
{
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
1796 1797
  DBUG_ENTER("MgmtSrvr::nodeStatusNotification");
  DBUG_PRINT("enter",("nodeid= %d, alive= %d, nfComplete= %d", nodeId, alive, nfComplete));
joreland@mysql.com's avatar
joreland@mysql.com committed
1798
  ((MgmtSrvr*)mgmSrv)->handleStatus(nodeId, alive, nfComplete);
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
1799
  DBUG_VOID_RETURN;
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
}

enum ndb_mgm_node_type 
MgmtSrvr::getNodeType(NodeId nodeId) const 
{
  if(nodeId >= MAX_NODES)
    return (enum ndb_mgm_node_type)-1;
  
  return nodeTypes[nodeId];
}

1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828
const char *MgmtSrvr::get_connect_address(Uint32 node_id)
{
  if (m_connect_address[node_id].s_addr == 0 &&
      theFacade && theFacade->theTransporterRegistry &&
      theFacade->theClusterMgr &&
      getNodeType(node_id) == NDB_MGM_NODE_TYPE_NDB) 
  {
    const ClusterMgr::Node &node=
      theFacade->theClusterMgr->getNodeInfo(node_id);
    if (node.connected)
    {
      m_connect_address[node_id]=
	theFacade->theTransporterRegistry->get_connect_address(node_id);
    }
  }
  return inet_ntoa(m_connect_address[node_id]);  
}

1829 1830 1831 1832 1833 1834 1835 1836 1837 1838
void
MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const
{
  if (theFacade && theFacade->theClusterMgr) 
  {
    for(Uint32 i = 0; i < MAX_NODES; i++)
    {
      if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB)
      {
	const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i);
1839
	connected_nodes.bitOR(node.m_state.m_connected_nodes);
1840 1841 1842 1843 1844
      }
    }
  }
}

tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1845
bool
joreland@mysql.com's avatar
joreland@mysql.com committed
1846 1847 1848
MgmtSrvr::alloc_node_id(NodeId * nodeId, 
			enum ndb_mgm_node_type type,
			struct sockaddr *client_addr, 
1849 1850
			SOCKET_SIZE_TYPE *client_addr_len,
			BaseString &error_string)
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1851
{
1852 1853 1854 1855 1856
  DBUG_ENTER("MgmtSrvr::alloc_node_id");
  DBUG_PRINT("enter", ("nodeid=%d, type=%d, client_addr=%d",
		       *nodeId, type, client_addr));
  if (g_no_nodeid_checks) {
    if (*nodeId == 0) {
1857
      error_string.appfmt("no-nodeid-checks set in management server.\n"
1858 1859 1860 1861 1862
			  "node id must be set explicitly in connectstring");
      DBUG_RETURN(false);
    }
    DBUG_RETURN(true);
  }
1863
  Guard g(m_node_id_mutex);
1864
  int no_mgm= 0;
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1865
  NodeBitmask connected_nodes(m_reserved_nodes);
1866
  get_connected_nodes(connected_nodes);
1867
  {
1868 1869 1870
    for(Uint32 i = 0; i < MAX_NODES; i++)
      if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM)
	no_mgm++;
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1871
  }
1872 1873 1874
  bool found_matching_id= false;
  bool found_matching_type= false;
  bool found_free_node= false;
1875 1876
  unsigned id_found= 0;
  const char *config_hostname= 0;
1877 1878
  struct in_addr config_addr= {0};
  int r_config_addr= -1;
1879 1880
  unsigned type_c= 0;

1881 1882 1883 1884 1885
  if(NdbMutex_Lock(m_configMutex))
  {
    error_string.appfmt("unable to lock configuration mutex");
    return false;
  }
1886
  ndb_mgm_configuration_iterator
1887
    iter(* _config->m_configValues, CFG_SECTION_NODE);
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1888 1889
  for(iter.first(); iter.valid(); iter.next()) {
    unsigned tmp= 0;
1890
    if(iter.get(CFG_NODE_ID, &tmp)) require(false);
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1891 1892
    if (*nodeId && *nodeId != tmp)
      continue;
1893
    found_matching_id= true;
1894
    if(iter.get(CFG_TYPE_OF_SECTION, &type_c)) require(false);
joreland@mysql.com's avatar
joreland@mysql.com committed
1895
    if(type_c != (unsigned)type)
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1896
      continue;
1897 1898 1899 1900
    found_matching_type= true;
    if (connected_nodes.get(tmp))
      continue;
    found_free_node= true;
1901
    if(iter.get(CFG_NODE_HOST, &config_hostname)) require(false);
1902 1903 1904
    if (config_hostname && config_hostname[0] == 0)
      config_hostname= 0;
    else if (client_addr) {
1905
      // check hostname compatability
1906 1907 1908
      const void *tmp_in= &(((sockaddr_in*)client_addr)->sin_addr);
      if((r_config_addr= Ndb_getInAddr(&config_addr, config_hostname)) != 0
	 || memcmp(&config_addr, tmp_in, sizeof(config_addr)) != 0) {
1909 1910
	struct in_addr tmp_addr;
	if(Ndb_getInAddr(&tmp_addr, "localhost") != 0
1911
	   || memcmp(&tmp_addr, tmp_in, sizeof(config_addr)) != 0) {
1912
	  // not localhost
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1913
#if 0
1914 1915 1916
	  ndbout << "MgmtSrvr::getFreeNodeId compare failed for \""
		 << config_hostname
		 << "\" id=" << tmp << endl;
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1917
#endif
1918 1919 1920
	  continue;
	}
	// connecting through localhost
1921 1922 1923 1924 1925 1926 1927 1928
	// check if config_hostname is local
	if (!SocketServer::tryBind(0,config_hostname)) {
	  continue;
	}
      }
    } else { // client_addr == 0
      if (!SocketServer::tryBind(0,config_hostname)) {
	continue;
1929
      }
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
1930
    }
1931 1932 1933
    if (*nodeId != 0 ||
	type != NDB_MGM_NODE_TYPE_MGM ||
	no_mgm == 1) { // any match is ok
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945

      if (config_hostname == 0 &&
	  *nodeId == 0 &&
	  type != NDB_MGM_NODE_TYPE_MGM)
      {
	if (!id_found) // only set if not set earlier
	  id_found= tmp;
	continue; /* continue looking for a nodeid with specified
		   * hostname
		   */
      }
      assert(id_found == 0);
1946 1947 1948 1949 1950 1951 1952 1953
      id_found= tmp;
      break;
    }
    if (id_found) { // mgmt server may only have one match
      error_string.appfmt("Ambiguous node id's %d and %d.\n"
			  "Suggest specifying node id in connectstring,\n"
			  "or specifying unique host names in config file.",
			  id_found, tmp);
1954
      NdbMutex_Unlock(m_configMutex);
1955 1956 1957 1958 1959
      DBUG_RETURN(false);
    }
    if (config_hostname == 0) {
      error_string.appfmt("Ambiguity for node id %d.\n"
			  "Suggest specifying node id in connectstring,\n"
1960
			  "or specifying unique host names in config file,\n"
1961 1962 1963 1964 1965 1966
			  "or specifying just one mgmt server in config file.",
			  tmp);
      DBUG_RETURN(false);
    }
    id_found= tmp; // mgmt server matched, check for more matches
  }
1967
  NdbMutex_Unlock(m_configMutex);
1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991

  if (id_found)
  {
    *nodeId= id_found;
    DBUG_PRINT("info", ("allocating node id %d",*nodeId));
    {
      int r= 0;
      if (client_addr)
	m_connect_address[id_found]=
	  ((struct sockaddr_in *)client_addr)->sin_addr;
      else if (config_hostname)
	r= Ndb_getInAddr(&(m_connect_address[id_found]), config_hostname);
      else {
	char name[256];
	r= gethostname(name, sizeof(name));
	if (r == 0) {
	  name[sizeof(name)-1]= 0;
	  r= Ndb_getInAddr(&(m_connect_address[id_found]), name);
	}
      }
      if (r)
	m_connect_address[id_found].s_addr= 0;
    }
    m_reserved_nodes.set(id_found);
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001
    if (theFacade && id_found != theFacade->ownId())
    {
      /**
       * Make sure we're ready to accept connections from this node
       */
      theFacade->lock_mutex();
      theFacade->doConnect(id_found);
      theFacade->unlock_mutex();
    }
    
2002 2003
    char tmp_str[128];
    m_reserved_nodes.getText(tmp_str);
2004
    g_eventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, m_reserved_nodes %s.",
2005
		       id_found, get_connect_address(id_found), tmp_str);
2006
    DBUG_RETURN(true);
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
2007
  }
2008 2009

  if (found_matching_type && !found_free_node) {
2010 2011
    // we have a temporary error which might be due to that 
    // we have got the latest connect status from db-nodes.  Force update.
2012 2013 2014
    global_flag_send_heartbeat_now= 1;
  }

2015 2016 2017 2018 2019
  BaseString type_string, type_c_string;
  {
    const char *alias, *str;
    alias= ndb_mgm_get_node_type_alias_string(type, &str);
    type_string.assfmt("%s(%s)", alias, str);
2020 2021
    alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)type_c,
					      &str);
2022 2023 2024 2025 2026 2027 2028
    type_c_string.assfmt("%s(%s)", alias, str);
  }

  if (*nodeId == 0) {
    if (found_matching_id)
      if (found_matching_type)
	if (found_free_node)
2029
	  error_string.appfmt("Connection done from wrong host ip %s.",
2030 2031 2032
			      (client_addr)?
			        inet_ntoa(((struct sockaddr_in *)
					 (client_addr))->sin_addr):"");
2033
	else
2034 2035
	  error_string.appfmt("No free node id found for %s.",
			      type_string.c_str());
2036
      else
2037 2038
	error_string.appfmt("No %s node defined in config file.",
			    type_string.c_str());
2039 2040 2041 2042 2043
    else
      error_string.append("No nodes defined in config file.");
  } else {
    if (found_matching_id)
      if (found_matching_type)
2044 2045 2046
	if (found_free_node) {
	  // have to split these into two since inet_ntoa overwrites itself
	  error_string.appfmt("Connection with id %d done from wrong host ip %s,",
2047 2048
			      *nodeId, inet_ntoa(((struct sockaddr_in *)
						  (client_addr))->sin_addr));
2049
	  error_string.appfmt(" expected %s(%s).", config_hostname,
2050 2051
			      r_config_addr ?
			      "lookup failed" : inet_ntoa(config_addr));
2052
	} else
2053 2054
	  error_string.appfmt("Id %d already allocated by another node.",
			      *nodeId);
2055 2056
      else
	error_string.appfmt("Id %d configured as %s, connect attempted as %s.",
2057 2058
			    *nodeId, type_c_string.c_str(),
			    type_string.c_str());
2059
    else
2060 2061
      error_string.appfmt("No node defined with id=%d in config file.",
			  *nodeId);
2062
  }
2063

2064
  g_eventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s. "
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086
			"Returned error string \"%s\"",
			*nodeId,
			client_addr != 0 ? inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr) : "<none>",
			error_string.c_str());

  NodeBitmask connected_nodes2;
  get_connected_nodes(connected_nodes2);
  {
    BaseString tmp_connected, tmp_not_connected;
    for(Uint32 i = 0; i < MAX_NODES; i++)
    {
      if (connected_nodes2.get(i))
      {
	if (!m_reserved_nodes.get(i))
	  tmp_connected.appfmt(" %d", i);
      }
      else if (m_reserved_nodes.get(i))
      {
	tmp_not_connected.appfmt(" %d", i);
      }
    }
    if (tmp_connected.length() > 0)
2087
      g_eventLogger.info("Mgmt server state: node id's %s connected but not reserved", 
2088 2089
			 tmp_connected.c_str());
    if (tmp_not_connected.length() > 0)
2090
      g_eventLogger.info("Mgmt server state: node id's %s not connected but reserved",
2091 2092
			 tmp_not_connected.c_str());
  }
2093
  DBUG_RETURN(false);
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
2094 2095
}

2096 2097 2098 2099 2100 2101 2102 2103 2104
bool
MgmtSrvr::getNextNodeId(NodeId * nodeId, enum ndb_mgm_node_type type) const 
{
  NodeId tmp = * nodeId;

  tmp++;
  while(nodeTypes[tmp] != type && tmp < MAX_NODES)
    tmp++;
  
2105
  if(tmp == MAX_NODES){
2106
    return false;
2107
  }
2108 2109 2110 2111 2112

  * nodeId = tmp;
  return true;
}

joreland@mysql.com's avatar
joreland@mysql.com committed
2113 2114
#include "Services.hpp"

2115
void
2116
MgmtSrvr::eventReport(const Uint32 * theData)
2117 2118
{
  const EventReport * const eventReport = (EventReport *)&theData[0];
joreland@mysql.com's avatar
joreland@mysql.com committed
2119
  
2120
  NodeId nodeId = eventReport->getNodeId();
2121
  Ndb_logevent_type type = eventReport->getEventType();
2122
  // Log event
2123
  g_eventLogger.log(type, theData, nodeId, 
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
2124 2125
		    &m_event_listner[0].m_logLevel);  
  m_event_listner.log(type, theData, nodeId);
2126 2127 2128 2129 2130
}

/***************************************************************************
 * Backup
 ***************************************************************************/
2131

2132
int
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
2133
MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
2134
{
2135 2136 2137
  SignalSender ss(theFacade);
  ss.lock(); // lock will be released on exit

2138 2139 2140 2141 2142 2143 2144
  bool next;
  NodeId nodeId = 0;
  while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
	theFacade->get_node_alive(nodeId) == false);
  
  if(!next) return NO_CONTACT_WITH_DB_NODES;

2145 2146 2147 2148
  SimpleSignal ssig;
  BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
  ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ, 
	   BackupReq::SignalLength);
2149 2150 2151
  
  req->senderData = 19;
  req->backupDataLen = 0;
2152 2153
  assert(waitCompleted < 3);
  req->flags = waitCompleted & 0x3;
2154

2155 2156 2157 2158 2159
  BackupEvent event;
  int do_send = 1;
  while (1) {
    if (do_send)
    {
2160
      if (ss.sendSignal(nodeId, &ssig) != SEND_OK) {
2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184
	return SEND_OR_RECEIVE_FAILED;
      }
      if (waitCompleted == 0)
	return 0;
      do_send = 0;
    }
    SimpleSignal *signal = ss.waitFor();

    int gsn = signal->readSignalNumber();
    switch (gsn) {
    case GSN_BACKUP_CONF:{
      const BackupConf * const conf = 
	CAST_CONSTPTR(BackupConf, signal->getDataPtr());
      event.Event = BackupEvent::BackupStarted;
      event.Started.BackupId = conf->backupId;
      event.Nodes = conf->nodes;
#ifdef VM_TRACE
      ndbout_c("Backup(%d) master is %d", conf->backupId,
	       refToNode(signal->header.theSendersBlockRef));
#endif
      backupId = conf->backupId;
      if (waitCompleted == 1)
	return 0;
      // wait for next signal
2185
      break;
2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244
    }
    case GSN_BACKUP_COMPLETE_REP:{
      const BackupCompleteRep * const rep = 
	CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
      ndbout_c("Backup(%d) completed %d", rep->backupId);
#endif
      event.Event = BackupEvent::BackupCompleted;
      event.Completed.BackupId = rep->backupId;
    
      event.Completed.NoOfBytes = rep->noOfBytes;
      event.Completed.NoOfLogBytes = rep->noOfLogBytes;
      event.Completed.NoOfRecords = rep->noOfRecords;
      event.Completed.NoOfLogRecords = rep->noOfLogRecords;
      event.Completed.stopGCP = rep->stopGCP;
      event.Completed.startGCP = rep->startGCP;
      event.Nodes = rep->nodes;

      backupId = rep->backupId;
      return 0;
    }
    case GSN_BACKUP_REF:{
      const BackupRef * const ref = 
	CAST_CONSTPTR(BackupRef, signal->getDataPtr());
      if(ref->errorCode == BackupRef::IAmNotMaster){
	nodeId = refToNode(ref->masterRef);
#ifdef VM_TRACE
	ndbout_c("I'm not master resending to %d", nodeId);
#endif
	do_send = 1; // try again
	continue;
      }
      event.Event = BackupEvent::BackupFailedToStart;
      event.FailedToStart.ErrorCode = ref->errorCode;
      return ref->errorCode;
    }
    case GSN_BACKUP_ABORT_REP:{
      const BackupAbortRep * const rep = 
	CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
      event.Event = BackupEvent::BackupAborted;
      event.Aborted.Reason = rep->reason;
      event.Aborted.BackupId = rep->backupId;
      event.Aborted.ErrorCode = rep->reason;
#ifdef VM_TRACE
      ndbout_c("Backup %d aborted", rep->backupId);
#endif
      return rep->reason;
    }
    case GSN_NF_COMPLETEREP:{
      const NFCompleteRep * const rep =
	CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
      ndbout_c("Node %d fail completed", rep->failedNodeId);
#endif
      if (rep->failedNodeId == nodeId ||
	  waitCompleted == 1)
	return 1326;
      // wait for next signal
      // master node will report aborted backup
2245
      break;
2246 2247 2248 2249
    }
    case GSN_NODE_FAILREP:{
      const NodeFailRep * const rep =
	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
2250
      if (NodeBitmask::get(rep->theNodes,nodeId) ||
2251
	  waitCompleted == 1)
2252
	return 1326;
2253 2254
      // wait for next signal
      // master node will report aborted backup
2255 2256
      break;
    }
2257 2258 2259 2260
    default:
      report_unknown_signal(signal);
      return SEND_OR_RECEIVE_FAILED;
    }
2261 2262 2263 2264 2265 2266
  }
}

int 
MgmtSrvr::abortBackup(Uint32 backupId)
{
2267 2268
  SignalSender ss(theFacade);

2269 2270 2271 2272 2273 2274 2275 2276 2277
  bool next;
  NodeId nodeId = 0;
  while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
	theFacade->get_node_alive(nodeId) == false);
  
  if(!next){
    return NO_CONTACT_WITH_DB_NODES;
  }
  
2278
  SimpleSignal ssig;
2279

2280 2281 2282
  AbortBackupOrd* ord = CAST_PTR(AbortBackupOrd, ssig.getDataPtrSend());
  ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_ABORT_BACKUP_ORD, 
	   AbortBackupOrd::SignalLength);
2283 2284 2285 2286 2287
  
  ord->requestType = AbortBackupOrd::ClientAbort;
  ord->senderData = 19;
  ord->backupId = backupId;
  
2288
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
2289 2290 2291 2292 2293 2294 2295 2296 2297 2298
}


/*****************************************************************************
 * Global Replication
 *****************************************************************************/

int
MgmtSrvr::repCommand(Uint32* repReqId, Uint32 request, bool waitCompleted)
{
2299
  require(false);
2300 2301 2302
  return 0;
}

tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
2303 2304 2305 2306 2307 2308 2309
MgmtSrvr::Allocated_resources::Allocated_resources(MgmtSrvr &m)
  : m_mgmsrv(m)
{
}

MgmtSrvr::Allocated_resources::~Allocated_resources()
{
2310
  Guard g(m_mgmsrv.m_node_id_mutex);
2311
  if (!m_reserved_nodes.isclear()) {
2312
    m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes); 
2313 2314
    // node has been reserved, force update signal to ndb nodes
    global_flag_send_heartbeat_now= 1;
2315 2316 2317

    char tmp_str[128];
    m_mgmsrv.m_reserved_nodes.getText(tmp_str);
2318
    g_eventLogger.info("Mgmt server state: nodeid %d freed, m_reserved_nodes %s.",
2319
		       get_nodeid(), tmp_str);
2320
  }
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
2321 2322 2323 2324 2325 2326 2327 2328
}

void
MgmtSrvr::Allocated_resources::reserve_node(NodeId id)
{
  m_reserved_nodes.set(id);
}

2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
NodeId
MgmtSrvr::Allocated_resources::get_nodeid() const
{
  for(Uint32 i = 0; i < MAX_NODES; i++)
  {
    if (m_reserved_nodes.get(i))
      return i;
  }
  return 0;
}

2340 2341 2342
int
MgmtSrvr::setDbParameter(int node, int param, const char * value,
			 BaseString& msg){
2343 2344 2345 2346

  if(NdbMutex_Lock(m_configMutex))
    return -1;

2347 2348 2349
  /**
   * Check parameter
   */
2350 2351
  ndb_mgm_configuration_iterator
    iter(* _config->m_configValues, CFG_SECTION_NODE);
2352 2353
  if(iter.first() != 0){
    msg.assign("Unable to find node section (iter.first())");
2354
    NdbMutex_Unlock(m_configMutex);
2355 2356 2357 2358 2359 2360 2361
    return -1;
  }
  
  Uint32 type = NODE_TYPE_DB + 1;
  if(node != 0){
    if(iter.find(CFG_NODE_ID, node) != 0){
      msg.assign("Unable to find node (iter.find())");
2362
      NdbMutex_Unlock(m_configMutex);
2363 2364 2365 2366
      return -1;
    }
    if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
      msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
2367
      NdbMutex_Unlock(m_configMutex);
2368 2369 2370 2371 2372 2373
      return -1;
    }
  } else {
    do {
      if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
	msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
2374
	NdbMutex_Unlock(m_configMutex);
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384
	return -1;
      }
      if(type == NODE_TYPE_DB)
	break;
    } while(iter.next() == 0);
  }
  
  if(type != NODE_TYPE_DB){
    msg.assfmt("Invalid node type or no such node (%d %d)", 
	       type, NODE_TYPE_DB);
2385
    NdbMutex_Unlock(m_configMutex);
2386 2387 2388 2389 2390
    return -1;
  }

  int p_type;
  unsigned val_32;
joreland@mysql.com's avatar
joreland@mysql.com committed
2391
  Uint64 val_64;
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401
  const char * val_char;
  do {
    p_type = 0;
    if(iter.get(param, &val_32) == 0){
      val_32 = atoi(value);
      break;
    }
    
    p_type++;
    if(iter.get(param, &val_64) == 0){
2402
      val_64 = strtoll(value, 0, 10);
2403 2404 2405 2406 2407 2408 2409 2410
      break;
    }
    p_type++;
    if(iter.get(param, &val_char) == 0){
      val_char = value;
      break;
    }
    msg.assign("Could not get parameter");
2411
    NdbMutex_Unlock(m_configMutex);
2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431
    return -1;
  } while(0);
  
  bool res = false;
  do {
    int ret = iter.get(CFG_TYPE_OF_SECTION, &type);
    assert(ret == 0);
    
    if(type != NODE_TYPE_DB)
      continue;
    
    Uint32 node;
    ret = iter.get(CFG_NODE_ID, &node);
    assert(ret == 0);
    
    ConfigValues::Iterator i2(_config->m_configValues->m_config, 
			      iter.m_config);
    switch(p_type){
    case 0:
      res = i2.set(param, val_32);
2432
      ndbout_c("Updating node %d param: %d to %d",  node, param, val_32);
2433 2434 2435
      break;
    case 1:
      res = i2.set(param, val_64);
2436
      ndbout_c("Updating node %d param: %d to %Ld",  node, param, val_32);
2437 2438 2439
      break;
    case 2:
      res = i2.set(param, val_char);
2440
      ndbout_c("Updating node %d param: %d to %s",  node, param, val_char);
2441 2442
      break;
    default:
2443
      require(false);
2444 2445 2446 2447 2448
    }
    assert(res);
  } while(node == 0 && iter.next() == 0);

  msg.assign("Success");
2449
  NdbMutex_Unlock(m_configMutex);
2450 2451
  return 0;
}
2452 2453 2454 2455 2456 2457 2458 2459 2460 2461
int
MgmtSrvr::setConnectionDbParameter(int node1, 
				   int node2,
				   int param,
				   int value,
				   BaseString& msg){
  Uint32 current_value,new_value;

  DBUG_ENTER("MgmtSrvr::setConnectionDbParameter");

2462 2463 2464 2465 2466 2467 2468
  if(NdbMutex_Lock(m_configMutex))
  {
    DBUG_RETURN(-1);
  }

  ndb_mgm_configuration_iterator 
    iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
2469 2470 2471

  if(iter.first() != 0){
    msg.assign("Unable to find connection section (iter.first())");
2472 2473
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2474 2475 2476 2477 2478 2479
  }

  for(;iter.valid();iter.next()) {
    Uint32 n1,n2;
    iter.get(CFG_CONNECTION_NODE_1, &n1);
    iter.get(CFG_CONNECTION_NODE_2, &n2);
2480 2481
    if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
       || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
2482 2483 2484 2485
      break;
  }
  if(!iter.valid()) {
    msg.assign("Unable to find connection between nodes");
2486
    NdbMutex_Unlock(m_configMutex);
2487
    DBUG_RETURN(-2);
2488 2489
  }
  
2490
  if(iter.get(param, &current_value) != 0) {
2491
    msg.assign("Unable to get current value of parameter");
2492
    NdbMutex_Unlock(m_configMutex);
2493
    DBUG_RETURN(-3);
2494 2495 2496 2497 2498
  }

  ConfigValues::Iterator i2(_config->m_configValues->m_config, 
			    iter.m_config);

tulin@build.mysql.com's avatar
tulin@build.mysql.com committed
2499
  if(i2.set(param, (unsigned)value) == false) {
2500
    msg.assign("Unable to set new value of parameter");
2501
    NdbMutex_Unlock(m_configMutex);
2502
    DBUG_RETURN(-4);
2503 2504
  }
  
2505
  if(iter.get(param, &new_value) != 0) {
2506
    msg.assign("Unable to get parameter after setting it.");
2507
    NdbMutex_Unlock(m_configMutex);
2508
    DBUG_RETURN(-5);
2509 2510 2511
  }

  msg.assfmt("%u -> %u",current_value,new_value);
2512
  NdbMutex_Unlock(m_configMutex);
2513
  DBUG_RETURN(1);
2514 2515 2516
}


2517 2518 2519 2520
int
MgmtSrvr::getConnectionDbParameter(int node1, 
				   int node2,
				   int param,
2521
				   int *value,
2522 2523 2524
				   BaseString& msg){
  DBUG_ENTER("MgmtSrvr::getConnectionDbParameter");

2525 2526 2527 2528 2529 2530 2531
  if(NdbMutex_Lock(m_configMutex))
  {
    DBUG_RETURN(-1);
  }

  ndb_mgm_configuration_iterator
    iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
2532 2533 2534

  if(iter.first() != 0){
    msg.assign("Unable to find connection section (iter.first())");
2535 2536
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2537 2538 2539
  }

  for(;iter.valid();iter.next()) {
2540
    Uint32 n1=0,n2=0;
2541 2542
    iter.get(CFG_CONNECTION_NODE_1, &n1);
    iter.get(CFG_CONNECTION_NODE_2, &n2);
2543 2544
    if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
       || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
2545 2546 2547 2548
      break;
  }
  if(!iter.valid()) {
    msg.assign("Unable to find connection between nodes");
2549 2550
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2551 2552
  }
  
2553
  if(iter.get(param, (Uint32*)value) != 0) {
2554
    msg.assign("Unable to get current value of parameter");
2555 2556
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2557 2558
  }

2559
  msg.assfmt("%d",*value);
2560
  NdbMutex_Unlock(m_configMutex);
2561
  DBUG_RETURN(1);
2562
}
2563

2564 2565
void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd)
{
2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577
  if (theFacade->get_registry()->connect_server(sockfd))
  {
    /**
     * Force an update_connections() so that the
     * ClusterMgr and TransporterFacade is up to date
     * with the new connection.
     * Important for correct node id reservation handling
     */
    NdbMutex_Lock(theFacade->theMutexPtr);
    theFacade->get_registry()->update_connections();
    NdbMutex_Unlock(theFacade->theMutexPtr);
  }
2578 2579
}

2580
int MgmtSrvr::connect_to_self(void)
2581
{
2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596
  int r= 0;
  m_local_mgm_handle= ndb_mgm_create_handle();
  snprintf(m_local_mgm_connect_string,sizeof(m_local_mgm_connect_string),
           "localhost:%u",getPort());
  ndb_mgm_set_connectstring(m_local_mgm_handle, m_local_mgm_connect_string);

  if((r= ndb_mgm_connect(m_local_mgm_handle, 0, 0, 0)) < 0)
  {
    ndb_mgm_destroy_handle(&m_local_mgm_handle);
    return r;
  }
  // TransporterRegistry now owns this NdbMgmHandle and will destroy it.
  theFacade->get_registry()->set_mgm_handle(m_local_mgm_handle);

  return 0;
2597 2598 2599
}


joreland@mysql.com's avatar
joreland@mysql.com committed
2600 2601

template class MutexVector<unsigned short>;
tomas@poseidon.ndb.mysql.com's avatar
tomas@poseidon.ndb.mysql.com committed
2602
template class MutexVector<Ndb_mgmd_event_service::Event_listener>;
joreland@mysql.com's avatar
joreland@mysql.com committed
2603
template class MutexVector<EventSubscribeReq>;