MgmtSrvr.cpp 75.4 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_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

#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/ManagementServer.hpp>
41 42
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/NodeFailRep.hpp>
43
#include <signaldata/AllocNodeId.hpp>
44 45 46 47 48
#include <NdbSleep.h>
#include <EventLogger.hpp>
#include <DebuggerNames.hpp>
#include <ndb_version.h>

unknown's avatar
unknown 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>
unknown's avatar
unknown 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;\
    }\
  }

unknown's avatar
unknown 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);
  }
}
unknown's avatar
unknown 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

unknown's avatar
unknown 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) {
unknown's avatar
unknown committed
122 123 124 125
    /**
     * Handle started nodes
     */
    m_started_nodes.lock();
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    if (m_started_nodes.size() > 0)
    {
      // calculate max log level
      EventSubscribeReq req;
      {
        LogLevel tmp;
        m_event_listner.lock();
        for(int i = m_event_listner.m_clients.size() - 1; i >= 0; i--)
          tmp.set_max(m_event_listner[i].m_logLevel);
        m_event_listner.unlock();
        req = tmp;
      }
      req.blockRef = _ownReference;
      while (m_started_nodes.size() > 0)
      {
        Uint32 node = m_started_nodes[0];
        m_started_nodes.erase(0, false);
        m_started_nodes.unlock();
144

145 146 147 148 149 150 151 152 153
        setEventReportingLevelImpl(node, req);

        SetLogLevelOrd ord;
        ord = m_nodeLogLevel[node];
        setNodeLogLevelImpl(node, ord);

        m_started_nodes.lock();
      }
    }
unknown's avatar
unknown committed
154 155 156
    m_started_nodes.unlock();
    
    m_log_level_requests.lock();
157 158 159
    while (m_log_level_requests.size() > 0)
    {
      EventSubscribeReq req = m_log_level_requests[0];
unknown's avatar
unknown committed
160 161
      m_log_level_requests.erase(0, false);
      m_log_level_requests.unlock();
162

unknown's avatar
unknown committed
163 164 165 166
      if(req.blockRef == 0){
	req.blockRef = _ownReference;
	setEventReportingLevelImpl(0, req);
      } else {
167 168
        SetLogLevelOrd ord;
        ord = req;
unknown's avatar
unknown committed
169 170 171 172 173
	setNodeLogLevelImpl(req.blockRef, ord);
      }
      m_log_level_requests.lock();
    }      
    m_log_level_requests.unlock();
174
    NdbSleep_MilliSleep(_logLevelThreadSleep);  
unknown's avatar
unknown committed
175
  }
176 177 178 179 180
}

void
MgmtSrvr::startEventLog() 
{
181 182
  NdbMutex_Lock(m_configMutex);

183
  g_eventLogger.setCategory("MgmSrvr");
184

185 186 187 188 189 190
  ndb_mgm_configuration_iterator 
    iter(* _config->m_configValues, CFG_SECTION_NODE);

  if(iter.find(CFG_NODE_ID, _ownNodeId) != 0){
    NdbMutex_Unlock(m_configMutex);
    return;
191 192 193
  }
  
  const char * tmp;
194 195
  char errStr[100];
  int err= 0;
196
  BaseString logdest;
197 198 199
  char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId);
  NdbAutoPtr<char> tmp_aptr(clusterLog);

200
  if(iter.get(CFG_LOG_DESTINATION, &tmp) == 0){
201 202
    logdest.assign(tmp);
  }
203
  NdbMutex_Unlock(m_configMutex);
204
  
unknown's avatar
unknown committed
205
  if(logdest.length() == 0 || logdest == "") {
206 207
    logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6", 
		   clusterLog);
208
  }
209 210
  errStr[0]='\0';
  if(!g_eventLogger.addHandler(logdest, &err, sizeof(errStr), errStr)) {
unknown's avatar
unknown committed
211
    ndbout << "Warning: could not add log destination \""
212 213 214 215 216 217 218 219
           << logdest.c_str() << "\". Reason: ";
    if(err)
      ndbout << strerror(err);
    if(err && errStr[0]!='\0')
      ndbout << ", ";
    if(errStr[0]!='\0')
      ndbout << errStr;
    ndbout << endl;
220 221 222 223 224 225 226 227 228 229 230 231 232
  }
}

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

class ErrorItem 
{
public:
  int _errorCode;
unknown's avatar
unknown committed
233
  const char * _errorText;
234 235 236
};

bool
unknown's avatar
unknown committed
237
MgmtSrvr::setEventLogFilter(int severity, int enable)
238 239
{
  Logger::LoggerLevel level = (Logger::LoggerLevel)severity;
unknown's avatar
unknown committed
240
  if (enable > 0) {
241
    g_eventLogger.enable(level);
unknown's avatar
unknown committed
242
  } else if (enable == 0) {
243 244 245
    g_eventLogger.disable(level);
  } else if (g_eventLogger.isEnable(level)) {
    g_eventLogger.disable(level);
246
  } else {
247
    g_eventLogger.enable(level);
248
  }
249
  return g_eventLogger.isEnable(level);
250 251 252 253 254
}

bool 
MgmtSrvr::isEventLogFilterEnabled(int severity) 
{
255
  return g_eventLogger.isEnable((Logger::LoggerLevel)severity);
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 293 294 295 296 297 298 299 300 301
}

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."},
302 303 304 305
  {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" },
306 307
  {MgmtSrvr::UNSUPPORTED_NODE_SHUTDOWN,
   "Unsupported multi node shutdown. Abort option required." },
308 309 310
  {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."},
311 312 313 314 315 316 317
  {MgmtSrvr::NO_CONTACT_WITH_DB_NODES, "No contact with database nodes" }
};

int MgmtSrvr::translateStopRef(Uint32 errCode)
{
  switch(errCode){
  case StopRef::NodeShutdownInProgress:
318
    return NODE_SHUTDOWN_IN_PROGESS;
319 320
    break;
  case StopRef::SystemShutdownInProgress:
321
    return SYSTEM_SHUTDOWN_IN_PROGRESS;
322 323
    break;
  case StopRef::NodeShutdownWouldCauseSystemCrash:
324
    return NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH;
325
    break;
326 327 328
  case StopRef::UnsupportedNodeShutdown:
    return UNSUPPORTED_NODE_SHUTDOWN;
    break;
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
  }
  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;
}

unknown's avatar
unknown committed
347
int 
348 349 350
MgmtSrvr::getPort() const
{
  if(NdbMutex_Lock(m_configMutex))
unknown's avatar
unknown committed
351 352
    return 0;

353 354 355 356
  ndb_mgm_configuration_iterator 
    iter(* _config->m_configValues, CFG_SECTION_NODE);

  if(iter.find(CFG_NODE_ID, getOwnNodeId()) != 0){
unknown's avatar
unknown committed
357 358 359
    ndbout << "Could not retrieve configuration for Node " 
	   << getOwnNodeId() << " in config file." << endl 
	   << "Have you set correct NodeId for this node?" << endl;
360
    NdbMutex_Unlock(m_configMutex);
unknown's avatar
unknown committed
361 362 363 364
    return 0;
  }

  unsigned type;
365
  if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0 ||
unknown's avatar
unknown committed
366 367 368 369
     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;
370
    NdbMutex_Unlock(m_configMutex);
unknown's avatar
unknown committed
371 372 373 374
    return 0;
  }
  
  Uint32 port = 0;
375
  if(iter.get(CFG_MGM_PORT, &port) != 0){
unknown's avatar
unknown committed
376
    ndbout << "Could not find PortNumber in the configuration file." << endl;
377
    NdbMutex_Unlock(m_configMutex);
unknown's avatar
unknown committed
378 379
    return 0;
  }
unknown's avatar
unknown committed
380

381 382
  NdbMutex_Unlock(m_configMutex);

unknown's avatar
unknown committed
383 384 385
  return port;
}

386
/* Constructor */
387 388 389 390 391 392 393 394 395 396
int MgmtSrvr::init()
{
  if ( _ownNodeId > 0)
    return 0;
  return -1;
}

MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
		   const char *config_filename,
		   const char *connect_string) :
397 398
  _blockNumber(1), // Hard coded block number since it makes it easy to send
                   // signals to other management servers.
399
  m_socket_server(socket_server),
400 401 402
  _ownReference(0),
  theSignalIdleList(NULL),
  theWaitState(WAIT_SUBSCRIBE_CONF),
