MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbRestarter.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <NdbRestarter.hpp>
19 #include <NdbOut.hpp>
20 #include <NdbSleep.h>
21 #include <NdbTick.h>
22 #include <mgmapi_debug.h>
23 #include <NDBT_Output.hpp>
24 #include <random.h>
25 #include <kernel/ndb_limits.h>
26 #include <ndb_version.h>
27 #include <NodeBitmask.hpp>
28 
29 #define MGMERR(h) \
30  ndbout << "latest_error="<<ndb_mgm_get_latest_error(h) \
31  << ", line="<<ndb_mgm_get_latest_error_line(h) \
32  << ", mesg="<<ndb_mgm_get_latest_error_msg(h) \
33  << ", desc="<<ndb_mgm_get_latest_error_desc(h) \
34  << endl;
35 
36 
37 NdbRestarter::NdbRestarter(const char* _addr):
38  handle(NULL),
39  connected(false),
40  m_config(0),
41  m_reconnect(false)
42 {
43  if (_addr == NULL){
44  addr.assign("");
45  } else {
46  addr.assign(_addr);
47  }
48 }
49 
50 NdbRestarter::~NdbRestarter(){
51  disconnect();
52 }
53 
54 
55 int NdbRestarter::getDbNodeId(int _i){
56  if (!isConnected())
57  return -1;
58 
59  if (getStatus() != 0)
60  return -1;
61 
62  for(size_t i = 0; i < ndbNodes.size(); i++){
63  if (i == (unsigned)_i){
64  return ndbNodes[i].node_id;
65  }
66  }
67  return -1;
68 }
69 
70 
71 int
72 NdbRestarter::restartOneDbNode(int _nodeId,
73  bool inital,
74  bool nostart,
75  bool abort,
76  bool force)
77 {
78  return restartNodes(&_nodeId, 1,
79  (inital ? NRRF_INITIAL : 0) |
80  (nostart ? NRRF_NOSTART : 0) |
81  (abort ? NRRF_ABORT : 0) |
82  (force ? NRRF_FORCE : 0));
83 }
84 
85 int
86 NdbRestarter::restartNodes(int * nodes, int cnt,
87  Uint32 flags)
88 {
89  if (!isConnected())
90  return -1;
91 
92  int ret = 0;
93  int unused;
94  if ((ret = ndb_mgm_restart4(handle, cnt, nodes,
95  (flags & NRRF_INITIAL),
96  (flags & NRRF_NOSTART),
97  (flags & NRRF_ABORT),
98  (flags & NRRF_FORCE),
99  &unused)) <= 0)
100  {
108  if (getStatus() != 0)
109  return -1;
110 
111  g_info << "ndb_mgm_restart4 returned with error, checking node state"
112  << endl;
113 
114  for (int j = 0; j<cnt; j++)
115  {
116  int _nodeId = nodes[j];
117  for(size_t i = 0; i < ndbNodes.size(); i++)
118  {
119  if(ndbNodes[i].node_id == _nodeId)
120  {
121  g_info <<_nodeId<<": status="<<ndbNodes[i].node_status<<endl;
122  /* Node found check state */
123  switch(ndbNodes[i].node_status){
126  break;
127  default:
128  MGMERR(handle);
129  g_err << "Could not stop node with id = "<< _nodeId << endl;
130  return -1;
131  }
132  }
133  }
134  }
135  }
136 
137  return 0;
138 }
139 
140 int
141 NdbRestarter::getMasterNodeId(){
142  if (!isConnected())
143  return -1;
144 
145  if (getStatus() != 0)
146  return -1;
147 
148  int min = 0;
149  int node = -1;
150  for(size_t i = 0; i < ndbNodes.size(); i++){
151  if(min == 0 || ndbNodes[i].dynamic_id < min){
152  min = ndbNodes[i].dynamic_id;
153  node = ndbNodes[i].node_id;
154  }
155  }
156 
157  return node;
158 }
159 
160 int
161 NdbRestarter::getNodeGroup(int nodeId){
162  if (!isConnected())
163  return -1;
164 
165  if (getStatus() != 0)
166  return -1;
167 
168  for(size_t i = 0; i < ndbNodes.size(); i++)
169  {
170  if(ndbNodes[i].node_id == nodeId)
171  {
172  return ndbNodes[i].node_group;
173  }
174  }
175 
176  return -1;
177 }
178 
179 int
180 NdbRestarter::getNextMasterNodeId(int nodeId){
181  if (!isConnected())
182  return -1;
183 
184  if (getStatus() != 0)
185  return -1;
186 
187  size_t i;
188  for(i = 0; i < ndbNodes.size(); i++)
189  {
190  if(ndbNodes[i].node_id == nodeId)
191  {
192  break;
193  }
194  }
195  assert(i < ndbNodes.size());
196  if (i == ndbNodes.size())
197  return -1;
198 
199  int dynid = ndbNodes[i].dynamic_id;
200  int minid = dynid;
201  for (i = 0; i<ndbNodes.size(); i++)
202  if (ndbNodes[i].dynamic_id > minid)
203  minid = ndbNodes[i].dynamic_id;
204 
205  for (i = 0; i<ndbNodes.size(); i++)
206  if (ndbNodes[i].dynamic_id > dynid &&
207  ndbNodes[i].dynamic_id < minid)
208  {
209  minid = ndbNodes[i].dynamic_id;
210  }
211 
212  if (minid != ~0)
213  {
214  for (i = 0; i<ndbNodes.size(); i++)
215  if (ndbNodes[i].dynamic_id == minid)
216  return ndbNodes[i].node_id;
217  }
218 
219  return getMasterNodeId();
220 }
221 
222 int
223 NdbRestarter::getRandomNotMasterNodeId(int rand){
224  int master = getMasterNodeId();
225  if(master == -1)
226  return -1;
227 
228  Uint32 counter = 0;
229  rand = rand % ndbNodes.size();
230  while(counter++ < ndbNodes.size() && ndbNodes[rand].node_id == master)
231  rand = (rand + 1) % ndbNodes.size();
232 
233  if(ndbNodes[rand].node_id != master)
234  return ndbNodes[rand].node_id;
235  return -1;
236 }
237 
238 int
239 NdbRestarter::getRandomNodeOtherNodeGroup(int nodeId, int rand){
240  if (!isConnected())
241  return -1;
242 
243  if (getStatus() != 0)
244  return -1;
245 
246  int node_group = -1;
247  for(size_t i = 0; i < ndbNodes.size(); i++){
248  if(ndbNodes[i].node_id == nodeId){
249  node_group = ndbNodes[i].node_group;
250  break;
251  }
252  }
253  if(node_group == -1){
254  return -1;
255  }
256 
257  Uint32 counter = 0;
258  rand = rand % ndbNodes.size();
259  while(counter++ < ndbNodes.size() && ndbNodes[rand].node_group == node_group)
260  rand = (rand + 1) % ndbNodes.size();
261 
262  if(ndbNodes[rand].node_group != node_group)
263  return ndbNodes[rand].node_id;
264 
265  return -1;
266 }
267 
268 int
269 NdbRestarter::getRandomNodeSameNodeGroup(int nodeId, int rand){
270  if (!isConnected())
271  return -1;
272 
273  if (getStatus() != 0)
274  return -1;
275 
276  int node_group = -1;
277  for(size_t i = 0; i < ndbNodes.size(); i++){
278  if(ndbNodes[i].node_id == nodeId){
279  node_group = ndbNodes[i].node_group;
280  break;
281  }
282  }
283  if(node_group == -1){
284  return -1;
285  }
286 
287  Uint32 counter = 0;
288  rand = rand % ndbNodes.size();
289  while(counter++ < ndbNodes.size() &&
290  (ndbNodes[rand].node_id == nodeId ||
291  ndbNodes[rand].node_group != node_group))
292  rand = (rand + 1) % ndbNodes.size();
293 
294  if(ndbNodes[rand].node_group == node_group &&
295  ndbNodes[rand].node_id != nodeId)
296  return ndbNodes[rand].node_id;
297 
298  return -1;
299 }
300 
301 
302 // Wait until connected to ndb_mgmd
303 int
304 NdbRestarter::waitConnected(unsigned int _timeout){
305  _timeout*= 10;
306  while (isConnected() && getStatus() != 0){
307  if (_timeout-- == 0){
308  ndbout << "NdbRestarter::waitConnected failed" << endl;
309  return -1;
310  }
311  NdbSleep_MilliSleep(100);
312  }
313  return 0;
314 }
315 
316 int
317 NdbRestarter::waitClusterStarted(unsigned int _timeout){
318  return waitClusterState(NDB_MGM_NODE_STATUS_STARTED, _timeout);
319 }
320 
321 int
322 NdbRestarter::waitClusterStartPhase(int _startphase, unsigned int _timeout){
323  return waitClusterState(NDB_MGM_NODE_STATUS_STARTING, _timeout, _startphase);
324 }
325 
326 int
327 NdbRestarter::waitClusterSingleUser(unsigned int _timeout){
328  return waitClusterState(NDB_MGM_NODE_STATUS_SINGLEUSER, _timeout);
329 }
330 
331 int
332 NdbRestarter::waitClusterNoStart(unsigned int _timeout){
333  return waitClusterState(NDB_MGM_NODE_STATUS_NOT_STARTED, _timeout);
334 }
335 
336 int
337 NdbRestarter::waitClusterState(ndb_mgm_node_status _status,
338  unsigned int _timeout,
339  int _startphase){
340 
341  int nodes[MAX_NDB_NODES];
342  int numNodes = 0;
343 
344  if (getStatus() != 0){
345  g_err << "waitClusterStat: getStatus != 0" << endl;
346  return -1;
347  }
348 
349  // Collect all nodes into nodes
350  for (size_t i = 0; i < ndbNodes.size(); i++){
351  nodes[i] = ndbNodes[i].node_id;
352  numNodes++;
353  }
354 
355  return waitNodesState(nodes, numNodes, _status, _timeout, _startphase);
356 }
357 
358 
359 int
360 NdbRestarter::waitNodesState(const int * _nodes, int _num_nodes,
361  ndb_mgm_node_status _status,
362  unsigned int _timeout,
363  int _startphase){
364 
365  if (!isConnected()){
366  g_err << "!isConnected"<<endl;
367  return -1;
368  }
369 
370  unsigned int attempts = 0;
371  unsigned int resetAttempts = 0;
372  const unsigned int MAX_RESET_ATTEMPTS = 10;
373  bool allInState = false;
374  while (allInState == false){
375  if (_timeout > 0 && attempts > _timeout){
380  bool waitMore = false;
385  if(_status == NDB_MGM_NODE_STATUS_STARTED){
386  waitMore = true;
391  for (size_t n = 0; n < ndbNodes.size(); n++){
392  if (ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTED &&
393  ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTING)
394  waitMore = false;
395 
396  }
397  }
398 
399  if (!waitMore || resetAttempts > MAX_RESET_ATTEMPTS){
400  g_err << "waitNodesState("
402  <<", "<<_startphase<<")"
403  << " timeout after " << attempts <<" attemps" << endl;
404  return -1;
405  }
406 
407  g_err << "waitNodesState("
409  <<", "<<_startphase<<")"
410  << " resetting number of attempts "
411  << resetAttempts << endl;
412  attempts = 0;
413  resetAttempts++;
414 
415  }
416 
417  allInState = true;
418  if (getStatus() != 0){
419  g_err << "waitNodesState: getStatus != 0" << endl;
420  return -1;
421  }
422 
423  // ndbout << "waitNodeState; _num_nodes = " << _num_nodes << endl;
424  // for (int i = 0; i < _num_nodes; i++)
425  // ndbout << " node["<<i<<"] =" <<_nodes[i] << endl;
426 
427  for (int i = 0; i < _num_nodes; i++){
428  ndb_mgm_node_state* ndbNode = NULL;
429  for (size_t n = 0; n < ndbNodes.size(); n++){
430  if (ndbNodes[n].node_id == _nodes[i])
431  ndbNode = &ndbNodes[n];
432  }
433 
434  if(ndbNode == NULL){
435  allInState = false;
436  continue;
437  }
438 
439  g_info << "State node " << ndbNode->node_id << " "
442  g_info<< ", start_phase=" << ndbNode->start_phase;
443  g_info << endl;
444 
445  assert(ndbNode != NULL);
446 
447  if(_status == NDB_MGM_NODE_STATUS_STARTING &&
448  ((ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTING &&
449  ndbNode->start_phase >= _startphase) ||
451  continue;
452 
453  if (_status == NDB_MGM_NODE_STATUS_STARTING){
454  g_info << "status = "
456  <<", start_phase="<<ndbNode->start_phase<<endl;
457  if (ndbNode->node_status != _status) {
458  if (ndbNode->node_status < _status)
459  allInState = false;
460  else
461  g_info << "node_status(" << ndbNode->node_status
462  <<") != _status("<<_status<<")"<<endl;
463  } else if (ndbNode->start_phase < _startphase)
464  allInState = false;
465  } else {
466  if (ndbNode->node_status != _status)
467  allInState = false;
468  }
469  }
470  g_info << "Waiting for cluster enter state"
471  << ndb_mgm_get_node_status_string(_status)<< endl;
472  NdbSleep_SecSleep(1);
473  attempts++;
474  }
475  return 0;
476 }
477 
478 int NdbRestarter::waitNodesStarted(const int * _nodes, int _num_nodes,
479  unsigned int _timeout){
480  return waitNodesState(_nodes, _num_nodes,
481  NDB_MGM_NODE_STATUS_STARTED, _timeout);
482 }
483 
484 int NdbRestarter::waitNodesStartPhase(const int * _nodes, int _num_nodes,
485  int _startphase, unsigned int _timeout){
486  return waitNodesState(_nodes, _num_nodes,
488  _startphase);
489 }
490 
491 int NdbRestarter::waitNodesNoStart(const int * _nodes, int _num_nodes,
492  unsigned int _timeout){
493  return waitNodesState(_nodes, _num_nodes,
495 }
496 
497 bool
498 NdbRestarter::isConnected(){
499  if (connected == true)
500  return true;
501  return connect() == 0;
502 }
503 
504 int
505 NdbRestarter::connect(){
506  disconnect();
508  if (handle == NULL){
509  g_err << "handle == NULL" << endl;
510  return -1;
511  }
512  g_info << "Connecting to mgmsrv at " << addr.c_str() << endl;
514  {
515  MGMERR(handle);
516  g_err << "Connection to " << addr.c_str() << " failed" << endl;
517  return -1;
518  }
519 
520  if (ndb_mgm_connect(handle, 0, 0, 0) == -1)
521  {
522  MGMERR(handle);
523  g_err << "Connection to " << addr.c_str() << " failed" << endl;
524  return -1;
525  }
526 
527  connected = true;
528  return 0;
529 }
530 
531 void
532 NdbRestarter::disconnect(){
533  if (handle != NULL){
536  }
537  connected = false;
538 }
539 
540 int
541 NdbRestarter::getStatus(){
542  int retries = 0;
543  struct ndb_mgm_cluster_state * status;
544  struct ndb_mgm_node_state * node;
545 
546  ndbNodes.clear();
547  mgmNodes.clear();
548  apiNodes.clear();
549 
550  if (!isConnected())
551  return -1;
552 
553  while(retries < 10){
554  status = ndb_mgm_get_status(handle);
555  if (status == NULL){
556  if (m_reconnect){
557  if (connect() == 0){
558  g_err << "Reconnected..." << endl;
559  continue;
560  }
561  const int err = ndb_mgm_get_latest_error(handle);
562  if (err == NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET){
563  g_err << "Could not connect to socket, sleep and retry" << endl;
564  retries= 0;
565  NdbSleep_SecSleep(1);
566  continue;
567  }
568  }
569  const int err = ndb_mgm_get_latest_error(handle);
570  ndbout << "status==NULL, retries="<<retries<< " err=" << err << endl;
571  MGMERR(handle);
572  retries++;
573  continue;
574  }
575  for (int i = 0; i < status->no_of_nodes; i++){
576  node = &status->node_states[i];
577  switch(node->node_type){
579  ndbNodes.push_back(*node);
580  break;
582  mgmNodes.push_back(*node);
583  break;
585  apiNodes.push_back(*node);
586  break;
587  default:
590  retries++;
591  ndbNodes.clear();
592  mgmNodes.clear();
593  apiNodes.clear();
594  free(status);
595  status = NULL;
596  i = status->no_of_nodes;
597 
598  ndbout << "kalle"<< endl;
599  break;
600  }
601  abort();
602  break;
603  }
604  }
605  if(status == 0){
606  ndbout << "status == 0" << endl;
607  continue;
608  }
609  free(status);
610  return 0;
611  }
612 
613  g_err << "getStatus failed" << endl;
614  return -1;
615 }
616 
617 
618 int NdbRestarter::getNumDbNodes(){
619  if (!isConnected())
620  return -1;
621 
622  if (getStatus() != 0)
623  return -1;
624 
625  return ndbNodes.size();
626 }
627 
628 int NdbRestarter::restartAll(bool initial,
629  bool nostart,
630  bool abort,
631  bool force)
632 {
633  if (!isConnected())
634  return -1;
635 
636  int unused;
637  if (ndb_mgm_restart4(handle, 0, NULL, initial, 1, abort,
638  force, &unused) == -1) {
639  MGMERR(handle);
640  g_err << "Could not restart(stop) all nodes " << endl;
641  // return -1; Continue anyway - Magnus
642  }
643 
644  if (waitClusterNoStart(60) != 0){
645  g_err << "Cluster didnt enter STATUS_NOT_STARTED within 60s" << endl;
646  return -1;
647  }
648 
649  if(nostart){
650  g_debug << "restartAll: nostart == true" << endl;
651  return 0;
652  }
653 
654  if (ndb_mgm_start(handle, 0, NULL) == -1) {
655  MGMERR(handle);
656  g_err << "Could not restart(start) all nodes " << endl;
657  return -1;
658  }
659 
660  return 0;
661 }
662 
663 int NdbRestarter::startAll(){
664  if (!isConnected())
665  return -1;
666 
667  if (ndb_mgm_start(handle, 0, NULL) == -1) {
668  MGMERR(handle);
669  g_err << "Could not start all nodes " << endl;
670  return -1;
671  }
672 
673  return 0;
674 
675 }
676 
677 int NdbRestarter::startNodes(const int * nodes, int num_nodes){
678  if (!isConnected())
679  return -1;
680 
681  if (ndb_mgm_start(handle, num_nodes, nodes) != num_nodes) {
682  MGMERR(handle);
683  g_err << "Could not start all nodes " << endl;
684  return -1;
685  }
686 
687  return 0;
688 }
689 
690 int NdbRestarter::insertErrorInNode(int _nodeId, int _error){
691  if (!isConnected())
692  return -1;
693 
695  reply.return_code = 0;
696 
697  if (ndb_mgm_insert_error(handle, _nodeId, _error, &reply) == -1){
698  MGMERR(handle);
699  g_err << "Could not insert error in node with id = "<< _nodeId << endl;
700  }
701  if(reply.return_code != 0){
702  g_err << "Error: " << reply.message << endl;
703  }
704  return 0;
705 }
706 
707 int NdbRestarter::insertErrorInAllNodes(int _error){
708  if (!isConnected())
709  return -1;
710 
711  if (getStatus() != 0)
712  return -1;
713 
714  int result = 0;
715 
716  for(size_t i = 0; i < ndbNodes.size(); i++){
717  g_debug << "inserting error in node " << ndbNodes[i].node_id << endl;
718  if (insertErrorInNode(ndbNodes[i].node_id, _error) == -1)
719  result = -1;
720  }
721  return result;
722 
723 }
724 
725 
726 
727 int NdbRestarter::dumpStateOneNode(int _nodeId, const int * _args, int _num_args){
728  if (!isConnected())
729  return -1;
730 
731  ndb_mgm_reply reply;
732  reply.return_code = 0;
733 
734  if (ndb_mgm_dump_state(handle, _nodeId, _args, _num_args, &reply) == -1){
735  MGMERR(handle);
736  g_err << "Could not dump state in node with id = "<< _nodeId << endl;
737  }
738 
739  if(reply.return_code != 0){
740  g_err << "Error: " << reply.message << endl;
741  }
742  return reply.return_code;
743 }
744 
745 int NdbRestarter::dumpStateAllNodes(const int * _args, int _num_args){
746  if (!isConnected())
747  return -1;
748 
749  if (getStatus() != 0)
750  return -1;
751 
752  int result = 0;
753 
754  for(size_t i = 0; i < ndbNodes.size(); i++){
755  g_debug << "dumping state in node " << ndbNodes[i].node_id << endl;
756  if (dumpStateOneNode(ndbNodes[i].node_id, _args, _num_args) == -1)
757  result = -1;
758  }
759  return result;
760 
761 }
762 
763 
764 int NdbRestarter::enterSingleUserMode(int _nodeId){
765  if (!isConnected())
766  return -1;
767 
768  ndb_mgm_reply reply;
769  reply.return_code = 0;
770 
771  if (ndb_mgm_enter_single_user(handle, _nodeId, &reply) == -1){
772  MGMERR(handle);
773  g_err << "Could not enter single user mode api node = "<< _nodeId << endl;
774  }
775 
776  if(reply.return_code != 0){
777  g_err << "Error: " << reply.message << endl;
778  }
779 
780  return reply.return_code;
781 }
782 
783 
784 int NdbRestarter::exitSingleUserMode(){
785  if (!isConnected())
786  return -1;
787 
788  ndb_mgm_reply reply;
789  reply.return_code = 0;
790 
791  if (ndb_mgm_exit_single_user(handle, &reply) == -1){
792  MGMERR(handle);
793  g_err << "Could not exit single user mode " << endl;
794  }
795 
796  if(reply.return_code != 0){
797  g_err << "Error: " << reply.message << endl;
798  }
799  return reply.return_code;
800 }
801 
803 NdbRestarter::getConfig(){
804  if(m_config) return m_config;
805 
806  if (!isConnected())
807  return 0;
808  m_config = ndb_mgm_get_configuration(handle, 0);
809  return m_config;
810 }
811 
812 int
813 NdbRestarter::getNode(NodeSelector type)
814 {
815  switch(type){
816  case NS_RANDOM:
817  return getDbNodeId(rand() % getNumDbNodes());
818  case NS_MASTER:
819  return getMasterNodeId();
820  case NS_NON_MASTER:
821  return getRandomNotMasterNodeId(rand());
822  default:
823  abort();
824  }
825  return -1;
826 }
827 
828 
829 void
830 NdbRestarter::setReconnect(bool val){
831  m_reconnect= val;
832 }
833 
834 int
835 NdbRestarter::checkClusterAlive(const int * deadnodes, int num_nodes)
836 {
837  if (getStatus() != 0)
838  return -1;
839 
840  NdbNodeBitmask mask;
841  for (int i = 0; i<num_nodes; i++)
842  mask.set(deadnodes[i]);
843 
844  for (size_t n = 0; n < ndbNodes.size(); n++)
845  {
846  if (mask.get(ndbNodes[n].node_id))
847  continue;
848 
849  if (ndbNodes[n].node_status != NDB_MGM_NODE_STATUS_STARTED)
850  return ndbNodes[n].node_id;
851  }
852 
853  return 0;
854 }
855 
856 int
857 NdbRestarter::rollingRestart(Uint32 flags)
858 {
859  if (getStatus() != 0)
860  return -1;
861 
862  NdbNodeBitmask ng_mask;
863  NdbNodeBitmask restart_nodes;
864  Vector<int> nodes;
865  for(size_t i = 0; i < ndbNodes.size(); i++)
866  {
867  if (ng_mask.get(ndbNodes[i].node_group) == false)
868  {
869  ng_mask.set(ndbNodes[i].node_group);
870  nodes.push_back(ndbNodes[i].node_id);
871  restart_nodes.set(ndbNodes[i].node_id);
872  }
873  }
874 
875 loop:
876  if (ndb_mgm_restart2(handle, nodes.size(), nodes.getBase(),
877  (flags & NRRF_INITIAL) != 0,
878  (flags & NRRF_NOSTART) != 0,
879  (flags & NRRF_ABORT) != 0 || true) <= 0)
880  {
881  return -1;
882  }
883 
884  if (waitNodesNoStart(nodes.getBase(), nodes.size()))
885  return -1;
886 
887  if (startNodes(nodes.getBase(), nodes.size()))
888  return -1;
889 
890  if (waitClusterStarted())
891  return -1;
892 
893  nodes.clear();
894  for (Uint32 i = 0; i<ndbNodes.size(); i++)
895  {
896  if (restart_nodes.get(ndbNodes[i].node_id) == false)
897  {
898  nodes.push_back(ndbNodes[i].node_id);
899  restart_nodes.set(ndbNodes[i].node_id);
900  }
901  }
902  if (nodes.size())
903  goto loop;
904 
905  return 0;
906 }
907 
908 int
909 NdbRestarter::getMasterNodeVersion(int& version)
910 {
911  int masterNodeId = getMasterNodeId();
912  if (masterNodeId != -1)
913  {
914  for(size_t i = 0; i < ndbNodes.size(); i++)
915  {
916  if (ndbNodes[i].node_id == masterNodeId)
917  {
918  version = ndbNodes[i].version;
919  return 0;
920  }
921  }
922  }
923 
924  g_err << "Could not find node info for master node id "
925  << masterNodeId << endl;
926  return -1;
927 }
928 
929 int
930 NdbRestarter::getNodeTypeVersionRange(ndb_mgm_node_type type,
931  int& minVer,
932  int& maxVer)
933 {
934  if (!isConnected())
935  return -1;
936 
937  if (getStatus() != 0)
938  return -1;
939 
940  Vector<ndb_mgm_node_state>* nodeVec = NULL;
941 
942  switch (type)
943  {
945  nodeVec = &apiNodes;
946  break;
948  nodeVec = &ndbNodes;
949  break;
951  nodeVec = &mgmNodes;
952  break;
953  default:
954  g_err << "Bad node type : " << type << endl;
955  return -1;
956  }
957 
958  if (nodeVec->size() == 0)
959  {
960  g_err << "No nodes of type " << type << " online" << endl;
961  return -1;
962  }
963 
964  minVer = 0;
965  maxVer = 0;
966 
967  for(size_t i = 0; i < nodeVec->size(); i++)
968  {
969  int nodeVer = (*nodeVec)[i].version;
970  if ((minVer == 0) ||
971  (nodeVer < minVer))
972  minVer = nodeVer;
973 
974  if (nodeVer > maxVer)
975  maxVer = nodeVer;
976  }
977 
978  return 0;
979 }
980 
981 int
982 NdbRestarter::getNodeStatus(int nodeid)
983 {
984  if (getStatus() != 0)
985  return -1;
986 
987  for (size_t n = 0; n < ndbNodes.size(); n++)
988  {
989  if (ndbNodes[n].node_id == nodeid)
990  return ndbNodes[n].node_status;
991  }
992  return -1;
993 }
994 
995 template class Vector<ndb_mgm_node_state>;