NdbRestarter.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <NdbRestarter.hpp>
  14. #include <NdbOut.hpp>
  15. #include <NdbSleep.h>
  16. #include <NdbTick.h>
  17. #include <mgmapi_debug.h>
  18. #include <NDBT_Output.hpp>
  19. #include <random.h>
  20. #include <kernel/ndb_limits.h>
  21. #include <ndb_version.h>
  22. #define MGMERR(h) 
  23.   ndbout << "latest_error="<<ndb_mgm_get_latest_error(h) 
  24.  << ", line="<<ndb_mgm_get_latest_error_line(h) 
  25.  << endl;
  26. NdbRestarter::NdbRestarter(const char* _addr): 
  27.   connected(false),
  28.   handle(NULL),
  29.   m_config(0)
  30. {
  31.   if (_addr == NULL){
  32.     addr.assign("");
  33.   } else {
  34.     addr.assign(_addr);
  35.   }
  36. }
  37. NdbRestarter::~NdbRestarter(){
  38.   disconnect();
  39. }
  40. int NdbRestarter::getDbNodeId(int _i){
  41.   if (!isConnected())
  42.     return -1;
  43.   if (getStatus() != 0)
  44.     return -1;
  45.   for(size_t i = 0; i < ndbNodes.size(); i++){     
  46.     if (i == (unsigned)_i){
  47.       return ndbNodes[i].node_id;
  48.     }
  49.   }
  50.   return -1;
  51. }
  52. int
  53. NdbRestarter::restartOneDbNode(int _nodeId,
  54.        bool inital,
  55.        bool nostart,
  56.        bool abort){
  57.   if (!isConnected())
  58.     return -1;
  59.   int ret = 0;
  60.   
  61.   if ((ret = ndb_mgm_restart2(handle, 1, &_nodeId,
  62.       inital, nostart, abort)) <= 0) {
  63.     /**
  64.      * ndb_mgm_restart2 returned error, one reason could
  65.      * be that the node have not stopped fast enough!
  66.      * Check status of the node to see if it's on the 
  67.      * way down. If that's the case ignore the error
  68.      */ 
  69.     if (getStatus() != 0)
  70.       return -1;
  71.     g_info << "ndb_mgm_restart2 returned with error, checking node state" << endl;
  72.     for(size_t i = 0; i < ndbNodes.size(); i++){
  73.       if(ndbNodes[i].node_id == _nodeId){
  74. g_info <<_nodeId<<": status="<<ndbNodes[i].node_status<<endl;
  75. /* Node found check state */
  76. switch(ndbNodes[i].node_status){
  77. case NDB_MGM_NODE_STATUS_RESTARTING:
  78. case NDB_MGM_NODE_STATUS_SHUTTING_DOWN:
  79.   return 0;
  80. default:
  81.   break;
  82. }
  83.       }
  84.     }
  85.     
  86.     MGMERR(handle);
  87.     g_err  << "Could not stop node with id = "<< _nodeId << endl;
  88.     return -1;
  89.   }
  90.   return 0;
  91. }
  92. int
  93. NdbRestarter::getMasterNodeId(){
  94.   if (!isConnected())
  95.     return -1;
  96.   
  97.   if (getStatus() != 0)
  98.     return -1;
  99.   
  100.   int min = 0;
  101.   int node = -1;
  102.   for(size_t i = 0; i < ndbNodes.size(); i++){
  103.     if(min == 0 || ndbNodes[i].dynamic_id < min){
  104.       min = ndbNodes[i].dynamic_id;
  105.       node = ndbNodes[i].node_id;
  106.     }
  107.   }
  108.   return node;
  109. }
  110. int
  111. NdbRestarter::getRandomNotMasterNodeId(int rand){
  112.   int master = getMasterNodeId();
  113.   if(master == -1)
  114.     return -1;
  115.   Uint32 counter = 0;
  116.   rand = rand % ndbNodes.size();
  117.   while(counter++ < ndbNodes.size() && ndbNodes[rand].node_id == master)
  118.     rand = (rand + 1) % ndbNodes.size();
  119.   
  120.   if(ndbNodes[rand].node_id != master)
  121.     return ndbNodes[rand].node_id;
  122.   return -1;
  123. }
  124. int
  125. NdbRestarter::getRandomNodeOtherNodeGroup(int nodeId, int rand){
  126.   if (!isConnected())
  127.     return -1;
  128.   
  129.   if (getStatus() != 0)
  130.     return -1;
  131.   
  132.   int node_group = -1;
  133.   for(size_t i = 0; i < ndbNodes.size(); i++){
  134.     if(ndbNodes[i].node_id == nodeId){
  135.       node_group = ndbNodes[i].node_group;
  136.       break;
  137.     }
  138.   }
  139.   if(node_group == -1){
  140.     return -1;
  141.   }
  142.   Uint32 counter = 0;
  143.   rand = rand % ndbNodes.size();
  144.   while(counter++ < ndbNodes.size() && ndbNodes[rand].node_group == node_group)
  145.     rand = (rand + 1) % ndbNodes.size();
  146.   
  147.   if(ndbNodes[rand].node_group != node_group)
  148.     return ndbNodes[rand].node_id;
  149.   return -1;
  150. }
  151. int 
  152. NdbRestarter::waitClusterStarted(unsigned int _timeout){
  153.   return waitClusterState(NDB_MGM_NODE_STATUS_STARTED, _timeout);
  154. }
  155. int 
  156. NdbRestarter::waitClusterStartPhase(int _startphase, unsigned int _timeout){
  157.   return waitClusterState(NDB_MGM_NODE_STATUS_STARTING, _timeout, _startphase);
  158. }
  159. int 
  160. NdbRestarter::waitClusterSingleUser(unsigned int _timeout){
  161.   return waitClusterState(NDB_MGM_NODE_STATUS_SINGLEUSER, _timeout);
  162. }
  163. int 
  164. NdbRestarter::waitClusterNoStart(unsigned int _timeout){
  165.   return waitClusterState(NDB_MGM_NODE_STATUS_NOT_STARTED, _timeout);
  166. }
  167. int 
  168. NdbRestarter::waitClusterState(ndb_mgm_node_status _status,
  169.        unsigned int _timeout,
  170.        int _startphase){
  171.   int nodes[MAX_NDB_NODES];
  172.   int numNodes = 0;
  173.   if (getStatus() != 0)
  174.     return -1;
  175.   
  176.   // Collect all nodes into nodes
  177.   for (size_t i = 0; i < ndbNodes.size(); i++){
  178.     nodes[i] = ndbNodes[i].node_id;
  179.     numNodes++;
  180.   }
  181.   return waitNodesState(nodes, numNodes, _status, _timeout, _startphase);
  182. }
  183.  
  184. int 
  185. NdbRestarter::waitNodesState(int * _nodes, int _num_nodes,
  186.      ndb_mgm_node_status _status,
  187.      unsigned int _timeout,
  188.      int _startphase){
  189.   
  190.   if (!isConnected()){
  191.     g_err << "!isConnected"<<endl;
  192.     return -1;
  193.   }
  194.   unsigned int attempts = 0;
  195.   unsigned int resetAttempts = 0;
  196.   const unsigned int MAX_RESET_ATTEMPTS = 10;
  197.   bool allInState = false;    
  198.   while (allInState == false){
  199.     if (_timeout > 0 && attempts > _timeout){
  200.       /**
  201.        * Timeout has expired waiting for the nodes to enter
  202.        * the state we want
  203.        */
  204.       bool waitMore = false;
  205.       /** 
  206.        * Make special check if we are waiting for 
  207.        * cluster to become started
  208.        */
  209.       if(_status == NDB_MGM_NODE_STATUS_STARTED){
  210. waitMore = true;
  211. /**
  212.  * First check if any node is not starting
  213.  * then it's no idea to wait anymore
  214.  */
  215. for (size_t n = 0; n < ndbNodes.size(); n++){
  216.   if (ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTED &&
  217.       ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTING)
  218.     waitMore = false;
  219. }
  220.       } 
  221.       if (!waitMore || resetAttempts > MAX_RESET_ATTEMPTS){
  222. g_err << "waitNodeState("
  223.       << ndb_mgm_get_node_status_string(_status)
  224.       <<", "<<_startphase<<")"
  225.       << " timeout after " << attempts <<" attemps" << endl;
  226. return -1;
  227.       } 
  228.       g_err << "waitNodeState("
  229.     << ndb_mgm_get_node_status_string(_status)
  230.     <<", "<<_startphase<<")"
  231.     << " resetting number of attempts "
  232.     << resetAttempts << endl;
  233.       attempts = 0;
  234.       resetAttempts++;
  235.       
  236.     }
  237.     allInState = true;
  238.     if (getStatus() != 0){
  239.       g_err << "getStatus != 0" << endl;
  240.       return -1;
  241.     }
  242.     // ndbout << "waitNodeState; _num_nodes = " << _num_nodes << endl;
  243.     // for (int i = 0; i < _num_nodes; i++)
  244.     //   ndbout << " node["<<i<<"] =" <<_nodes[i] << endl;
  245.     for (int i = 0; i < _num_nodes; i++){
  246.       ndb_mgm_node_state* ndbNode = NULL;
  247.       for (size_t n = 0; n < ndbNodes.size(); n++){
  248. if (ndbNodes[n].node_id == _nodes[i])
  249.   ndbNode = &ndbNodes[n];
  250.       }
  251.       if(ndbNode == NULL){
  252. allInState = false;
  253. continue;
  254.       }
  255.       g_info << "State node " << ndbNode->node_id << " "
  256.      << ndb_mgm_get_node_status_string(ndbNode->node_status)<< endl;
  257.       assert(ndbNode != NULL);
  258.       if(_status == NDB_MGM_NODE_STATUS_STARTING && 
  259.  ((ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTING && 
  260.    ndbNode->start_phase >= _startphase) ||
  261.   (ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTED)))
  262. continue;
  263.       if (_status == NDB_MGM_NODE_STATUS_STARTING){
  264. g_info << "status = "  
  265.        << ndb_mgm_get_node_status_string(ndbNode->node_status)
  266.        <<", start_phase="<<ndbNode->start_phase<<endl;
  267. if (ndbNode->node_status !=  _status) {
  268.   if (ndbNode->node_status < _status)
  269.     allInState = false;
  270.   else 
  271.     g_info << "node_status(" << ndbNode->node_status
  272.    <<") != _status("<<_status<<")"<<endl;
  273. } else if (ndbNode->start_phase < _startphase)
  274.   allInState = false;
  275.       } else {
  276. if (ndbNode->node_status !=  _status) 
  277.   allInState = false;
  278.       }
  279.     }
  280.     g_info << "Waiting for cluster enter state" 
  281.     << ndb_mgm_get_node_status_string(_status)<< endl;
  282.     NdbSleep_SecSleep(1);
  283.     attempts++;
  284.   }
  285.   return 0;
  286. }
  287. int NdbRestarter::waitNodesStarted(int * _nodes, int _num_nodes,
  288.      unsigned int _timeout){
  289.   return waitNodesState(_nodes, _num_nodes, 
  290.   NDB_MGM_NODE_STATUS_STARTED, _timeout);  
  291. }
  292. int NdbRestarter::waitNodesStartPhase(int * _nodes, int _num_nodes, 
  293. int _startphase, unsigned int _timeout){
  294.   return waitNodesState(_nodes, _num_nodes, 
  295.   NDB_MGM_NODE_STATUS_STARTING, _timeout,
  296.   _startphase);  
  297. }
  298. int NdbRestarter::waitNodesNoStart(int * _nodes, int _num_nodes,
  299.      unsigned int _timeout){
  300.   return waitNodesState(_nodes, _num_nodes, 
  301.   NDB_MGM_NODE_STATUS_NOT_STARTED, _timeout);  
  302. }
  303. bool 
  304. NdbRestarter::isConnected(){
  305.   if (connected == true)
  306.     return true;
  307.   return connect() == 0;
  308. }
  309. int 
  310. NdbRestarter::connect(){
  311.   disconnect();
  312.   handle = ndb_mgm_create_handle();   
  313.   if (handle == NULL){
  314.     g_err << "handle == NULL" << endl;
  315.     return -1;
  316.   }
  317.   g_info << "Connecting to mgmsrv at " << addr.c_str() << endl;
  318.   if (ndb_mgm_set_connectstring(handle,addr.c_str()))
  319.   {
  320.     MGMERR(handle);
  321.     g_err  << "Connection to " << addr.c_str() << " failed" << endl;
  322.     return -1;
  323.   }
  324.   if (ndb_mgm_connect(handle, 0, 0, 0) == -1)
  325.   {
  326.     MGMERR(handle);
  327.     g_err  << "Connection to " << addr.c_str() << " failed" << endl;
  328.     return -1;
  329.   }
  330.   connected = true;
  331.   return 0;
  332. }
  333. void 
  334. NdbRestarter::disconnect(){
  335.   if (handle != NULL){
  336.     ndb_mgm_disconnect(handle);
  337.     ndb_mgm_destroy_handle(&handle);
  338.   }
  339.   connected = false;
  340. }
  341. int 
  342. NdbRestarter::getStatus(){
  343.   int retries = 0;
  344.   struct ndb_mgm_cluster_state * status;
  345.   struct ndb_mgm_node_state * node;
  346.   
  347.   ndbNodes.clear();
  348.   mgmNodes.clear();
  349.   apiNodes.clear();
  350.   if (!isConnected())
  351.     return -1;
  352.   
  353.   while(retries < 10){
  354.     status = ndb_mgm_get_status(handle);
  355.     if (status == NULL){
  356.       ndbout << "status==NULL, retries="<<retries<<endl;
  357.       MGMERR(handle);
  358.       retries++;
  359.       continue;
  360.     }
  361.     for (int i = 0; i < status->no_of_nodes; i++){
  362.       node = &status->node_states[i];      
  363.       switch(node->node_type){
  364.       case NDB_MGM_NODE_TYPE_NDB:
  365. ndbNodes.push_back(*node);
  366. break;
  367.       case NDB_MGM_NODE_TYPE_MGM:
  368. mgmNodes.push_back(*node);
  369. break;
  370.       case NDB_MGM_NODE_TYPE_API:
  371. apiNodes.push_back(*node);
  372. break;
  373.       default:
  374. if(node->node_status == NDB_MGM_NODE_STATUS_UNKNOWN ||
  375.    node->node_status == NDB_MGM_NODE_STATUS_NO_CONTACT){
  376.   retries++;
  377.   ndbNodes.clear();
  378.   mgmNodes.clear();
  379.   apiNodes.clear();
  380.   free(status); 
  381.   status = NULL;
  382.   i = status->no_of_nodes;
  383.   ndbout << "kalle"<< endl;
  384.   break;
  385. }
  386. abort();
  387. break;
  388.       }
  389.     }
  390.     if(status == 0){
  391.       ndbout << "status == 0" << endl;
  392.       continue;
  393.     }
  394.     free(status);
  395.     return 0;
  396.   }
  397.    
  398.   g_err  << "getStatus failed" << endl;
  399.   return -1;
  400. }
  401. int NdbRestarter::getNumDbNodes(){
  402.   if (!isConnected())
  403.     return -1;
  404.   if (getStatus() != 0)
  405.     return -1;
  406.   return ndbNodes.size();
  407. }
  408. int NdbRestarter::restartAll(bool initial,
  409.      bool nostart,
  410.      bool abort){
  411.   
  412.   if (!isConnected())
  413.     return -1;
  414.   if (ndb_mgm_restart2(handle, 0, NULL, initial, 1, abort) == -1) {
  415.     MGMERR(handle);
  416.     g_err  << "Could not restart(stop) all nodes " << endl;
  417.     // return -1; Continue anyway - Magnus
  418.   }
  419.   
  420.   if (waitClusterNoStart(60) != 0){
  421.     g_err << "Cluster didnt enter STATUS_NOT_STARTED within 60s" << endl;
  422.     return -1;
  423.   }
  424.   
  425.   if(nostart){
  426.     g_debug << "restartAll: nostart == true" << endl;
  427.     return 0;
  428.   }
  429.   if (ndb_mgm_start(handle, 0, NULL) == -1) {
  430.     MGMERR(handle);
  431.     g_err  << "Could not restart(start) all nodes " << endl;
  432.     return -1;
  433.   }
  434.   
  435.   return 0;
  436. }
  437. int NdbRestarter::startAll(){
  438.   if (!isConnected())
  439.     return -1;
  440.   if (ndb_mgm_start(handle, 0, NULL) == -1) {
  441.     MGMERR(handle);
  442.     g_err  << "Could not start all nodes " << endl;
  443.     return -1;
  444.   }
  445.   
  446.   return 0;
  447.   
  448. }
  449. int NdbRestarter::startNodes(int * nodes, int num_nodes){
  450.   if (!isConnected())
  451.     return -1;
  452.   
  453.   if (ndb_mgm_start(handle, num_nodes, nodes) != num_nodes) {
  454.     MGMERR(handle);
  455.     g_err  << "Could not start all nodes " << endl;
  456.     return -1;
  457.   }
  458.   
  459.   return 0;
  460. }
  461. int NdbRestarter::insertErrorInNode(int _nodeId, int _error){
  462.   if (!isConnected())
  463.     return -1;
  464.   ndb_mgm_reply reply;
  465.   reply.return_code = 0;
  466.   if (ndb_mgm_insert_error(handle, _nodeId, _error, &reply) == -1){
  467.     MGMERR(handle);
  468.     g_err << "Could not insert error in node with id = "<< _nodeId << endl;
  469.   }
  470.   if(reply.return_code != 0){
  471.     g_err << "Error: " << reply.message << endl;
  472.   }
  473.   return 0;
  474. }
  475. int NdbRestarter::insertErrorInAllNodes(int _error){
  476.   if (!isConnected())
  477.     return -1;
  478.   if (getStatus() != 0)
  479.     return -1;
  480.   int result = 0;
  481.  
  482.   for(size_t i = 0; i < ndbNodes.size(); i++){     
  483.     g_debug << "inserting error in node " << ndbNodes[i].node_id << endl;
  484.     if (insertErrorInNode(ndbNodes[i].node_id, _error) == -1)
  485.       result = -1;
  486.   }
  487.   return result;
  488. }
  489. int NdbRestarter::dumpStateOneNode(int _nodeId, int * _args, int _num_args){
  490.  if (!isConnected())
  491.     return -1;
  492.   ndb_mgm_reply reply;
  493.   reply.return_code = 0;
  494.   if (ndb_mgm_dump_state(handle, _nodeId, _args, _num_args, &reply) == -1){
  495.     MGMERR(handle);
  496.     g_err << "Could not dump state in node with id = "<< _nodeId << endl;
  497.   }
  498.   if(reply.return_code != 0){
  499.     g_err << "Error: " << reply.message << endl;
  500.   }
  501.   return reply.return_code;  
  502. }
  503. int NdbRestarter::dumpStateAllNodes(int * _args, int _num_args){
  504.  if (!isConnected())
  505.     return -1;
  506.  if (getStatus() != 0)
  507.    return -1;
  508.  int result = 0;
  509.  
  510.  for(size_t i = 0; i < ndbNodes.size(); i++){     
  511.    g_debug << "dumping state in node " << ndbNodes[i].node_id << endl;
  512.    if (dumpStateOneNode(ndbNodes[i].node_id, _args, _num_args) == -1)
  513.      result = -1;
  514.  }
  515.  return result;
  516. }
  517. int NdbRestarter::enterSingleUserMode(int _nodeId){
  518.   if (!isConnected())
  519.     return -1;
  520.   ndb_mgm_reply reply;
  521.   reply.return_code = 0;
  522.   if (ndb_mgm_enter_single_user(handle, _nodeId, &reply) == -1){
  523.     MGMERR(handle);
  524.     g_err << "Could not enter single user mode api node = "<< _nodeId << endl;
  525.   }
  526.   
  527.   if(reply.return_code != 0){
  528.     g_err << "Error: " << reply.message << endl;
  529.   }
  530.   
  531.   return reply.return_code;  
  532. }
  533. int NdbRestarter::exitSingleUserMode(){
  534.   if (!isConnected())
  535.     return -1;
  536.   ndb_mgm_reply reply;
  537.   reply.return_code = 0;
  538.   if (ndb_mgm_exit_single_user(handle, &reply) == -1){
  539.     MGMERR(handle);
  540.     g_err << "Could not exit single user mode " << endl;
  541.   }
  542.   if(reply.return_code != 0){
  543.     g_err << "Error: " << reply.message << endl;
  544.   }
  545.   return reply.return_code;  
  546. }
  547. ndb_mgm_configuration*
  548. NdbRestarter::getConfig(){
  549.   if(m_config) return m_config;
  550.   if (!isConnected())
  551.     return 0;
  552.   m_config = ndb_mgm_get_configuration(handle, 0);
  553.   return m_config;
  554. }
  555. template class Vector<ndb_mgm_node_state>;