403
  m_local_mgm_handle(0),
404
  m_event_listner(this),
405
  m_master_node(0)
406
{
unknown's avatar
unknown committed
407
    
408 409
  DBUG_ENTER("MgmtSrvr::MgmtSrvr");

410 411
  _ownNodeId= 0;

412 413 414 415 416 417
  _config     = NULL;

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

unknown's avatar
unknown committed
418 419
  theFacade = 0;

420
  m_newConfig = NULL;
421 422
  if (config_filename)
    m_configFilename.assign(config_filename);
423 424 425

  m_nextConfigGenerationNumber = 0;

426 427
  m_config_retriever= new ConfigRetriever(connect_string,
					  NDB_VERSION, NDB_MGM_NODE_TYPE_MGM);
428 429
  // if connect_string explicitly given or
  // no config filename is given then
430
  // first try to allocate nodeid from another management server
431 432
  if ((connect_string || config_filename == NULL) &&
      (m_config_retriever->do_connect(0,0,0) == 0))
433 434 435 436 437 438
  {
    int tmp_nodeid= 0;
    tmp_nodeid= m_config_retriever->allocNodeId(0 /*retry*/,0 /*delay*/);
    if (tmp_nodeid == 0)
    {
      ndbout_c(m_config_retriever->getErrorString());
439
      require(false);
440 441 442 443 444 445
    }
    // read config from other managent server
    _config= fetchConfig();
    if (_config == 0)
    {
      ndbout << m_config_retriever->getErrorString() << endl;
446
      require(false);
447 448 449 450 451 452 453 454 455 456
    }
    _ownNodeId= tmp_nodeid;
  }

  if (_ownNodeId == 0)
  {
    // read config locally
    _config= readConfig();
    if (_config == 0) {
      ndbout << "Unable to read config file" << endl;
unknown's avatar
unknown committed
457
      exit(-1);
458 459 460
    }
  }

461 462 463 464 465 466 467
  theMgmtWaitForResponseCondPtr = NdbCondition_Create();

  m_configMutex = NdbMutex_Create();

  /**
   * Fill the nodeTypes array
   */
unknown's avatar
unknown committed
468
  for(Uint32 i = 0; i<MAX_NODES; i++) {
469
    nodeTypes[i] = (enum ndb_mgm_node_type)-1;
unknown's avatar
unknown committed
470 471
    m_connect_address[i].s_addr= 0;
  }
472

473
  {
474
    ndb_mgm_configuration_iterator
475 476 477
      iter(* _config->m_configValues, CFG_SECTION_NODE);

    for(iter.first(); iter.valid(); iter.next()){
478
      unsigned type, id;
479
      if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0)
480 481
	continue;
      
482
      if(iter.get(CFG_NODE_ID, &id) != 0)
483
	continue;
484
      
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
      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;
      default:
	break;
      }
500 501
    }
  }
502

503
  _props = NULL;
unknown's avatar
unknown committed
504
  BaseString error_string;
505 506 507 508

  if ((m_node_id_mutex = NdbMutex_Create()) == 0)
  {
    ndbout << "mutex creation failed line = " << __LINE__ << endl;
509
    require(false);
510 511
  }

512 513 514
  if (_ownNodeId == 0) // we did not get node id from other server
  {
    NodeId tmp= m_config_retriever->get_configuration_nodeid();
515
    int error_code;
516 517

    if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
518
		       0, 0, error_code, error_string)){
519 520
      ndbout << "Unable to obtain requested nodeid: "
	     << error_string.c_str() << endl;
521
      require(false);
522
    }
523
    _ownNodeId = tmp;
524
  }
525 526 527

  {
    DBUG_PRINT("info", ("verifyConfig"));
528 529 530 531
    if (!m_config_retriever->verifyConfig(_config->m_configValues,
					  _ownNodeId))
    {
      ndbout << m_config_retriever->getErrorString() << endl;
532
      require(false);
533 534 535
    }
  }

unknown's avatar
unknown committed
536
  // Setup clusterlog as client[0] in m_event_listner
unknown's avatar
unknown committed
537
  {
unknown's avatar
unknown committed
538
    Ndb_mgmd_event_service::Event_listener se;
unknown's avatar
unknown committed
539
    se.m_socket = NDB_INVALID_SOCKET;
unknown's avatar
unknown committed
540
    for(size_t t = 0; t<LogLevel::LOGLEVEL_CATEGORIES; t++){
unknown's avatar
unknown committed
541
      se.m_logLevel.setLogLevel((LogLevel::EventCategory)t, 7);
unknown's avatar
unknown committed
542
    }
unknown's avatar
unknown committed
543
    se.m_logLevel.setLogLevel(LogLevel::llError, 15);
unknown's avatar
unknown committed
544
    se.m_logLevel.setLogLevel(LogLevel::llConnection, 8);
unknown's avatar
unknown committed
545
    se.m_logLevel.setLogLevel(LogLevel::llBackup, 15);
unknown's avatar
unknown committed
546 547
    m_event_listner.m_clients.push_back(se);
    m_event_listner.m_logLevel = se.m_logLevel;
unknown's avatar
unknown committed
548
  }
unknown's avatar
unknown committed
549
  
550
  DBUG_VOID_RETURN;
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
}


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

  return true;
}

bool 
568
MgmtSrvr::start(BaseString &error_string)
569
{
570 571
  int mgm_connect_result;

unknown's avatar
unknown committed
572
  DBUG_ENTER("MgmtSrvr::start");
573
  if (_props == NULL) {
574 575
    if (!check_start()) {
      error_string.append("MgmtSrvr.cpp: check_start() failed.");
unknown's avatar
unknown committed
576
      DBUG_RETURN(false);
577
    }
578
  }
579
  theFacade= new TransporterFacade();
580 581 582
  
  if(theFacade == 0) {
    DEBUG("MgmtSrvr.cpp: theFacade is NULL.");
583
    error_string.append("MgmtSrvr.cpp: theFacade is NULL.");
unknown's avatar
unknown committed
584
    DBUG_RETURN(false);
585
  }  
586 587 588
  if ( theFacade->start_instance
       (_ownNodeId, (ndb_mgm_configuration*)_config->m_configValues) < 0) {
    DEBUG("MgmtSrvr.cpp: TransporterFacade::start_instance < 0.");
unknown's avatar
unknown committed
589
    DBUG_RETURN(false);
590
  }
591 592 593 594 595 596 597 598

  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);
599
  
600 601
  if(_blockNumber == -1){
    DEBUG("MgmtSrvr.cpp: _blockNumber is -1.");
602
    error_string.append("MgmtSrvr.cpp: _blockNumber is -1.");
603 604
    theFacade->stop_instance();
    theFacade = 0;
unknown's avatar
unknown committed
605
    DBUG_RETURN(false);
606
  }
607

608 609 610 611 612 613 614
  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.");
  }

615 616 617
  TransporterRegistry *reg = theFacade->get_registry();
  for(unsigned int i=0;i<reg->m_transporter_interface.size();i++) {
    BaseString msg;
618
    DBUG_PRINT("info",("Setting dynamic port %d->%d : %d",
619 620
		       reg->get_localNodeId(),
		       reg->m_transporter_interface[i].m_remote_nodeId,
621
		       reg->m_transporter_interface[i].m_s_service_port
622 623 624 625 626 627
		       )
	       );
    int res = setConnectionDbParameter((int)reg->get_localNodeId(),
				       (int)reg->m_transporter_interface[i]
				            .m_remote_nodeId,
				       (int)CFG_CONNECTION_SERVER_PORT,
628 629
				       reg->m_transporter_interface[i]
				            .m_s_service_port,
630 631 632 633
					 msg);
    DBUG_PRINT("info",("Set result: %d: %s",res,msg.c_str()));
  }

634 635 636 637 638 639 640 641 642 643 644 645 646
  _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);

unknown's avatar
unknown committed
647
  DBUG_RETURN(true);
648 649 650 651 652 653 654 655 656
}


