MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testMgmd.cpp
1 /*
2  Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <NDBT.hpp>
20 #include <NDBT_Test.hpp>
21 #include <portlib/NdbDir.hpp>
22 #include "ConfigFactory.hpp"
23 #include <NdbMgmd.hpp>
24 #include <NdbProcess.hpp>
25 #include <NDBT_Find.hpp>
26 #include <NDBT_Workingdir.hpp>
27 
28 static bool file_exists(const char* path, Uint32 timeout = 1)
29 {
30  g_info << "File '" << path << "' ";
37  for (Uint32 i = 0; i < 10 * timeout; i++)
38  {
39  if (access(path, F_OK) == 0)
40  {
41  g_info << "exists" << endl;
42  return true;
43  }
44  if (i == 0)
45  {
46  g_info << "does not exist, retrying...";
47  }
48  NdbSleep_MilliSleep(100);
49  }
50  g_info << "does not exist" << endl;
51  return false;
52 }
53 
54 // Util function that concatenate strings to form a path
55 
56 static BaseString path(const char* first, ...)
57 {
58  BaseString path;
59  path.assign(first);
60 
61  const char* str;
62  va_list args;
63  va_start(args, first);
64  while ((str = va_arg(args, const char*)) != NULL)
65  {
66  path.appfmt("%s%s", DIR_SEPARATOR, str);
67  }
68  va_end(args);
69  return path;
70 }
71 
72 class Mgmd
73 {
74  NdbProcess* m_proc;
75  int m_nodeid;
76  BaseString m_name;
77  BaseString m_exe;
78  NdbMgmd m_mgmd_client;
79 
80  Mgmd(const Mgmd& other); // Not implemented
81 public:
82 
83  Mgmd(int nodeid) :
84  m_proc(NULL),
85  m_nodeid(nodeid)
86  {
87  m_name.assfmt("ndb_mgmd_%d", nodeid);
88 
89  NDBT_find_ndb_mgmd(m_exe);
90  }
91 
92  ~Mgmd()
93  {
94  if (m_proc)
95  {
96  //stop the proces
97  stop();
98  }
99 
100  }
101 
102  const char* name(void) const
103  {
104  return m_name.c_str();
105  }
106 
107  const char* exe(void) const
108  {
109  return m_exe.c_str();
110  }
111 
112  bool start(const char* working_dir, NdbProcess::Args& args)
113  {
114  g_info << "Starting " << name() << " ";
115  for (unsigned i = 0; i < args.args().size(); i++)
116  g_info << args.args()[i].c_str() << " ";
117  g_info << endl;
118 
119  m_proc = NdbProcess::create(name(),
120  exe(),
121  working_dir,
122  args);
123  return (m_proc != NULL);
124  }
125 
126  bool start_from_config_ini(const char* working_dir,
127  const char* first_extra_arg = NULL, ...)
128  {
129  NdbProcess::Args args;
130  args.add("--configdir=.");
131  args.add("-f config.ini");
132  args.add("--ndb-nodeid=", m_nodeid);
133  args.add("--nodaemon");
134  args.add("--log-name=", name());
135  args.add("--verbose");
136 
137  if (first_extra_arg)
138  {
139  // Append any extra args
140  va_list extra_args;
141  const char* str = first_extra_arg;
142  va_start(extra_args, first_extra_arg);
143  do
144  {
145  args.add(str);
146  } while ((str = va_arg(extra_args, const char*)) != NULL);
147  va_end(extra_args);
148  }
149 
150  return start(working_dir, args);
151  }
152 
153  bool start(const char* working_dir,
154  const char* first_extra_arg = NULL, ...)
155  {
156  NdbProcess::Args args;
157  args.add("--configdir=.");
158  args.add("--ndb-nodeid=", m_nodeid);
159  args.add("--nodaemon");
160  args.add("--log-name=", name());
161  args.add("--verbose");
162 
163  if (first_extra_arg)
164  {
165  // Append any extra args
166  va_list extra_args;
167  const char* str = first_extra_arg;
168  va_start(extra_args, first_extra_arg);
169  do
170  {
171  args.add(str);
172  } while ((str = va_arg(extra_args, const char*)) != NULL);
173  va_end(extra_args);
174  }
175 
176  return start(working_dir, args);
177  }
178 
179  bool stop(void)
180  {
181  g_info << "Stopping " << name() << endl;
182 
183  // Diconnect and close our "builtin" client
184  m_mgmd_client.close();
185 
186  if (m_proc == 0 || !m_proc->stop())
187  {
188  fprintf(stderr, "Failed to stop process %s\n", name());
189  return false; // Can't kill with -9 -> fatal error
190  }
191  int ret;
192  if (!m_proc->wait(ret, 300))
193  {
194  fprintf(stderr, "Failed to wait for process %s\n", name());
195  return false; // Can't wait after kill with -9 -> fatal error
196  }
197 
198  if (ret != 9)
199  {
200  fprintf(stderr, "stop ret: %u\n", ret);
201  return false; // Can't wait after kill with -9 -> fatal error
202  }
203 
204  delete m_proc;
205  m_proc = 0;
206 
207  return true;
208 
209  }
210 
211  bool wait(int& ret, int timeout = 300)
212  {
213  g_info << "Waiting for " << name() << endl;
214 
215  if (m_proc == 0 || !m_proc->wait(ret, timeout))
216  {
217  fprintf(stderr, "Failed to wait for process %s\n", name());
218  return false;
219  }
220  delete m_proc;
221  m_proc = 0;
222 
223  return true;
224 
225  }
226 
227  const BaseString connectstring(const Properties& config)
228  {
229  const char* hostname;
230  if (!get_section_string(config, m_name.c_str(), "HostName", &hostname))
231  return false;
232 
233  Uint32 port;
234  if (!get_section_uint32(config, m_name.c_str(), "PortNumber", &port))
235  return false;
236 
237  BaseString constr;
238  constr.assfmt("%s:%d", hostname, port);
239  return constr;
240  }
241 
242  bool connect(const Properties& config,
243  int num_retries = 60, int retry_delay_in_seconds = 1)
244  {
245  BaseString constr = connectstring(config);
246  g_info << "Connecting to " << name() << " @ " << constr.c_str() << endl;
247 
248  return m_mgmd_client.connect(constr.c_str(),
249  num_retries,
250  retry_delay_in_seconds);
251  }
252 
253  bool wait_confirmed_config(int timeout = 30)
254  {
255  if (!m_mgmd_client.is_connected())
256  {
257  g_err << "wait_confirmed_config: not connected!" << endl;
258  return false;
259  }
260 
261  int retries = 0;
262  Config conf;
263  while (!m_mgmd_client.get_config(conf))
264  {
265  retries++;
266 
267  if (retries == timeout * 10)
268  {
269  g_err << "wait_confirmed_config: Failed to get config within "
270  << timeout << " seconds" << endl;
271  return false;
272  }
273 
274  g_err << "Failed to get config, sleeping" << endl;
275  NdbSleep_MilliSleep(100);
276 
277  }
278  g_info << "wait_confirmed_config: ok" << endl;
279  return true;
280 
281  }
282 
283  NdbMgmHandle handle() { return m_mgmd_client.handle(); }
284 
285 private:
286 
287  bool get_section_string(const Properties& config,
288  const char* section_name,
289  const char* key,
290  const char** value) const
291  {
292  const Properties* section;
293  if (!config.get(section_name, &section))
294  return false;
295 
296  if (!section->get(key, value))
297  return false;
298  return true;
299  }
300 
301  bool get_section_uint32(const Properties& config,
302  const char* section_name,
303  const char* key,
304  Uint32* value) const
305  {
306  const Properties* section;
307  if (!config.get(section_name, &section))
308  return false;
309 
310  if (!section->get(key, value))
311  return false;
312  return true;
313  }
314 
315 };
316 
317 class MgmdProcessList : public Vector<Mgmd*>
318 {
319 public:
320 
321  ~MgmdProcessList()
322  {
323  // Delete and thus stop the mgmd(s)
324  for (unsigned i = 0; i < size(); i++)
325  {
326  Mgmd* mgmd = this->operator[](i);
327  delete mgmd;
328  }
329  // delete this->[i];
330  clear();
331  }
332 };
333 
334 
335 #define CHECK(x) \
336  if (!(x)) { \
337  fprintf(stderr, "CHECK(" #x ") failed at line: %d\n", \
338  __LINE__); \
339  return NDBT_FAILED; \
340  }
341 
342 int runTestBasic2Mgm(NDBT_Context* ctx, NDBT_Step* step)
343 {
344  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
345 
346  // Create config.ini
347  Properties config = ConfigFactory::create(2);
348  CHECK(ConfigFactory::write_config_ini(config,
349  path(wd.path(),
350  "config.ini",
351  NULL).c_str()));
352  // Start ndb_mgmd(s)
353  MgmdProcessList mgmds;
354  for (int i = 1; i <= 2; i++)
355  {
356  Mgmd* mgmd = new Mgmd(i);
357  mgmds.push_back(mgmd);
358  CHECK(mgmd->start_from_config_ini(wd.path()));
359  }
360 
361  // Connect the ndb_mgmd(s)
362  for (unsigned i = 0; i < mgmds.size(); i++)
363  CHECK(mgmds[i]->connect(config));
364 
365  // wait for confirmed config
366  for (unsigned i = 0; i < mgmds.size(); i++)
367  CHECK(mgmds[i]->wait_confirmed_config());
368 
369  // Check binary config files created
370  CHECK(file_exists(path(wd.path(),
371  "ndb_1_config.bin.1",
372  NULL).c_str()));
373  CHECK(file_exists(path(wd.path(),
374  "ndb_2_config.bin.1",
375  NULL).c_str()));
376 
377  // Stop the ndb_mgmd(s)
378  for (unsigned i = 0; i < mgmds.size(); i++)
379  CHECK(mgmds[i]->stop());
380 
381  // Start up the mgmd(s) again from config.bin
382  for (unsigned i = 0; i < mgmds.size(); i++)
383  CHECK(mgmds[i]->start_from_config_ini(wd.path()));
384 
385  // Connect the ndb_mgmd(s)
386  for (unsigned i = 0; i < mgmds.size(); i++)
387  CHECK(mgmds[i]->connect(config));
388 
389  // check ndb_X_config.bin.1 still exists but not ndb_X_config.bin.2
390  CHECK(file_exists(path(wd.path(),
391  "ndb_1_config.bin.1",
392  NULL).c_str()));
393  CHECK(file_exists(path(wd.path(),
394  "ndb_2_config.bin.1",
395  NULL).c_str()));
396 
397  CHECK(!file_exists(path(wd.path(),
398  "ndb_1_config.bin.2",
399  NULL).c_str()));
400  CHECK(!file_exists(path(wd.path(),
401  "ndb_2_config.bin.2",
402  NULL).c_str()));
403 
404  return NDBT_OK;
405 
406 }
407 
408 int runTestBug45495(NDBT_Context* ctx, NDBT_Step* step)
409 {
410  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
411 
412  g_err << "** Create config.ini" << endl;
413  Properties config = ConfigFactory::create(2);
414  CHECK(ConfigFactory::write_config_ini(config,
415  path(wd.path(),
416  "config.ini",
417  NULL).c_str()));
418  // Start ndb_mgmd(s)
419  MgmdProcessList mgmds;
420  for (int i = 1; i <= 2; i++)
421  {
422  Mgmd* mgmd = new Mgmd(i);
423  mgmds.push_back(mgmd);
424  CHECK(mgmd->start_from_config_ini(wd.path()));
425  }
426 
427  // Connect the ndb_mgmd(s)
428  for (unsigned i = 0; i < mgmds.size(); i++)
429  CHECK(mgmds[i]->connect(config));
430 
431  // wait for confirmed config
432  for (unsigned i = 0; i < mgmds.size(); i++)
433  CHECK(mgmds[i]->wait_confirmed_config());
434 
435  // Check binary config files created
436  CHECK(file_exists(path(wd.path(),
437  "ndb_1_config.bin.1",
438  NULL).c_str()));
439  CHECK(file_exists(path(wd.path(),
440  "ndb_2_config.bin.1",
441  NULL).c_str()));
442 
443  g_err << "** Restart one ndb_mgmd at a time --reload + --initial" << endl;
444  for (unsigned i = 0; i < mgmds.size(); i++)
445  {
446  CHECK(mgmds[i]->stop());
447  CHECK(mgmds[i]->start_from_config_ini(wd.path(),
448  "--reload", "--initial", NULL));
449  CHECK(mgmds[i]->connect(config));
450  CHECK(mgmds[i]->wait_confirmed_config());
451 
452  // check ndb_X_config.bin.1 still exists but not ndb_X_config.bin.2
453  CHECK(file_exists(path(wd.path(),
454  "ndb_1_config.bin.1",
455  NULL).c_str()));
456  CHECK(file_exists(path(wd.path(),
457  "ndb_2_config.bin.1",
458  NULL).c_str()));
459 
460  CHECK(!file_exists(path(wd.path(),
461  "ndb_1_config.bin.2",
462  NULL).c_str()));
463  CHECK(!file_exists(path(wd.path(),
464  "ndb_2_config.bin.2",
465  NULL).c_str()));
466  }
467 
468  g_err << "** Restart one ndb_mgmd at a time --initial" << endl;
469  for (unsigned i = 0; i < mgmds.size(); i++)
470  {
471  CHECK(mgmds[i]->stop());
472  CHECK(mgmds[i]->start_from_config_ini(wd.path(),
473  "--initial", NULL));
474  CHECK(mgmds[i]->connect(config));
475  CHECK(mgmds[i]->wait_confirmed_config());
476 
477  // check ndb_X_config.bin.1 still exists but not ndb_X_config.bin.2
478  CHECK(file_exists(path(wd.path(),
479  "ndb_1_config.bin.1",
480  NULL).c_str()));
481  CHECK(file_exists(path(wd.path(),
482  "ndb_2_config.bin.1",
483  NULL).c_str()));
484 
485  CHECK(!file_exists(path(wd.path(),
486  "ndb_1_config.bin.2",
487  NULL).c_str()));
488  CHECK(!file_exists(path(wd.path(),
489  "ndb_2_config.bin.2",
490  NULL).c_str()));
491  }
492 
493  g_err << "** Create config2.ini" << endl;
494  CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
495  CHECK(ConfigFactory::write_config_ini(config,
496  path(wd.path(),
497  "config2.ini",
498  NULL).c_str()));
499 
500  g_err << "** Restart one ndb_mgmd at a time --initial should not work" << endl;
501  for (unsigned i = 0; i < mgmds.size(); i++)
502  {
503  CHECK(mgmds[i]->stop());
504  // Start from config2.ini
505  CHECK(mgmds[i]->start_from_config_ini(wd.path(),
506  "-f config2.ini",
507  "--initial", NULL));
508 
509  // Wait for mgmd to exit and check return status
510  int ret;
511  CHECK(mgmds[i]->wait(ret));
512  CHECK(ret == 1);
513 
514  // check config files exist only for the still running mgmd(s)
515  for (unsigned j = 0; j < mgmds.size(); j++)
516  {
517  BaseString tmp;
518  tmp.assfmt("ndb_%d_config.bin.1", j+1);
519  CHECK(file_exists(path(wd.path(),
520  tmp.c_str(),
521  NULL).c_str()) == (j != i));
522  }
523 
524  // Start from config.ini again
525  CHECK(mgmds[i]->start_from_config_ini(wd.path(),
526  "--initial",
527  "--reload",
528  NULL));
529  CHECK(mgmds[i]->connect(config));
530  CHECK(mgmds[i]->wait_confirmed_config());
531  }
532 
533  g_err << "** Reload from config2.ini" << endl;
534  for (unsigned i = 0; i < mgmds.size(); i++)
535  {
536  CHECK(mgmds[i]->stop());
537  // Start from config2.ini
538  CHECK(mgmds[i]->start_from_config_ini(wd.path(),
539  "-f config2.ini",
540  "--reload", NULL));
541  CHECK(mgmds[i]->connect(config));
542  CHECK(mgmds[i]->wait_confirmed_config());
543  }
544 
545  CHECK(file_exists(path(wd.path(),
546  "ndb_1_config.bin.1",
547  NULL).c_str()));
548  CHECK(file_exists(path(wd.path(),
549  "ndb_2_config.bin.1",
550  NULL).c_str()));
551 
552  Uint32 timeout = 30;
553  CHECK(file_exists(path(wd.path(),
554  "ndb_1_config.bin.2",
555  NULL).c_str(), timeout));
556  CHECK(file_exists(path(wd.path(),
557  "ndb_2_config.bin.2",
558  NULL).c_str(), timeout));
559 
560  g_err << "** Reload mgmd initial(from generation=2)" << endl;
561  for (unsigned i = 0; i < mgmds.size(); i++)
562  {
563  CHECK(mgmds[i]->stop());
564  CHECK(mgmds[i]->start_from_config_ini(wd.path(),
565  "-f config2.ini",
566  "--reload", "--initial", NULL));
567 
568  CHECK(mgmds[i]->connect(config));
569  CHECK(mgmds[i]->wait_confirmed_config());
570 
571  // check config files exist
572  for (unsigned j = 0; j < mgmds.size(); j++)
573  {
574  BaseString tmp;
575  tmp.assfmt("ndb_%d_config.bin.1", j+1);
576  CHECK(file_exists(path(wd.path(),
577  tmp.c_str(),
578  NULL).c_str()) == (i < j));
579 
580  tmp.assfmt("ndb_%d_config.bin.2", j+1);
581  CHECK(file_exists(path(wd.path(),
582  tmp.c_str(),
583  NULL).c_str(),
584  timeout));
585  }
586  }
587 
588  return NDBT_OK;
589 }
590 
591 
592 
593 int runTestBug42015(NDBT_Context* ctx, NDBT_Step* step)
594 {
595  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
596 
597  g_err << "** Create config.ini" << endl;
598  Properties config = ConfigFactory::create(2);
599  CHECK(ConfigFactory::write_config_ini(config,
600  path(wd.path(),
601  "config.ini",
602  NULL).c_str()));
603 
604  MgmdProcessList mgmds;
605  // Start ndb_mgmd 1 from config.ini
606  Mgmd* mgmd = new Mgmd(1);
607  mgmds.push_back(mgmd);
608  CHECK(mgmd->start_from_config_ini(wd.path()));
609 
610  // Start ndb_mgmd 2 by fetching from first
611  Mgmd* mgmd2 = new Mgmd(2);
612  mgmds.push_back(mgmd2);
613  CHECK(mgmd2->start(wd.path(),
614  "--ndb-connectstring",
615  mgmd->connectstring(config).c_str(),
616  NULL));
617 
618  // Connect the ndb_mgmd(s)
619  for (unsigned i = 0; i < mgmds.size(); i++)
620  CHECK(mgmds[i]->connect(config));
621 
622  // wait for confirmed config
623  for (unsigned i = 0; i < mgmds.size(); i++)
624  CHECK(mgmds[i]->wait_confirmed_config());
625 
626  // Check binary config files created
627  CHECK(file_exists(path(wd.path(),
628  "ndb_1_config.bin.1",
629  NULL).c_str()));
630  CHECK(file_exists(path(wd.path(),
631  "ndb_2_config.bin.1",
632  NULL).c_str()));
633 
634  return NDBT_OK;
635 
636 }
637 
638 /* Test for bug 53008: --skip-config-cache */
639 int runTestNoConfigCache(NDBT_Context* ctx, NDBT_Step* step)
640 {
641  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
642 
643  g_err << "** Create config.ini" << endl;
644  Properties config = ConfigFactory::create();
645  CHECK(ConfigFactory::write_config_ini(config,
646  path(wd.path(),
647  "config.ini",
648  NULL).c_str()));
649 
650  // Start ndb_mgmd from config.ini
651  Mgmd* mgmd = new Mgmd(1);
652  CHECK(mgmd->start_from_config_ini(wd.path(), "--skip-config-cache", NULL));
653 
654  // Connect the ndb_mgmd(s)
655  CHECK(mgmd->connect(config));
656 
657  // wait for confirmed config
658  CHECK(mgmd->wait_confirmed_config());
659 
660  // Check binary config files *not* created
661  bool bin_conf_file = file_exists(path(wd.path(),
662  "ndb_1_config.bin.1",
663  NULL).c_str());
664  CHECK(bin_conf_file == false);
665 
666  mgmd->stop();
667  return NDBT_OK;
668 }
669 
670 
671 int runTestNowaitNodes(NDBT_Context* ctx, NDBT_Step* step)
672 {
673  MgmdProcessList mgmds;
674  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
675 
676  // Create config.ini
677  Properties config = ConfigFactory::create(2);
678  CHECK(ConfigFactory::write_config_ini(config,
679  path(wd.path(),
680  "config.ini",
681  NULL).c_str()));
682  // Start first ndb_mgmd
683  Mgmd* mgmd1 = new Mgmd(1);
684  {
685  mgmds.push_back(mgmd1);
686  CHECK(mgmd1->start_from_config_ini(wd.path(),
687  "--initial",
688  "--nowait-nodes=2",
689  NULL));
690 
691  // Connect the ndb_mgmd
692  CHECK(mgmd1->connect(config));
693 
694  // wait for confirmed config
695  CHECK(mgmd1->wait_confirmed_config());
696 
697  // Check binary config file created
698  CHECK(file_exists(path(wd.path(),
699  "ndb_1_config.bin.1",
700  NULL).c_str()));
701  }
702 
703  // Start second ndb_mgmd
704  {
705  Mgmd* mgmd2 = new Mgmd(2);
706  mgmds.push_back(mgmd2);
707  CHECK(mgmd2->start_from_config_ini(wd.path(),
708  "--initial",
709  NULL));
710 
711  // Connect the ndb_mgmd
712  CHECK(mgmd2->connect(config));
713 
714  // wait for confirmed config
715  CHECK(mgmd2->wait_confirmed_config());
716 
717  // Check binary config file created
718  CHECK(file_exists(path(wd.path(),
719  "ndb_2_config.bin.1",
720  NULL).c_str()));
721 
722  }
723 
724  // Create new config.ini
725  g_err << "** Create config2.ini" << endl;
726  CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
727  CHECK(ConfigFactory::write_config_ini(config,
728  path(wd.path(),
729  "config2.ini",
730  NULL).c_str()));
731 
732  g_err << "** Reload second mgmd from config2.ini" << endl;
733  {
734  Mgmd* mgmd2 = mgmds[1];
735  CHECK(mgmd2->stop());
736  // Start from config2.ini
737  CHECK(mgmd2->start_from_config_ini(wd.path(),
738  "-f config2.ini",
739  "--reload", NULL));
740  CHECK(mgmd2->connect(config));
741  CHECK(mgmd1->wait_confirmed_config());
742  CHECK(mgmd2->wait_confirmed_config());
743 
744  CHECK(file_exists(path(wd.path(),
745  "ndb_1_config.bin.1",
746  NULL).c_str()));
747  CHECK(file_exists(path(wd.path(),
748  "ndb_2_config.bin.1",
749  NULL).c_str()));
750 
751  // Both ndb_mgmd(s) should have reloaded and new binary config exist
752  CHECK(file_exists(path(wd.path(),
753  "ndb_1_config.bin.2",
754  NULL).c_str()));
755  CHECK(file_exists(path(wd.path(),
756  "ndb_2_config.bin.2",
757  NULL).c_str()));
758  }
759 
760  // Stop the ndb_mgmd(s)
761  for (unsigned i = 0; i < mgmds.size(); i++)
762  CHECK(mgmds[i]->stop());
763 
764  return NDBT_OK;
765 }
766 
767 
768 int runTestNowaitNodes2(NDBT_Context* ctx, NDBT_Step* step)
769 {
770  int ret;
771  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
772 
773  // Create config.ini
774  Properties config = ConfigFactory::create(2);
775  CHECK(ConfigFactory::write_config_ini(config,
776  path(wd.path(),
777  "config.ini",
778  NULL).c_str()));
779 
780  g_err << "** Start mgmd1 from config.ini" << endl;
781  MgmdProcessList mgmds;
782  Mgmd* mgmd1 = new Mgmd(1);
783  mgmds.push_back(mgmd1);
784  CHECK(mgmd1->start_from_config_ini(wd.path(),
785  "--initial",
786  "--nowait-nodes=1-255",
787  NULL));
788  CHECK(mgmd1->connect(config));
789  CHECK(mgmd1->wait_confirmed_config());
790 
791  // check config files exist
792  CHECK(file_exists(path(wd.path(),
793  "ndb_1_config.bin.1",
794  NULL).c_str()));
795 
796  g_err << "** Create config2.ini" << endl;
797  CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
798  CHECK(ConfigFactory::write_config_ini(config,
799  path(wd.path(),
800  "config2.ini",
801  NULL).c_str()));
802 
803  g_err << "** Start mgmd2 from config2.ini" << endl;
804  Mgmd* mgmd2 = new Mgmd(2);
805  mgmds.push_back(mgmd2);
806  CHECK(mgmd2->start_from_config_ini(wd.path(),
807  "-f config2.ini",
808  "--initial",
809  "--nowait-nodes=1-255",
810  NULL));
811  CHECK(mgmd2->wait(ret));
812  CHECK(ret == 1);
813 
814  CHECK(mgmd1->stop());
815 
816  g_err << "** Start mgmd2 again from config2.ini" << endl;
817  CHECK(mgmd2->start_from_config_ini(wd.path(),
818  "-f config2.ini",
819  "--initial",
820  "--nowait-nodes=1-255",
821  NULL));
822 
823 
824  CHECK(mgmd2->connect(config));
825  CHECK(mgmd2->wait_confirmed_config());
826 
827  // check config files exist
828  CHECK(file_exists(path(wd.path(),
829  "ndb_2_config.bin.1",
830  NULL).c_str()));
831 
832  g_err << "** Start mgmd1 from config.ini, mgmd2 should shutdown" << endl;
833  CHECK(mgmd1->start_from_config_ini(wd.path(),
834  "--initial",
835  "--nowait-nodes=1-255",
836  NULL));
837  CHECK(mgmd2->wait(ret));
838  CHECK(ret == 1);
839 
840  CHECK(mgmd1->stop());
841 
842  return NDBT_OK;
843 }
844 
845 int
846 runBug56844(NDBT_Context* ctx, NDBT_Step* step)
847 {
848  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
849 
850  g_err << "** Create config.ini" << endl;
851  Properties config = ConfigFactory::create(2);
852  CHECK(ConfigFactory::write_config_ini(config,
853  path(wd.path(),
854  "config.ini",
855  NULL).c_str()));
856  // Start ndb_mgmd(s)
857  MgmdProcessList mgmds;
858  for (int i = 1; i <= 2; i++)
859  {
860  Mgmd* mgmd = new Mgmd(i);
861  mgmds.push_back(mgmd);
862  CHECK(mgmd->start_from_config_ini(wd.path()));
863  }
864 
865  // Connect the ndb_mgmd(s)
866  for (unsigned i = 0; i < mgmds.size(); i++)
867  {
868  CHECK(mgmds[i]->connect(config));
869  }
870 
871  // wait for confirmed config
872  for (unsigned i = 0; i < mgmds.size(); i++)
873  {
874  CHECK(mgmds[i]->wait_confirmed_config());
875  }
876 
877  // stop them
878  for (unsigned i = 0; i < mgmds.size(); i++)
879  {
880  CHECK(mgmds[i]->stop());
881  }
882 
883  // Check binary config files created
884  CHECK(file_exists(path(wd.path(),
885  "ndb_1_config.bin.1",
886  NULL).c_str()));
887  CHECK(file_exists(path(wd.path(),
888  "ndb_2_config.bin.1",
889  NULL).c_str()));
890 
891  CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
892  CHECK(ConfigFactory::write_config_ini(config,
893  path(wd.path(),
894  "config2.ini",
895  NULL).c_str()));
896  Uint32 no = 2;
897  int loops = ctx->getNumLoops();
898  for (int l = 0; l < loops; l++, no++)
899  {
900  g_err << l << ": *** Reload from config.ini" << endl;
901  for (unsigned i = 0; i < mgmds.size(); i++)
902  {
903  // Start from config2.ini
904  CHECK(mgmds[i]->start_from_config_ini(wd.path(),
905  (l & 1) == 1 ?
906  "-f config.ini" :
907  "-f config2.ini",
908  "--reload", NULL));
909  }
910  for (unsigned i = 0; i < mgmds.size(); i++)
911  {
912  CHECK(mgmds[i]->connect(config));
913  CHECK(mgmds[i]->wait_confirmed_config());
914  }
915 
922  Uint32 timeout = 30;
923  for (unsigned i = 0; i < mgmds.size(); i++)
924  {
925  BaseString p = path(wd.path(), "", NULL);
926  p.appfmt("ndb_%u_config.bin.%u", i+1, no);
927  g_err << "CHECK(" << p.c_str() << ")" << endl;
928  CHECK(file_exists(p.c_str(), timeout));
929  }
930 
931  for (unsigned i = 0; i < mgmds.size(); i++)
932  {
933  CHECK(mgmds[i]->stop());
934  }
935  }
936  return NDBT_OK;
937 }
938 
939 static bool
940 get_status(const char* connectstring,
941  Properties& status)
942 {
943  NdbMgmd ndbmgmd;
944  if (!ndbmgmd.connect(connectstring))
945  return false;
946 
947  Properties args;
948  if (!ndbmgmd.call("get status", args,
949  "node status", status, NULL, true))
950  {
951  g_err << "fetch_mgmd_status: mgmd.call failed" << endl;
952  return false;
953  }
954  return true;
955 }
956 
957 static bool
958 value_equal(Properties& status,
959  int nodeid, const char* name,
960  const char* expected_value)
961 {
962  const char* value;
963  BaseString key;
964  key.assfmt("node.%d.%s", nodeid, name);
965  if (!status.get(key.c_str(), &value))
966  {
967  g_err << "value_equal: no value found for '" << name
968  << "." << nodeid << "'" << endl;
969  return false;
970  }
971 
972  if (strcmp(value, expected_value))
973  {
974  g_err << "value_equal: found unexpected value: '" << value
975  << "', expected: '" << expected_value << "'" <<endl;
976  return false;
977  }
978  g_info << "'" << value << "'=='" << expected_value << "'" << endl;
979  return true;
980 }
981 
982 #include <ndb_version.h>
983 
984 int runTestBug12352191(NDBT_Context* ctx, NDBT_Step* step)
985 {
986  BaseString version;
987  version.assfmt("%u", NDB_VERSION_D);
988  BaseString mysql_version;
989  mysql_version.assfmt("%u", NDB_MYSQL_VERSION_D);
990  BaseString address("127.0.0.1");
991 
992  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
993 
994  g_err << "** Create config.ini" << endl;
995  Properties config = ConfigFactory::create(2);
996  CHECK(ConfigFactory::write_config_ini(config,
997  path(wd.path(),
998  "config.ini",
999  NULL).c_str()));
1000 
1001  MgmdProcessList mgmds;
1002  const int nodeid1 = 1;
1003  Mgmd* mgmd1 = new Mgmd(nodeid1);
1004  mgmds.push_back(mgmd1);
1005 
1006  const int nodeid2 = 2;
1007  Mgmd* mgmd2 = new Mgmd(nodeid2);
1008  mgmds.push_back(mgmd2);
1009 
1010  // Start first mgmd
1011  CHECK(mgmd1->start_from_config_ini(wd.path()));
1012  CHECK(mgmd1->connect(config));
1013 
1014  Properties status1;
1015  CHECK(get_status(mgmd1->connectstring(config).c_str(), status1));
1016  //status1.print();
1017  // Check status for own mgm node, always CONNECTED
1018  CHECK(value_equal(status1, nodeid1, "type", "MGM"));
1019  CHECK(value_equal(status1, nodeid1, "status", "CONNECTED"));
1020  CHECK(value_equal(status1, nodeid1, "version", version.c_str()));
1021  CHECK(value_equal(status1, nodeid1, "mysql_version", mysql_version.c_str()));
1022  CHECK(value_equal(status1, nodeid1, "address", address.c_str()));
1023  CHECK(value_equal(status1, nodeid1, "startphase", "0"));
1024  CHECK(value_equal(status1, nodeid1, "dynamic_id", "0"));
1025  CHECK(value_equal(status1, nodeid1, "node_group", "0"));
1026  CHECK(value_equal(status1, nodeid1, "connect_count", "0"));
1027 
1028  // Check status for other mgm node
1029  // not started yet -> NO_CONTACT, no address, no versions
1030  CHECK(value_equal(status1, nodeid2, "type", "MGM"));
1031  CHECK(value_equal(status1, nodeid2, "status", "NO_CONTACT"));
1032  CHECK(value_equal(status1, nodeid2, "version", "0"));
1033  CHECK(value_equal(status1, nodeid2, "mysql_version", "0"));
1034  CHECK(value_equal(status1, nodeid2, "address", ""));
1035  CHECK(value_equal(status1, nodeid2, "startphase", "0"));
1036  CHECK(value_equal(status1, nodeid2, "dynamic_id", "0"));
1037  CHECK(value_equal(status1, nodeid2, "node_group", "0"));
1038  CHECK(value_equal(status1, nodeid2, "connect_count", "0"));
1039 
1040  // Start second mgmd
1041  CHECK(mgmd2->start_from_config_ini(wd.path()));
1042  CHECK(mgmd2->connect(config));
1043 
1044  // wait for confirmed config
1045  for (unsigned i = 0; i < mgmds.size(); i++)
1046  CHECK(mgmds[i]->wait_confirmed_config());
1047 
1048  Properties status2;
1049  CHECK(get_status(mgmd2->connectstring(config).c_str(), status2));
1050  //status2.print();
1051  // Check status for own mgm node, always CONNECTED
1052  CHECK(value_equal(status2, nodeid2, "type", "MGM"));
1053  CHECK(value_equal(status2, nodeid2, "status", "CONNECTED"));
1054  CHECK(value_equal(status2, nodeid2, "version", version.c_str()));
1055  CHECK(value_equal(status2, nodeid2, "mysql_version", mysql_version.c_str()));
1056  CHECK(value_equal(status2, nodeid2, "address", address.c_str()));
1057  CHECK(value_equal(status2, nodeid2, "startphase", "0"));
1058  CHECK(value_equal(status2, nodeid2, "dynamic_id", "0"));
1059  CHECK(value_equal(status2, nodeid2, "node_group", "0"));
1060  CHECK(value_equal(status2, nodeid2, "connect_count", "0"));
1061 
1062  // Check status for other mgm node
1063  // both started now -> CONNECTED, address and versions filled in
1064  CHECK(value_equal(status2, nodeid1, "type", "MGM"));
1065  CHECK(value_equal(status2, nodeid1, "status", "CONNECTED"));
1066  CHECK(value_equal(status2, nodeid1, "version", version.c_str()));
1067  CHECK(value_equal(status2, nodeid1, "mysql_version", mysql_version.c_str()));
1068  CHECK(value_equal(status2, nodeid1, "address", address.c_str()));
1069  CHECK(value_equal(status2, nodeid1, "startphase", "0"));
1070  CHECK(value_equal(status2, nodeid1, "dynamic_id", "0"));
1071  CHECK(value_equal(status2, nodeid1, "node_group", "0"));
1072  CHECK(value_equal(status2, nodeid1, "connect_count", "0"));
1073 
1074  Properties status3;
1075  CHECK(get_status(mgmd1->connectstring(config).c_str(), status3));
1076  //status3.print();
1077  // Check status for own mgm node, always CONNECTED
1078  CHECK(value_equal(status3, nodeid1, "type", "MGM"));
1079  CHECK(value_equal(status3, nodeid1, "status", "CONNECTED"));
1080  CHECK(value_equal(status3, nodeid1, "version", version.c_str()));
1081  CHECK(value_equal(status3, nodeid1, "mysql_version", mysql_version.c_str()));
1082  CHECK(value_equal(status3, nodeid1, "address", address.c_str()));
1083  CHECK(value_equal(status3, nodeid1, "startphase", "0"));
1084  CHECK(value_equal(status3, nodeid1, "dynamic_id", "0"));
1085  CHECK(value_equal(status3, nodeid1, "node_group", "0"));
1086  CHECK(value_equal(status3, nodeid1, "connect_count", "0"));
1087 
1088  // Check status for other mgm node
1089  // both started now -> CONNECTED, address and versions filled in
1090  CHECK(value_equal(status3, nodeid2, "type", "MGM"));
1091  CHECK(value_equal(status3, nodeid2, "status", "CONNECTED"));
1092  CHECK(value_equal(status3, nodeid2, "version", version.c_str()));
1093  CHECK(value_equal(status3, nodeid2, "mysql_version", mysql_version.c_str()));
1094  CHECK(value_equal(status3, nodeid2, "address", address.c_str()));
1095  CHECK(value_equal(status3, nodeid2, "startphase", "0"));
1096  CHECK(value_equal(status3, nodeid2, "dynamic_id", "0"));
1097  CHECK(value_equal(status3, nodeid2, "node_group", "0"));
1098  CHECK(value_equal(status3, nodeid2, "connect_count", "0"));
1099 
1100  return NDBT_OK;
1101 
1102 }
1103 
1104 int
1105 runBug61607(NDBT_Context* ctx, NDBT_Step* step)
1106 {
1107  NDBT_Workingdir wd("test_mgmd"); // temporary working directory
1108 
1109  // Create config.ini
1110  const int cnt_mgmd = 1;
1111  Properties config = ConfigFactory::create(cnt_mgmd);
1112  CHECK(ConfigFactory::write_config_ini(config,
1113  path(wd.path(),
1114  "config.ini",
1115  NULL).c_str()));
1116  // Start ndb_mgmd(s)
1117  MgmdProcessList mgmds;
1118  for (int i = 1; i <= cnt_mgmd; i++)
1119  {
1120  Mgmd* mgmd = new Mgmd(i);
1121  mgmds.push_back(mgmd);
1122  CHECK(mgmd->start_from_config_ini(wd.path()));
1123  }
1124 
1125  // Connect the ndb_mgmd(s)
1126  for (unsigned i = 0; i < mgmds.size(); i++)
1127  CHECK(mgmds[i]->connect(config));
1128 
1129  // wait for confirmed config
1130  for (unsigned i = 0; i < mgmds.size(); i++)
1131  CHECK(mgmds[i]->wait_confirmed_config());
1132 
1133  // Check binary config files created
1134  CHECK(file_exists(path(wd.path(),
1135  "ndb_1_config.bin.1",
1136  NULL).c_str()));
1137 
1138  int no_of_nodes = 0;
1139  int * node_ids = 0;
1140  int initialstart = 0;
1141  int nostart = 0;
1142  int abort = 0;
1143  int force = 0;
1144  int need_disconnect = 0;
1145  int res = ndb_mgm_restart4(mgmds[0]->handle(), no_of_nodes, node_ids,
1146  initialstart, nostart, abort, force,
1147  &need_disconnect);
1148 
1149 
1150  return res == 0 ? NDBT_OK : NDBT_FAILED;
1151 }
1152 
1153 NDBT_TESTSUITE(testMgmd);
1154 DRIVER(DummyDriver); /* turn off use of NdbApi */
1155 
1156 TESTCASE("Basic2Mgm",
1157  "Basic test with two mgmd")
1158 {
1159  INITIALIZER(runTestBasic2Mgm);
1160 }
1161 
1162 TESTCASE("Bug42015",
1163  "Test that mgmd can fetch configuration from another mgmd")
1164 {
1165  INITIALIZER(runTestBug42015);
1166 }
1167 TESTCASE("NowaitNodes",
1168  "Test that one mgmd(of 2) can start alone with usage "
1169  "of --nowait-nodes, then start the second mgmd and it should join")
1170 {
1171  INITIALIZER(runTestNowaitNodes);
1172 }
1173 TESTCASE("NowaitNodes2",
1174  "Test that one mgmd(of 2) can start alone with usage "
1175  "of --nowait-nodes, then start the second mgmd from different "
1176  "configuration and the one with lowest nodeid should shutdown")
1177 {
1178  INITIALIZER(runTestNowaitNodes2);
1179 }
1180 
1181 TESTCASE("NoCfgCache",
1182  "Test that when an mgmd is started with --skip-config-cache, "
1183  "no ndb_xx_config.xx.bin file is created, but you can "
1184  "connect to the mgm node and retrieve the config.")
1185 {
1186  INITIALIZER(runTestNoConfigCache);
1187 }
1188 
1189 TESTCASE("Bug45495",
1190  "Test that mgmd can be restarted in any order")
1191 {
1192  INITIALIZER(runTestBug45495);
1193 }
1194 
1195 TESTCASE("Bug56844",
1196  "Test that mgmd can be reloaded in parallel")
1197 {
1198  INITIALIZER(runBug56844);
1199 }
1200 TESTCASE("Bug12352191",
1201  "Test mgmd status for other mgmd")
1202 {
1203  INITIALIZER(runTestBug12352191);
1204 }
1205 TESTCASE("Bug61607", "")
1206 {
1207  INITIALIZER(runBug61607);
1208 }
1209 
1210 NDBT_TESTSUITE_END(testMgmd);
1211 
1212 int main(int argc, const char** argv)
1213 {
1214  ndb_init();
1215  NDBT_TESTSUITE_INSTANCE(testMgmd);
1216  testMgmd.setCreateTable(false);
1217  testMgmd.setRunAllTables(true);
1218  testMgmd.setConnectCluster(false);
1219  return testMgmd.execute(argc, argv);
1220 }
1221 
1222 template class Vector<Mgmd*>;
1223