//****************************************************************************
//****************************************************************************
MgmtSrvr::~MgmtSrvr() 
{
  if(theFacade != 0){
    theFacade->stop_instance();
unknown's avatar
unknown committed
657
    delete theFacade;
658 659 660 661 662
    theFacade = 0;
  }

  stopEventLog();

663 664 665
  NdbMutex_Destroy(m_node_id_mutex);
  NdbCondition_Destroy(theMgmtWaitForResponseCondPtr);
  NdbMutex_Destroy(m_configMutex);
666 667

  if(m_newConfig != NULL)
668 669 670 671 672
    free(m_newConfig);

  if(_config != NULL)
    delete _config;

673 674 675 676 677 678 679 680
  // End set log level thread
  void* res = 0;
  _isStopThread = true;

  if (_logLevelThread != NULL) {
    NdbThread_WaitFor(_logLevelThread, &res);
    NdbThread_Destroy(&_logLevelThread);
  }
unknown's avatar
unknown committed
681

682 683
  if (m_config_retriever)
    delete m_config_retriever;
684 685 686 687 688
}

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

689
int MgmtSrvr::okToSendTo(NodeId nodeId, bool unCond) 
690
{
691
  if(nodeId == 0 || getNodeType(nodeId) != NDB_MGM_NODE_TYPE_NDB)
692 693 694
    return WRONG_PROCESS_TYPE;
  // Check if we have contact with it
  if(unCond){
695
    if(theFacade->theClusterMgr->getNodeInfo(nodeId).connected)
696 697
      return 0;
  }
698
  else if (theFacade->get_node_alive(nodeId) == true)
699
    return 0;
700
  return NO_CONTACT_WITH_PROCESS;
701 702
}

703 704 705 706 707 708 709 710 711
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));
}

712 713 714 715 716
/*****************************************************************************
 * Starting and stopping database nodes
 ****************************************************************************/

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

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

int 
734
MgmtSrvr::versionNode(int nodeId, Uint32 &version, const char **address)
735
{
736 737
  version= 0;
  if (getOwnNodeId() == nodeId)
738
  {
739 740 741 742 743 744 745 746 747 748
    /**
     * 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.
     */
749
    sendVersionReq(nodeId, version, address);
750
    version= NDB_VERSION;
751 752 753 754 755 756 757 758 759 760 761 762 763 764
    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;
      }
    }
765
  }
766
  else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB)
767
  {
768
    ClusterMgr::Node node= theFacade->theClusterMgr->getNodeInfo(nodeId);
769 770
    if(node.connected)
      version= node.m_info.m_version;
771
    *address= get_connect_address(nodeId);
772
  }
773 774
  else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API ||
	   getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM)
775
  {
776
    return sendVersionReq(nodeId, version, address);
777
  }
778 779

  return 0;
780 781 782
}

int 
783
MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address)
784
{
785 786
  SignalSender ss(theFacade);
  ss.lock();
787

788 789 790 791 792 793
  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);
794

795 796
  int do_send = 1;
  NodeId nodeId;
797

798 799 800 801 802 803
  while (1)
  {
    if (do_send)
    {
      bool next;
      nodeId = 0;
804

805 806
      while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
	    okToSendTo(nodeId, true) != 0);
807 808 809 810 811 812 813 814 815 816 817

      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;
      }
818

819
      if(!next) return NO_CONTACT_WITH_DB_NODES;
820

821 822 823 824
      if (ss.sendSignal(nodeId, &ssig) != SEND_OK) {
	return SEND_OR_RECEIVE_FAILED;
      }
      do_send = 0;
825
    }
826 827 828 829 830 831 832 833 834 835

    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;
836 837 838
      struct in_addr in;
      in.s_addr= conf->inet_addr;
      *address= inet_ntoa(in);
839
      return 0;
840
    }
841 842 843 844 845 846
    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;
847
    }
848 849 850
    case GSN_NODE_FAILREP:{
      const NodeFailRep * const rep =
	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
851
      if (NodeBitmask::get(rep->theNodes,nodeId))
852 853 854 855 856 857 858 859 860 861
	do_send = 1; // retry with other node
      continue;
    }
    default:
      report_unknown_signal(signal);
      return SEND_OR_RECEIVE_FAILED;
    }
    break;
  } // while(1)

862 863 864
  return 0;
}

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 928 929 930 931
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;
}

932 933 934
/*
 * Common method for handeling all STOP_REQ signalling that
 * is used by Stopping, Restarting and Single user commands
935 936 937 938 939
 *
 * 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.
940
 */
941

942
int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
943 944 945 946 947 948 949 950
			   NodeBitmask &stoppedNodes,
			   Uint32 singleUserNodeId,
			   bool abort,
			   bool stop,
			   bool restart,
			   bool nostart,
			   bool initialStart)
{
951
  int error = 0;
952 953 954 955 956 957
  DBUG_ENTER("MgmtSrvr::sendSTOP_REQ");
  DBUG_PRINT("enter", ("no of nodes: %d  singleUseNodeId: %d  "
                       "abort: %d  stop: %d  restart: %d  "
                       "nostart: %d  initialStart: %d",
                       node_ids.size(), singleUserNodeId,
                       abort, stop, restart, nostart, initialStart));
958

959
  stoppedNodes.clear();
960

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

964 965 966
  SimpleSignal ssig;
  StopReq* const stopReq = CAST_PTR(StopReq, ssig.getDataPtrSend());
  ssig.set(ss, TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength);
967 968 969 970 971 972 973

  stopReq->requestInfo = 0;
  stopReq->apiTimeout = 5000;
  stopReq->transactionTimeout = 1000;
  stopReq->readOperationTimeout = 1000;
  stopReq->operationTimeout = 1000;
  stopReq->senderData = 12;
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
  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);
991 992
  }

993 994
  // send the signals
  NodeBitmask nodes;
995
  NodeId nodeId= 0;
996 997
  int use_master_node= 0;
  int do_send= 0;
998
  int do_stop_self= 0;
999
  NdbNodeBitmask nodes_to_stop;
1000
  {
1001
    for (unsigned i= 0; i < node_ids.size(); i++)
1002
    {
1003 1004 1005 1006
      nodeId= node_ids[i];
      if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM)
        nodes_to_stop.set(nodeId);
      else if (nodeId != getOwnNodeId())
1007 1008 1009 1010 1011 1012
      {
        error= sendStopMgmd(nodeId, abort, stop, restart,
                            nostart, initialStart);
        if (error == 0)
          stoppedNodes.set(nodeId);
      }
1013 1014
      else
        do_stop_self= 1;;
1015
    }
1016 1017 1018 1019 1020
  }
  int no_of_nodes_to_stop= nodes_to_stop.count();
  if (node_ids.size())
  {
    if (no_of_nodes_to_stop)
1021
    {
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
      do_send= 1;
      if (no_of_nodes_to_stop == 1)
      {
        nodeId= nodes_to_stop.find(0);
      }
      else // multi node stop, send to master
      {
        use_master_node= 1;
        nodes_to_stop.copyto(NdbNodeBitmask::Size, stopReq->nodes);
        StopReq::setStopNodes(stopReq->requestInfo, 1);
      }
1033
    }
1034
  }
1035
  else
1036
  {
1037
    nodeId= 0;
1038 1039 1040 1041 1042 1043 1044 1045 1046
    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);
      }
    }
1047 1048 1049 1050 1051 1052 1053 1054 1055
    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);
    }
  }
1056

1057
  // now wait for the replies
1058
  while (!nodes.isclear() || do_send)
1059
  {
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
    if (do_send)
    {
      int r;
      assert(nodes.count() == 0);
      if (use_master_node)
        nodeId= m_master_node;
      if ((r= okToSendTo(nodeId, true)) != 0)
      {
        bool next;
        if (!use_master_node)
          DBUG_RETURN(r);
        m_master_node= nodeId= 0;
        while((next= getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
              (r= okToSendTo(nodeId, true)) != 0);
        if (!next)
          DBUG_RETURN(NO_CONTACT_WITH_DB_NODES);
      }
      if (ss.sendSignal(nodeId, &ssig) != SEND_OK)
        DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
      nodes.set(nodeId);
      do_send= 0;
    }
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
    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);
1093 1094 1095 1096 1097 1098 1099
      if (ref->errorCode == StopRef::MultiNodeShutdownNotMaster)
      {
        assert(use_master_node);
        m_master_node= ref->masterNodeId;
        do_send= 1;
        continue;
      }
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
      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));
1110 1111 1112 1113 1114 1115
      if (singleUserNodeId != 0)
      {
        stoppedNodes.set(nodeId);
      }
      else
      {
1116
        assert(no_of_nodes_to_stop > 1);
1117 1118
        stoppedNodes.bitOR(nodes_to_stop);
      }
1119 1120 1121 1122 1123 1124 1125
      nodes.clear(nodeId);
      break;
    }
    case GSN_NF_COMPLETEREP:{
      const NFCompleteRep * const rep =
	CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
1126
      ndbout_c("sendSTOP_REQ Node %d fail completed", rep->failedNodeId);
1127
#endif
1128 1129 1130
      nodes.clear(rep->failedNodeId); // clear the failed node
      if (singleUserNodeId == 0)
        stoppedNodes.set(rep->failedNodeId);
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
      break;
    }
    case GSN_NODE_FAILREP:{
      const NodeFailRep * const rep =
	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
      break;
    }
    default:
      report_unknown_signal(signal);
#ifdef VM_TRACE
      ndbout_c("Unknown signal %d", gsn);
#endif
1143
      DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
1144
    }
1145
  }
1146 1147 1148 1149 1150 1151
  if (!error && do_stop_self)
  {
    if (restart)
      g_RestartServer= true;
    g_StopServer= true;
  }
1152
  DBUG_RETURN(error);
1153 1154
}

1155
/*
1156
 * Stop one nodes
1157 1158
 */

1159 1160
int MgmtSrvr::stopNodes(const Vector<NodeId> &node_ids,
                        int *stopCount, bool abort)
1161
{
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
  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;
    }
  }
1174
  NodeBitmask nodes;
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
  int ret= sendSTOP_REQ(node_ids,
                        nodes,
                        0,
                        abort,
                        false,
                        false,
                        false,
                        false);
  if (stopCount)
    *stopCount= nodes.count();
  return ret;
1186
}
1187

1188 1189 1190
/*
 * Perform system shutdown
 */
1191

1192 1193 1194
int MgmtSrvr::stop(int * stopCount, bool abort)
{
  NodeBitmask nodes;
1195 1196
  Vector<NodeId> node_ids;
  int ret = sendSTOP_REQ(node_ids,
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
			 nodes,
			 0,
			 abort,
			 true,
			 false,
			 false,
			 false);
  if (stopCount)
    *stopCount = nodes.count();
  return ret;
}

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

1213 1214 1215
int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
{
  if (getNodeType(singleUserNodeId) != NDB_MGM_NODE_TYPE_API)
1216
    return NODE_NOT_API_NODE;
1217 1218 1219 1220 1221 1222 1223
  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))
1224
      return OPERATION_NOT_ALLOWED_START_STOP;
1225
  }
1226
  NodeBitmask nodes;
1227 1228
  Vector<NodeId> node_ids;
  int ret = sendSTOP_REQ(node_ids,
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
			 nodes,
			 singleUserNodeId,
			 false,
			 false,
			 false,
			 false,
			 false);
  if (stopCount)
    *stopCount = nodes.count();
  return ret;
1239 1240
}

1241 1242 1243
/*
 * Perform node restart
 */
1244

1245 1246 1247
int MgmtSrvr::restartNodes(const Vector<NodeId> &node_ids,
                           int * stopCount, bool nostart,
                           bool initialStart, bool abort)
1248
{
1249
  NodeBitmask nodes;
1250 1251 1252 1253 1254 1255
  int ret= sendSTOP_REQ(node_ids,
                        nodes,
                        0,
                        abort,
                        false,
                        true,
1256
                        true,
1257
                        initialStart);
1258 1259 1260 1261

  if (ret)
    return ret;

1262 1263
  if (stopCount)
    *stopCount = nodes.count();
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
  
  // start up the nodes again
  int waitTime = 12000;
  NDB_TICKS maxTime = NdbTick_CurrentMillisecond() + waitTime;
  for (unsigned i = 0; i < node_ids.size(); i++)
  {
    NodeId nodeId= node_ids[i];
    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;
      const char *address;
      status(nodeId, &s, &version, &startPhase, 
             &system, &dynamicId, &nodeGroup, &connectCount, &address);
      NdbSleep_MilliSleep(100);  
      waitTime = (maxTime - NdbTick_CurrentMillisecond());
    }
  }

  if (nostart)
    return 0;

  for (unsigned i = 0; i < node_ids.size(); i++)
  {
    int result = start(node_ids[i]);
  }
  return 0;
1297
}
1298

1299 1300 1301
/*
 * Perform system restart
 */
1302

1303 1304
int MgmtSrvr::restart(bool nostart, bool initialStart, 
		      bool abort, int * stopCount )
1305
{
1306
  NodeBitmask nodes;
1307 1308
  Vector<NodeId> node_ids;
  int ret = sendSTOP_REQ(node_ids,
1309 1310 1311 1312 1313 1314 1315
			 nodes,
			 0,
			 abort,
			 true,
			 true,
			 true,
			 initialStart);
1316

1317 1318
  if (ret)
    return ret;
1319

1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
  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;
1349
      const char *address;
1350
      status(nodeId, &s, &version, &startPhase, 
1351
	     &system, &dynamicId, &nodeGroup, &connectCount, &address);
1352 1353
      NdbSleep_MilliSleep(100);  
      waitTime = (maxTime - NdbTick_CurrentMillisecond());
1354 1355 1356
    }
  }
  
1357 1358
  if(nostart)
    return 0;
1359
  
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
  /**
   * 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.
     */
1377
  }
1378 1379
  
  return 0;
1380 1381 1382
}

int
1383
MgmtSrvr::exitSingleUser(int * stopCount, bool abort)
1384 1385
{
  NodeId nodeId = 0;
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
  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();

1399 1400
  while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
    if(okToSendTo(nodeId, true) == 0){
1401 1402 1403
      SendStatus result = ss.sendSignal(nodeId, &ssig);
      if (result == SEND_OK)
	count++;
1404 1405 1406 1407
    }
  }

  if(stopCount != 0)
1408
    * stopCount = count;
1409

1410
  return 0;
1411 1412 1413 1414 1415 1416 1417 1418 1419
}

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

#include <ClusterMgr.hpp>

int 
1420
MgmtSrvr::status(int nodeId, 
1421 1422 1423 1424 1425
                 ndb_mgm_node_status * _status, 
		 Uint32 * version,
		 Uint32 * _phase, 
		 bool * _system,
		 Uint32 * dynamic,
1426
		 Uint32 * nodegroup,
1427 1428
		 Uint32 * connectCount,
		 const char **address)
1429
{
1430 1431
  if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API ||
      getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM) {
1432 1433 1434
    versionNode(nodeId, *version, address);
  } else {
    *address= get_connect_address(nodeId);
1435 1436 1437
  }

  const ClusterMgr::Node node = 
1438
    theFacade->theClusterMgr->getNodeInfo(nodeId);
1439 1440 1441 1442 1443 1444

  if(!node.connected){
    * _status = NDB_MGM_NODE_STATUS_NO_CONTACT;
    return 0;
  }
  
1445
  if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB) {
1446 1447 1448 1449 1450
    * version = node.m_info.m_version;
  }

  * dynamic = node.m_state.dynamicId;
  * nodegroup = node.m_state.nodeGroup;
1451 1452
  * connectCount = node.m_info.m_connectCount;
  
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502
  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;
  }
1503
  
1504 1505 1506 1507
  return -1;
}

int 
1508
MgmtSrvr::setEventReportingLevelImpl(int nodeId, 
unknown's avatar
unknown committed
1509
				     const EventSubscribeReq& ll)
1510
{
1511 1512
  SignalSender ss(theFacade);
  ss.lock();
1513

1514
  SimpleSignal ssig;
1515
  EventSubscribeReq * dst = 
1516 1517 1518 1519 1520
    CAST_PTR(EventSubscribeReq, ssig.getDataPtrSend());
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_EVENT_SUBSCRIBE_REQ,
	   EventSubscribeReq::SignalLength);
  *dst = ll;

1521 1522 1523 1524 1525 1526 1527
  NodeBitmask nodes;
  nodes.clear();
  Uint32 max = (nodeId == 0) ? (nodeId = 1, MAX_NDB_NODES) : nodeId;
  for(; nodeId <= max; nodeId++)
  {
    if (nodeTypes[nodeId] != NODE_TYPE_DB)
      continue;
1528
    if (okToSendTo(nodeId, true))
1529 1530 1531 1532 1533 1534
      continue;
    if (ss.sendSignal(nodeId, &ssig) == SEND_OK)
    {
      nodes.set(nodeId);
    }
  }
1535

1536 1537
  int error = 0;
  while (!nodes.isclear())
1538 1539 1540
  {
    SimpleSignal *signal = ss.waitFor();
    int gsn = signal->readSignalNumber();
1541 1542
    nodeId = refToNode(signal->header.theSendersBlockRef);
    switch (gsn) {
1543
    case GSN_EVENT_SUBSCRIBE_CONF:{
1544
      nodes.clear(nodeId);
1545 1546 1547
      break;
    }
    case GSN_EVENT_SUBSCRIBE_REF:{
1548 1549 1550
      nodes.clear(nodeId);
      error = 1;
      break;
1551 1552 1553 1554
    }
    case GSN_NF_COMPLETEREP:{
      const NFCompleteRep * const rep =
	CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
1555
      nodes.clear(rep->failedNodeId);
1556 1557 1558
      break;
    }
    case GSN_NODE_FAILREP:{
1559
      // ignore, NF_COMPLETEREP will arrive later
1560 1561 1562 1563 1564 1565 1566
      break;
    }
    default:
      report_unknown_signal(signal);
      return SEND_OR_RECEIVE_FAILED;
    }
  }
1567 1568
  if (error)
    return SEND_OR_RECEIVE_FAILED;
1569 1570 1571 1572 1573 1574
  return 0;
}

//****************************************************************************
//****************************************************************************
int 
1575
MgmtSrvr::setNodeLogLevelImpl(int nodeId, const SetLogLevelOrd & ll)
1576
{
1577
  INIT_SIGNAL_SENDER(ss,nodeId);
1578

1579 1580 1581 1582 1583
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_SET_LOGLEVELORD,
	   SetLogLevelOrd::SignalLength);
  SetLogLevelOrd* const dst = CAST_PTR(SetLogLevelOrd, ssig.getDataPtrSend());
  *dst = ll;
unknown's avatar
unknown committed
1584
  
1585
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
unknown's avatar
unknown committed
1586
}
1587 1588 1589 1590 1591

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

int 
1592
MgmtSrvr::insertError(int nodeId, int errorNo) 
1593 1594 1595 1596 1597
{
  if (errorNo < 0) {
    return INVALID_ERROR_NUMBER;
  }

1598
  INIT_SIGNAL_SENDER(ss,nodeId);
1599
  
1600 1601 1602 1603
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TAMPER_ORD, 
	   TamperOrd::SignalLength);
  TamperOrd* const tamperOrd = CAST_PTR(TamperOrd, ssig.getDataPtrSend());
1604 1605
  tamperOrd->errorNo = errorNo;

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



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

int 
1615
MgmtSrvr::setTraceNo(int nodeId, int traceNo)
1616 1617 1618 1619 1620
{
  if (traceNo < 0) {
    return INVALID_TRACE_NUMBER;
  }

1621
  INIT_SIGNAL_SENDER(ss,nodeId);
1622

1623 1624 1625
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);
  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1626 1627 1628 1629 1630
  testOrd->clear();
  // Assume TRACE command causes toggling. Not really defined... ? TODO
  testOrd->setTraceCommand(TestOrd::Toggle, 
			   (TestOrd::TraceSpecification)traceNo);

1631
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
}

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

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

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

int 
1650
MgmtSrvr::setSignalLoggingMode(int nodeId, LogMode mode, 
1651 1652
			       const Vector<BaseString>& blocks)
{
1653
  INIT_SIGNAL_SENDER(ss,nodeId);
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681

  // 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:
unknown's avatar
unknown committed
1682 1683 1684 1685
    ndbout_c("Unexpected value %d, MgmtSrvr::setSignalLoggingMode, line %d",
	     (unsigned)mode, __LINE__);
    assert(false);
    return -1;
1686 1687
  }

1688 1689
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);
1690

1691
  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
  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

1707
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1708 1709 1710 1711 1712
}

/*****************************************************************************
 * Signal tracing
 *****************************************************************************/
1713
int MgmtSrvr::startSignalTracing(int nodeId)
1714
{
1715
  INIT_SIGNAL_SENDER(ss,nodeId);
1716
  
1717 1718 1719 1720
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);

  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1721 1722 1723
  testOrd->clear();
  testOrd->setTestCommand(TestOrd::On);

1724
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1725 1726 1727
}

int 
1728
MgmtSrvr::stopSignalTracing(int nodeId) 
1729
{
1730
  INIT_SIGNAL_SENDER(ss,nodeId);
1731

1732 1733 1734
  SimpleSignal ssig;
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength);
  TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend());
1735 1736 1737
  testOrd->clear();
  testOrd->setTestCommand(TestOrd::Off);

1738
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1739 1740 1741 1742 1743 1744 1745 1746
}


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

int
1747
MgmtSrvr::dumpState(int nodeId, const char* args)
1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
{
  // 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++;
    }    
  }
  
1769
  return dumpState(nodeId, args_array, numArgs);
1770 1771 1772
}

int
1773
MgmtSrvr::dumpState(int nodeId, const Uint32 args[], Uint32 no)
1774
{
1775
  INIT_SIGNAL_SENDER(ss,nodeId);
1776 1777 1778

  const Uint32 len = no > 25 ? 25 : no;
  
1779
  SimpleSignal ssig;
1780
  DumpStateOrd * const dumpOrd = 
1781 1782
    CAST_PTR(DumpStateOrd, ssig.getDataPtrSend());
  ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_DUMP_STATE_ORD, len);
1783 1784 1785 1786 1787 1788 1789
  for(Uint32 i = 0; i<25; i++){
    if (i < len)
      dumpOrd->args[i] = args[i];
    else
      dumpOrd->args[i] = 0;
  }
  
1790
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
1791 1792 1793 1794 1795 1796
}


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

1797
const char* MgmtSrvr::getErrorText(int errorCode, char *buf, int buf_sz)
1798 1799 1800 1801
{

  for (int i = 0; i < noOfErrorCodes; ++i) {
    if (errorCode == errorTable[i]._errorCode) {
1802 1803 1804
      BaseString::snprintf(buf, buf_sz, errorTable[i]._errorText);
      buf[buf_sz-1]= 0;
      return buf;
1805 1806
    }
  }
1807 1808 1809 1810 1811

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

  return buf;
1812 1813 1814 1815 1816 1817 1818
}

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

1820 1821 1822
  switch (gsn) {
  case GSN_EVENT_SUBSCRIBE_CONF:
    break;
1823 1824
  case GSN_EVENT_SUBSCRIBE_REF:
    break;
1825
  case GSN_EVENT_REP:
unknown's avatar
unknown committed
1826
  {
unknown's avatar
unknown committed
1827
    eventReport(signal->getDataPtr());
1828
    break;
unknown's avatar
unknown committed
1829
  }
1830

1831
  case GSN_NF_COMPLETEREP:
1832
    break;
1833
  case GSN_NODE_FAILREP:
1834 1835 1836
    break;

  default:
1837
    g_eventLogger.error("Unknown signal received. SignalNumber: "
1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
			"%i from (%d, %x)",
			gsn,
			refToNode(signal->theSendersBlockRef),
			refToBlock(signal->theSendersBlockRef));
  }
  
  if (theWaitState == NO_WAIT) {
    NdbCondition_Signal(theMgmtWaitForResponseCondPtr);
  }
}

void
unknown's avatar
unknown committed
1850
MgmtSrvr::handleStatus(NodeId nodeId, bool alive, bool nfComplete)
1851
{
unknown's avatar
unknown committed
1852 1853
  DBUG_ENTER("MgmtSrvr::handleStatus");
  Uint32 theData[25];
unknown's avatar
unknown committed
1854 1855
  EventReport *rep = (EventReport *)theData;

unknown's avatar
unknown committed
1856
  theData[1] = nodeId;
1857
  if (alive) {
unknown's avatar
unknown committed
1858
    m_started_nodes.push_back(nodeId);
unknown's avatar
unknown committed
1859
    rep->setEventType(NDB_LE_Connected);
1860
  } else {
unknown's avatar
unknown committed
1861
    rep->setEventType(NDB_LE_Connected);
unknown's avatar
unknown committed
1862 1863
    if(nfComplete)
    {
unknown's avatar
unknown committed
1864
      DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1865
    }
1866
  }
unknown's avatar
unknown committed
1867 1868
  rep->setNodeId(_ownNodeId);
  eventReport(theData);
unknown's avatar
unknown committed
1869
  DBUG_VOID_RETURN;
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
}

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

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


//****************************************************************************
//****************************************************************************
void 
1887
MgmtSrvr::nodeStatusNotification(void* mgmSrv, Uint32 nodeId, 
1888 1889
				 bool alive, bool nfComplete)
{
unknown's avatar
unknown committed
1890 1891
  DBUG_ENTER("MgmtSrvr::nodeStatusNotification");
  DBUG_PRINT("enter",("nodeid= %d, alive= %d, nfComplete= %d", nodeId, alive, nfComplete));
unknown's avatar
unknown committed
1892
  ((MgmtSrvr*)mgmSrv)->handleStatus(nodeId, alive, nfComplete);
unknown's avatar
unknown committed
1893
  DBUG_VOID_RETURN;
1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904
}

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

1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922
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]);  
}

1923 1924 1925 1926 1927 1928 1929 1930 1931 1932
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);
1933
	connected_nodes.bitOR(node.m_state.m_connected_nodes);
1934 1935 1936 1937 1938
      }
    }
  }
}

1939
int
1940
MgmtSrvr::alloc_node_id_req(NodeId free_node_id, enum ndb_mgm_node_type type)
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952
{
  SignalSender ss(theFacade);
  ss.lock(); // lock will be released on exit

  SimpleSignal ssig;
  AllocNodeIdReq* req = CAST_PTR(AllocNodeIdReq, ssig.getDataPtrSend());
  ssig.set(ss, TestOrd::TraceAPI, QMGR, GSN_ALLOC_NODEID_REQ,
	   AllocNodeIdReq::SignalLength);
  
  req->senderRef = ss.getOwnRef();
  req->senderData = 19;
  req->nodeId = free_node_id;
1953
  req->nodeType = type;
1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021

  int do_send = 1;
  NodeId nodeId = 0;
  while (1)
  {
    if (nodeId == 0)
    {
      bool next;
      while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
            theFacade->get_node_alive(nodeId) == false);
      if (!next)
        return NO_CONTACT_WITH_DB_NODES;
      do_send = 1;
    }
    if (do_send)
    {
      if (ss.sendSignal(nodeId, &ssig) != SEND_OK) {
        return SEND_OR_RECEIVE_FAILED;
      }
      do_send = 0;
    }
    
    SimpleSignal *signal = ss.waitFor();

    int gsn = signal->readSignalNumber();
    switch (gsn) {
    case GSN_ALLOC_NODEID_CONF:
    {
      const AllocNodeIdConf * const conf =
        CAST_CONSTPTR(AllocNodeIdConf, signal->getDataPtr());
      return 0;
    }
    case GSN_ALLOC_NODEID_REF:
    {
      const AllocNodeIdRef * const ref =
        CAST_CONSTPTR(AllocNodeIdRef, signal->getDataPtr());
      if (ref->errorCode == AllocNodeIdRef::NotMaster ||
          ref->errorCode == AllocNodeIdRef::Busy)
      {
        do_send = 1;
        nodeId = refToNode(ref->masterRef);
        continue;
      }
      return ref->errorCode;
    }
    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)
        nodeId = 0;
      continue;
    }
    case GSN_NODE_FAILREP:{
      // ignore NF_COMPLETEREP will come
      continue;
    }
    default:
      report_unknown_signal(signal);
      return SEND_OR_RECEIVE_FAILED;
    }
  }
  return 0;
}

unknown's avatar
unknown committed
2022
bool
unknown's avatar
unknown committed
2023 2024 2025
MgmtSrvr::alloc_node_id(NodeId * nodeId, 
			enum ndb_mgm_node_type type,
			struct sockaddr *client_addr, 
2026
			SOCKET_SIZE_TYPE *client_addr_len,
2027 2028
			int &error_code, BaseString &error_string,
                        int log_event)
unknown's avatar
unknown committed
2029
{
2030 2031 2032 2033 2034
  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) {
2035
      error_string.appfmt("no-nodeid-checks set in management server.\n"
2036
			  "node id must be set explicitly in connectstring");
2037
      error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
2038 2039 2040 2041
      DBUG_RETURN(false);
    }
    DBUG_RETURN(true);
  }
2042
  Guard g(m_node_id_mutex);
2043
  int no_mgm= 0;
unknown's avatar
unknown committed
2044
  NodeBitmask connected_nodes(m_reserved_nodes);
2045
  get_connected_nodes(connected_nodes);
unknown's avatar
unknown committed
2046
  {
2047 2048 2049
    for(Uint32 i = 0; i < MAX_NODES; i++)
      if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM)
	no_mgm++;
unknown's avatar
unknown committed
2050
  }
2051 2052 2053
  bool found_matching_id= false;
  bool found_matching_type= false;
  bool found_free_node= false;
2054 2055
  unsigned id_found= 0;
  const char *config_hostname= 0;
2056 2057
  struct in_addr config_addr= {0};
  int r_config_addr= -1;
2058 2059
  unsigned type_c= 0;

2060 2061
  if(NdbMutex_Lock(m_configMutex))
  {
2062
    // should not happen
2063
    error_string.appfmt("unable to lock configuration mutex");
2064 2065
    error_code = NDB_MGM_ALLOCID_ERROR;
    DBUG_RETURN(false);
2066
  }
2067
  ndb_mgm_configuration_iterator
2068
    iter(* _config->m_configValues, CFG_SECTION_NODE);
unknown's avatar
unknown committed
2069 2070
  for(iter.first(); iter.valid(); iter.next()) {
    unsigned tmp= 0;
2071
    if(iter.get(CFG_NODE_ID, &tmp)) require(false);
unknown's avatar
unknown committed
2072 2073
    if (*nodeId && *nodeId != tmp)
      continue;
2074
    found_matching_id= true;
2075
    if(iter.get(CFG_TYPE_OF_SECTION, &type_c)) require(false);
unknown's avatar
unknown committed
2076
    if(type_c != (unsigned)type)
unknown's avatar
unknown committed
2077
      continue;
2078 2079 2080 2081
    found_matching_type= true;
    if (connected_nodes.get(tmp))
      continue;
    found_free_node= true;
2082
    if(iter.get(CFG_NODE_HOST, &config_hostname)) require(false);
2083 2084 2085
    if (config_hostname && config_hostname[0] == 0)
      config_hostname= 0;
    else if (client_addr) {
2086
      // check hostname compatability
2087 2088 2089
      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) {
2090 2091
	struct in_addr tmp_addr;
	if(Ndb_getInAddr(&tmp_addr, "localhost") != 0
2092
	   || memcmp(&tmp_addr, tmp_in, sizeof(config_addr)) != 0) {
2093
	  // not localhost
unknown's avatar
unknown committed
2094
#if 0
2095 2096 2097
	  ndbout << "MgmtSrvr::getFreeNodeId compare failed for \""
		 << config_hostname
		 << "\" id=" << tmp << endl;
unknown's avatar
unknown committed
2098
#endif
2099 2100 2101
	  continue;
	}
	// connecting through localhost
unknown's avatar
unknown committed
2102 2103 2104 2105 2106 2107 2108 2109
	// check if config_hostname is local
	if (!SocketServer::tryBind(0,config_hostname)) {
	  continue;
	}
      }
    } else { // client_addr == 0
      if (!SocketServer::tryBind(0,config_hostname)) {
	continue;
2110
      }
unknown's avatar
unknown committed
2111
    }
2112 2113 2114
    if (*nodeId != 0 ||
	type != NDB_MGM_NODE_TYPE_MGM ||
	no_mgm == 1) { // any match is ok
2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126

      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);
2127 2128 2129 2130 2131 2132 2133 2134
      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);
2135
      NdbMutex_Unlock(m_configMutex);
2136
      error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
2137 2138 2139 2140 2141
      DBUG_RETURN(false);
    }
    if (config_hostname == 0) {
      error_string.appfmt("Ambiguity for node id %d.\n"
			  "Suggest specifying node id in connectstring,\n"
unknown's avatar
unknown committed
2142
			  "or specifying unique host names in config file,\n"
2143 2144
			  "or specifying just one mgmt server in config file.",
			  tmp);
2145
      error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
2146 2147 2148 2149
      DBUG_RETURN(false);
    }
    id_found= tmp; // mgmt server matched, check for more matches
  }
2150
  NdbMutex_Unlock(m_configMutex);
2151

2152 2153
  if (id_found && client_addr != 0)
  {
2154
    int res = alloc_node_id_req(id_found, type);
2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184
    unsigned save_id_found = id_found;
    switch (res)
    {
    case 0:
      // ok continue
      break;
    case NO_CONTACT_WITH_DB_NODES:
      // ok continue
      break;
    default:
      // something wrong
      id_found = 0;
      break;

    }
    if (id_found == 0)
    {
      char buf[128];
      ndb_error_string(res, buf, sizeof(buf));
      error_string.appfmt("Cluster refused allocation of id %d. Error: %d (%s).",
			  save_id_found, res, buf);
      g_eventLogger.warning("Cluster refused allocation of id %d. "
                            "Connection from ip %s. "
                            "Returned error string \"%s\"", save_id_found,
                            inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr),
                            error_string.c_str());
      DBUG_RETURN(false);
    }
  }

2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207
  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);
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217
    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();
    }
    
2218 2219
    char tmp_str[128];
    m_reserved_nodes.getText(tmp_str);
2220 2221 2222
    g_eventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, "
                       "m_reserved_nodes %s.",
                       id_found, get_connect_address(id_found), tmp_str);
2223
    DBUG_RETURN(true);
unknown's avatar
unknown committed
2224
  }
2225 2226

  if (found_matching_type && !found_free_node) {
2227 2228
    // we have a temporary error which might be due to that 
    // we have got the latest connect status from db-nodes.  Force update.
2229 2230 2231
    global_flag_send_heartbeat_now= 1;
  }

2232 2233 2234 2235 2236
  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);
2237 2238
    alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)type_c,
					      &str);
2239 2240 2241
    type_c_string.assfmt("%s(%s)", alias, str);
  }

2242 2243
  if (*nodeId == 0)
  {
2244
    if (found_matching_id)
2245
    {
2246
      if (found_matching_type)
2247
      {
2248
	if (found_free_node)
2249
        {
2250
	  error_string.appfmt("Connection done from wrong host ip %s.",
2251
			      (client_addr)?
2252
                              inet_ntoa(((struct sockaddr_in *)
2253
					 (client_addr))->sin_addr):"");
2254 2255
          error_code = NDB_MGM_ALLOCID_ERROR;
        }
2256
	else
2257
        {
2258 2259
	  error_string.appfmt("No free node id found for %s.",
			      type_string.c_str());
2260 2261 2262
          error_code = NDB_MGM_ALLOCID_ERROR;
        }
      }
2263
      else
2264
      {
2265 2266
	error_string.appfmt("No %s node defined in config file.",
			    type_string.c_str());
2267 2268 2269
        error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
      }
    }
2270
    else
2271
    {
2272
      error_string.append("No nodes defined in config file.");
2273 2274 2275 2276 2277
      error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
    }
  }
  else
  {
2278
    if (found_matching_id)
2279
    {
2280
      if (found_matching_type)
2281 2282 2283
      {
	if (found_free_node)
        {
2284 2285
	  // have to split these into two since inet_ntoa overwrites itself
	  error_string.appfmt("Connection with id %d done from wrong host ip %s,",
2286 2287
			      *nodeId, inet_ntoa(((struct sockaddr_in *)
						  (client_addr))->sin_addr));
2288
	  error_string.appfmt(" expected %s(%s).", config_hostname,
2289 2290
			      r_config_addr ?
			      "lookup failed" : inet_ntoa(config_addr));
2291 2292 2293 2294
          error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
	}
        else
        {
2295 2296
	  error_string.appfmt("Id %d already allocated by another node.",
			      *nodeId);
2297 2298 2299
          error_code = NDB_MGM_ALLOCID_ERROR;
        }
      }
2300
      else
2301
      {
2302
	error_string.appfmt("Id %d configured as %s, connect attempted as %s.",
2303 2304
			    *nodeId, type_c_string.c_str(),
			    type_string.c_str());
2305 2306 2307
        error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
      }
    }
2308
    else
2309
    {
2310 2311
      error_string.appfmt("No node defined with id=%d in config file.",
			  *nodeId);
2312 2313
      error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
    }
2314
  }
2315

2316
  if (log_event || error_code == NDB_MGM_ALLOCID_CONFIG_MISMATCH)
2317
  {
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328
    g_eventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s."
                          " 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);
2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342
    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)
2343
      g_eventLogger.info("Mgmt server state: node id's %s connected but not reserved", 
2344 2345
			 tmp_connected.c_str());
    if (tmp_not_connected.length() > 0)
2346
      g_eventLogger.info("Mgmt server state: node id's %s not connected but reserved",
2347 2348
			 tmp_not_connected.c_str());
  }
2349
  DBUG_RETURN(false);
unknown's avatar
unknown committed
2350 2351
}

2352 2353 2354 2355 2356 2357 2358 2359 2360
bool
MgmtSrvr::getNextNodeId(NodeId * nodeId, enum ndb_mgm_node_type type) const 
{
  NodeId tmp = * nodeId;

  tmp++;
  while(nodeTypes[tmp] != type && tmp < MAX_NODES)
    tmp++;
  
2361
  if(tmp == MAX_NODES){
2362
    return false;
2363
  }
2364 2365 2366 2367 2368

  * nodeId = tmp;
  return true;
}

unknown's avatar
unknown committed
2369 2370
#include "Services.hpp"

2371
void
unknown's avatar
unknown committed
2372
MgmtSrvr::eventReport(const Uint32 * theData)
2373 2374
{
  const EventReport * const eventReport = (EventReport *)&theData[0];
unknown's avatar
unknown committed
2375
  
unknown's avatar
unknown committed
2376
  NodeId nodeId = eventReport->getNodeId();
2377
  Ndb_logevent_type type = eventReport->getEventType();
2378
  // Log event
2379
  g_eventLogger.log(type, theData, nodeId, 
unknown's avatar
unknown committed
2380 2381
		    &m_event_listner[0].m_logLevel);  
  m_event_listner.log(type, theData, nodeId);
2382 2383 2384 2385 2386
}

/***************************************************************************
 * Backup
 ***************************************************************************/
2387

2388
int
unknown's avatar
unknown committed
2389
MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
2390
{
2391 2392 2393
  SignalSender ss(theFacade);
  ss.lock(); // lock will be released on exit

2394 2395 2396 2397 2398 2399 2400 2401 2402 2403
  NodeId nodeId = m_master_node;
  if (okToSendTo(nodeId, false) != 0)
  {
    bool next;
    nodeId = m_master_node = 0;
    while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
          okToSendTo(nodeId, false) != 0);
    if(!next)
      return NO_CONTACT_WITH_DB_NODES;
  }
2404

2405 2406 2407 2408
  SimpleSignal ssig;
  BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
  ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ, 
	   BackupReq::SignalLength);
2409 2410 2411
  
  req->senderData = 19;
  req->backupDataLen = 0;
2412 2413
  assert(waitCompleted < 3);
  req->flags = waitCompleted & 0x3;
2414

2415 2416 2417 2418 2419
  BackupEvent event;
  int do_send = 1;
  while (1) {
    if (do_send)
    {
2420
      if (ss.sendSignal(nodeId, &ssig) != SEND_OK) {
2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444
	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
2445
      break;
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470
    }
    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){
2471
	m_master_node = nodeId = refToNode(ref->masterRef);
2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504
#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
2505
      break;
2506 2507 2508 2509
    }
    case GSN_NODE_FAILREP:{
      const NodeFailRep * const rep =
	CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
2510
      if (NodeBitmask::get(rep->theNodes,nodeId) ||
2511
	  waitCompleted == 1)
unknown's avatar
unknown committed
2512
	return 1326;
2513 2514
      // wait for next signal
      // master node will report aborted backup
2515 2516
      break;
    }
2517 2518 2519 2520
    default:
      report_unknown_signal(signal);
      return SEND_OR_RECEIVE_FAILED;
    }
2521 2522 2523 2524 2525 2526
  }
}

int 
MgmtSrvr::abortBackup(Uint32 backupId)
{
2527
  SignalSender ss(theFacade);
2528
  ss.lock(); // lock will be released on exit
2529

2530 2531 2532 2533 2534 2535 2536 2537 2538
  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;
  }
  
2539
  SimpleSignal ssig;
2540

2541 2542 2543
  AbortBackupOrd* ord = CAST_PTR(AbortBackupOrd, ssig.getDataPtrSend());
  ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_ABORT_BACKUP_ORD, 
	   AbortBackupOrd::SignalLength);
2544 2545 2546 2547 2548
  
  ord->requestType = AbortBackupOrd::ClientAbort;
  ord->senderData = 19;
  ord->backupId = backupId;
  
2549
  return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
2550
}
unknown's avatar
unknown committed
2551 2552 2553 2554 2555


MgmtSrvr::Allocated_resources::Allocated_resources(MgmtSrvr &m)
  : m_mgmsrv(m)
{
2556 2557
  m_reserved_nodes.clear();
  m_alloc_timeout= 0;
unknown's avatar
unknown committed
2558 2559 2560 2561
}

MgmtSrvr::Allocated_resources::~Allocated_resources()
{
2562
  Guard g(m_mgmsrv.m_node_id_mutex);
2563
  if (!m_reserved_nodes.isclear()) {
2564
    m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes); 
2565 2566
    // node has been reserved, force update signal to ndb nodes
    global_flag_send_heartbeat_now= 1;
2567 2568 2569

    char tmp_str[128];
    m_mgmsrv.m_reserved_nodes.getText(tmp_str);
2570
    g_eventLogger.info("Mgmt server state: nodeid %d freed, m_reserved_nodes %s.",
2571
		       get_nodeid(), tmp_str);
2572
  }
unknown's avatar
unknown committed
2573 2574 2575
}

void
2576
MgmtSrvr::Allocated_resources::reserve_node(NodeId id, NDB_TICKS timeout)
unknown's avatar
unknown committed
2577 2578
{
  m_reserved_nodes.set(id);
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591
  m_alloc_timeout= NdbTick_CurrentMillisecond() + timeout;
}

bool
MgmtSrvr::Allocated_resources::is_timed_out(NDB_TICKS tick)
{
  if (m_alloc_timeout && tick > m_alloc_timeout)
  {
    g_eventLogger.info("Mgmt server state: nodeid %d timed out.",
                       get_nodeid());
    return true;
  }
  return false;
unknown's avatar
unknown committed
2592 2593
}

2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604
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;
}

2605 2606 2607
int
MgmtSrvr::setDbParameter(int node, int param, const char * value,
			 BaseString& msg){
2608 2609 2610 2611

  if(NdbMutex_Lock(m_configMutex))
    return -1;

2612 2613 2614
  /**
   * Check parameter
   */
2615 2616
  ndb_mgm_configuration_iterator
    iter(* _config->m_configValues, CFG_SECTION_NODE);
2617 2618
  if(iter.first() != 0){
    msg.assign("Unable to find node section (iter.first())");
2619
    NdbMutex_Unlock(m_configMutex);
2620 2621 2622 2623 2624 2625 2626
    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())");
2627
      NdbMutex_Unlock(m_configMutex);
2628 2629 2630 2631
      return -1;
    }
    if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
      msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
2632
      NdbMutex_Unlock(m_configMutex);
2633 2634 2635 2636 2637 2638
      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))");
2639
	NdbMutex_Unlock(m_configMutex);
2640 2641 2642 2643 2644 2645 2646 2647 2648 2649
	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);
2650
    NdbMutex_Unlock(m_configMutex);
2651 2652 2653 2654 2655
    return -1;
  }

  int p_type;
  unsigned val_32;
unknown's avatar
unknown committed
2656
  Uint64 val_64;
2657 2658 2659 2660 2661 2662 2663 2664 2665 2666
  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){
2667
      val_64 = strtoll(value, 0, 10);
2668 2669 2670 2671 2672 2673 2674 2675
      break;
    }
    p_type++;
    if(iter.get(param, &val_char) == 0){
      val_char = value;
      break;
    }
    msg.assign("Could not get parameter");
2676
    NdbMutex_Unlock(m_configMutex);
2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696
    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);
unknown's avatar
unknown committed
2697
      ndbout_c("Updating node %d param: %d to %d",  node, param, val_32);
2698 2699 2700
      break;
    case 1:
      res = i2.set(param, val_64);
unknown's avatar
unknown committed
2701
      ndbout_c("Updating node %d param: %d to %Ld",  node, param, val_32);
2702 2703 2704
      break;
    case 2:
      res = i2.set(param, val_char);
unknown's avatar
unknown committed
2705
      ndbout_c("Updating node %d param: %d to %s",  node, param, val_char);
2706 2707
      break;
    default:
2708
      require(false);
2709 2710 2711 2712 2713
    }
    assert(res);
  } while(node == 0 && iter.next() == 0);

  msg.assign("Success");
2714
  NdbMutex_Unlock(m_configMutex);
2715 2716
  return 0;
}
2717 2718 2719 2720 2721 2722 2723 2724 2725 2726
int
MgmtSrvr::setConnectionDbParameter(int node1, 
				   int node2,
				   int param,
				   int value,
				   BaseString& msg){
  Uint32 current_value,new_value;

  DBUG_ENTER("MgmtSrvr::setConnectionDbParameter");

2727 2728 2729 2730 2731 2732 2733
  if(NdbMutex_Lock(m_configMutex))
  {
    DBUG_RETURN(-1);
  }

  ndb_mgm_configuration_iterator 
    iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
2734 2735 2736

  if(iter.first() != 0){
    msg.assign("Unable to find connection section (iter.first())");
2737 2738
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2739 2740 2741 2742 2743 2744
  }

  for(;iter.valid();iter.next()) {
    Uint32 n1,n2;
    iter.get(CFG_CONNECTION_NODE_1, &n1);
    iter.get(CFG_CONNECTION_NODE_2, &n2);
2745 2746
    if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
       || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
2747 2748 2749 2750
      break;
  }
  if(!iter.valid()) {
    msg.assign("Unable to find connection between nodes");
2751
    NdbMutex_Unlock(m_configMutex);
2752
    DBUG_RETURN(-2);
2753 2754
  }
  
2755
  if(iter.get(param, &current_value) != 0) {
2756
    msg.assign("Unable to get current value of parameter");
2757
    NdbMutex_Unlock(m_configMutex);
2758
    DBUG_RETURN(-3);
2759 2760 2761 2762 2763
  }

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

unknown's avatar
unknown committed
2764
  if(i2.set(param, (unsigned)value) == false) {
2765
    msg.assign("Unable to set new value of parameter");
2766
    NdbMutex_Unlock(m_configMutex);
2767
    DBUG_RETURN(-4);
2768 2769
  }
  
2770
  if(iter.get(param, &new_value) != 0) {
2771
    msg.assign("Unable to get parameter after setting it.");
2772
    NdbMutex_Unlock(m_configMutex);
2773
    DBUG_RETURN(-5);
2774 2775 2776
  }

  msg.assfmt("%u -> %u",current_value,new_value);
2777
  NdbMutex_Unlock(m_configMutex);
2778
  DBUG_RETURN(1);
2779 2780 2781
}


2782 2783 2784 2785
int
MgmtSrvr::getConnectionDbParameter(int node1, 
				   int node2,
				   int param,
2786
				   int *value,
2787 2788 2789
				   BaseString& msg){
  DBUG_ENTER("MgmtSrvr::getConnectionDbParameter");

2790 2791 2792 2793 2794 2795 2796
  if(NdbMutex_Lock(m_configMutex))
  {
    DBUG_RETURN(-1);
  }

  ndb_mgm_configuration_iterator
    iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
2797 2798 2799

  if(iter.first() != 0){
    msg.assign("Unable to find connection section (iter.first())");
2800 2801
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2802 2803 2804
  }

  for(;iter.valid();iter.next()) {
2805
    Uint32 n1=0,n2=0;
2806 2807
    iter.get(CFG_CONNECTION_NODE_1, &n1);
    iter.get(CFG_CONNECTION_NODE_2, &n2);
2808 2809
    if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
       || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
2810 2811 2812 2813
      break;
  }
  if(!iter.valid()) {
    msg.assign("Unable to find connection between nodes");
2814 2815
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2816 2817
  }
  
2818
  if(iter.get(param, (Uint32*)value) != 0) {
2819
    msg.assign("Unable to get current value of parameter");
2820 2821
    NdbMutex_Unlock(m_configMutex);
    DBUG_RETURN(-1);
2822 2823
  }

2824
  msg.assfmt("%d",*value);
2825
  NdbMutex_Unlock(m_configMutex);
2826
  DBUG_RETURN(1);
2827
}
2828

2829 2830
void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd)
{
2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842
  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);
  }
2843 2844
}

2845
int MgmtSrvr::connect_to_self(void)
2846
{
2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861
  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;
2862 2863 2864
}


unknown's avatar
unknown committed
2865 2866

template class MutexVector<unsigned short>;
unknown's avatar
unknown committed
2867
template class MutexVector<Ndb_mgmd_event_service::Event_listener>;
unknown's avatar
unknown committed
2868
template class MutexVector<EventSubscribeReq>;