MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testConfig.cpp
1 /*
2  Copyright (c) 2008, 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 <ndb_global.h>
20 #include "InitConfigFileParser.hpp"
21 #include "ConfigInfo.hpp"
22 #include "Config.hpp"
23 #include <portlib/NdbDir.hpp>
24 
25 #define CHECK(x) \
26  if (!(x)) {\
27  fprintf(stderr, "testConfig: '"#x"' failed on line %d\n", __LINE__); \
28  exit(1); \
29  }
30 
31 
32 static const ConfigInfo g_info;
33 
34 /*
35  Create a small config.ini with the given parameter and run
36  it through InitConfigFileParser
37  */
38 bool
39 check_param(const ConfigInfo::ParamInfo & param)
40 {
41  FILE* config_file= tmpfile();
42  CHECK(config_file);
43 
44  const char* section= g_info.nameToAlias(param._section);
45  if (section == NULL)
46  section= param._section;
47 
48  if (param._type == ConfigInfo::CI_SECTION)
49  {
50  fclose(config_file);
51  return true;
52  }
53 
54  if(param._default == MANDATORY)
55  {
56  // Mandatory parameter
57  fclose(config_file);
58  return true;
59  }
60  else
61  {
62  fprintf(config_file, "[%s]\n", section);
63  fprintf(config_file, "%s=%s\n", param._fname,
64  param._default ? param._default : "some value");
65  }
66 
67  // Fill in lines needed for a minimal config
68  if (strcmp(section, "NDBD") != 0)
69  fprintf(config_file, "[ndbd]\n");
70  if (strcmp(param._fname, "NoOfReplicas") != 0)
71  fprintf(config_file, "NoOfReplicas=1\n");
72 
73  if (strcmp(section, "NDB_MGMD") != 0)
74  fprintf(config_file, "[ndb_mgmd]\n");
75  if (strcmp(param._fname, "Hostname") != 0)
76  fprintf(config_file, "HostName=localhost\n");
77 
78  if (strcmp(section, "MYSQLD") != 0)
79  fprintf(config_file, "[mysqld]\n");
80 
81  rewind(config_file);
82 
83  // Run the config file through InitConfigFileParser
84  InitConfigFileParser parser;
85  Config* conf = parser.parseConfig(config_file);
86  fclose(config_file);
87 
88  if (conf == NULL)
89  return false;
90  delete conf;
91  return true;
92 }
93 
94 
95 bool
96 check_params(void)
97 {
98  bool ok= true;
99  for (int j=0; j<g_info.m_NoOfParams; j++) {
100  const ConfigInfo::ParamInfo & param= g_info.m_ParamInfo[j];
101  printf("Checking %s...\n", param._fname);
102  if (!check_param(param))
103  {
104  ok= false;
105  }
106  }
107 
108  return true; // Ignore "ok" for now, just checking it doesn't crash
109 }
110 
111 
112 
113 Config*
114 create_config(const char* first, ...)
115 {
116  va_list args;
117 
118  FILE* config_file= tmpfile();
119  CHECK(config_file);
120 
121  va_start(args, first);
122  const char* str= first;
123  do
124  fprintf(config_file, "%s\n", str);
125  while((str= va_arg(args, const char*)) != NULL);
126  va_end(args);
127 
128 #if 0
129  rewind(config_file);
130 
131  char buf[100];
132  while(fgets(buf, sizeof(buf), config_file))
133  ndbout_c(buf);
134 #endif
135 
136  rewind(config_file);
137 
138  InitConfigFileParser parser;
139  Config* conf = parser.parseConfig(config_file);
140  fclose(config_file);
141 
142  return conf;
143 }
144 
145 // Global variable for my_getopt
146 extern "C" const char* my_defaults_file;
147 
148 static
149 unsigned
150 ndb_procid()
151 {
152 #ifdef _WIN32
153  return (unsigned)GetCurrentProcessId();
154 #else
155  return (unsigned)getpid();
156 #endif
157 }
158 
159 Config*
160 create_mycnf(const char* first, ...)
161 {
162  va_list args;
163 
164  NdbDir::Temp tempdir;
165  BaseString mycnf_file;
166  mycnf_file.assfmt("%s%stest_my.%u.cnf",
167  tempdir.path(), DIR_SEPARATOR, ndb_procid());
168 
169  FILE* config_file= fopen(mycnf_file.c_str(), "w+");
170  CHECK(config_file);
171 
172  va_start(args, first);
173  const char* str= first;
174  do
175  fprintf(config_file, "%s\n", str);
176  while((str= va_arg(args, const char*)) != NULL);
177  va_end(args);
178 
179 #if 0
180  rewind(config_file);
181 
182  char buf[100];
183  while(fgets(buf, sizeof(buf), config_file))
184  printf("%s", buf);
185 #endif
186 
187  fflush(config_file);
188  rewind(config_file);
189 
190  // Trick handle_options to read from the temp file
191  const char* save_defaults_file = my_defaults_file;
192  my_defaults_file = mycnf_file.c_str();
193 
194  InitConfigFileParser parser;
195  Config* conf = parser.parse_mycnf();
196 
197  // Restore the global variable
198  my_defaults_file = save_defaults_file;
199 
200  fclose(config_file);
201 
202  // Remove file
203  unlink(mycnf_file.c_str());
204 
205  return conf;
206 }
207 
208 
209 
210 
211 void
212 diff_config(void)
213 {
214  Config* c1=
215  create_config("[ndbd]", "NoOfReplicas=1",
216  "[ndb_mgmd]", "HostName=localhost",
217  "[mysqld]", NULL);
218  CHECK(c1);
219  Config* c2=
220  create_config("[ndbd]", "NoOfReplicas=1",
221  "[ndb_mgmd]", "HostName=localhost",
222  "[mysqld]", "[mysqld]", NULL);
223  CHECK(c2);
224 
225  CHECK(c1->equal(c1));
226 
227  CHECK(!c1->equal(c2));
228  CHECK(!c2->equal(c1));
229  CHECK(!c2->illegal_change(c1));
230  CHECK(!c1->illegal_change(c2));
231 
232  ndbout_c("==================");
233  ndbout_c("c1->print_diff(c2)");
234  c1->print_diff(c2);
235  ndbout_c("==================");
236  ndbout_c("c2->print_diff(c1)");
237  c2->print_diff(c1);
238  ndbout_c("==================");
239 
240  {
241 
242 
243  // BUG#47036 Reload of config shows only diff of last changed parameter
244  // - check that diff of c1 and c3 shows 2 diffs
245  Config* c1_bug47306=
246  create_config("[ndbd]", "NoOfReplicas=1",
247  "DataMemory=100M", "IndexMemory=100M",
248  "[ndb_mgmd]", "HostName=localhost",
249  "[mysqld]", NULL);
250  CHECK(c1_bug47306);
251 
252  ndbout_c("c1->print_diff(c1_bug47306)");
253  c1->print_diff(c1_bug47306);
254 
255  Properties diff_list;
256  unsigned exclude[]= {CFG_SECTION_SYSTEM, 0};
257  c1->diff(c1_bug47306, diff_list, exclude);
258 
259  // open section for ndbd with NodeId=1
260  const Properties* section;
261  CHECK(diff_list.get("NodeId=1", &section));
262 
263  // Count the number of diffs for ndbd 1
264  const char* name;
265  int count= 0, found = 0;
266  Properties::Iterator prop_it(section);
267  while ((name = prop_it.next())){
268  if (strcmp(name, "IndexMemory") == 0)
269  found++;
270  if (strcmp(name, "DataMemory") == 0)
271  found++;
272  count++;
273  }
274  CHECK(found == 2 &&
275  count == found + 2); // Overhead == 2
276  ndbout_c("==================");
277 
278  delete c1_bug47306;
279  }
280 
281  delete c1;
282  delete c2;
283 }
284 
285 
286 void
287 print_restart_info(void)
288 {
289  Vector<const char*> initial_node;
290  Vector<const char*> system;
291  Vector<const char*> initial_system;
292 
293  for (int i = 0; i < g_info.m_NoOfParams; i++) {
294  const ConfigInfo::ParamInfo & param = g_info.m_ParamInfo[i];
295  if ((param._flags & ConfigInfo::CI_RESTART_INITIAL) &&
296  (param._flags & ConfigInfo::CI_RESTART_SYSTEM))
297  initial_system.push_back(param._fname);
298  else if (param._flags & (ConfigInfo::CI_RESTART_SYSTEM))
299  system.push_back(param._fname);
300  else if (param._flags & (ConfigInfo::CI_RESTART_INITIAL))
301  initial_node.push_back(param._fname);
302  }
303 
304  fprintf(stderr, "*** initial node restart ***\n");
305  for (size_t i = 0; i < initial_node.size(); i++) {
306  fprintf(stderr, "%s\n", initial_node[i]);
307  }
308  fprintf(stderr, "\n");
309 
310  fprintf(stderr, "*** system restart ***\n");
311  for (size_t i = 0; i < system.size(); i++) {
312  fprintf(stderr, "%s\n", system[i]);
313  }
314  fprintf(stderr, "\n");
315 
316  fprintf(stderr, "*** initial system restart ***\n");
317  for (size_t i = 0; i < initial_system.size(); i++) {
318  fprintf(stderr, "%s\n", initial_system[i]);
319  }
320  fprintf(stderr, "\n");
321 }
322 
323 
324 static void
325 checksum_config(void)
326 {
327  Config* c1=
328  create_config("[ndbd]", "NoOfReplicas=1",
329  "[ndb_mgmd]", "HostName=localhost",
330  "[mysqld]", NULL);
331  CHECK(c1);
332  Config* c2=
333  create_config("[ndbd]", "NoOfReplicas=1",
334  "[ndb_mgmd]", "HostName=localhost",
335  "[mysqld]", "[mysqld]", NULL);
336  CHECK(c2);
337 
338  ndbout_c("== checksum tests ==");
339  Uint32 c1_check = c1->checksum();
340  Uint32 c2_check = c2->checksum();
341  ndbout_c("c1->checksum(): 0x%x", c1_check);
342  ndbout_c("c2->checksum(): 0x%x", c2_check);
343  // Different config should not have same checksum
344  CHECK(c1_check != c2_check);
345 
346  // Same config should have same checksum
347  CHECK(c1_check == c1->checksum());
348 
349  // Copied config should have same checksum
350  Config c1_copy(c1);
351  CHECK(c1_check == c1_copy.checksum());
352 
353  ndbout_c("==================");
354 
355  delete c1;
356  delete c2;
357 }
358 
359 static void
360 test_param_values(void)
361 {
362  struct test {
363  const char* param;
364  bool result;
365  } tests [] = {
366  // CI_ENUM
367  { "Arbitration=Disabled", true },
368  { "Arbitration=Invalid", false },
369  { "Arbitration=", false },
370  // CI_BITMASK
371  { "LockExecuteThreadToCPU=0", true },
372  { "LockExecuteThreadToCPU=1", true },
373  { "LockExecuteThreadToCPU=65535", true },
374  { "LockExecuteThreadToCPU=0-65535", true },
375  { "LockExecuteThreadToCPU=0-1,65534-65535", true },
376  { "LockExecuteThreadToCPU=17-256", true },
377  { "LockExecuteThreadToCPU=1-2,36-37,17-256,11-12,1-2", true },
378  { "LockExecuteThreadToCPU=", false }, // Zero size value not allowed
379  { "LockExecuteThreadToCPU=1-", false },
380  { "LockExecuteThreadToCPU=1--", false },
381  { "LockExecuteThreadToCPU=1-2,34-", false },
382  { "LockExecuteThreadToCPU=x", false },
383  { "LockExecuteThreadToCPU=x-1", false },
384  { "LockExecuteThreadToCPU=x-x", false },
385  { 0, false }
386  };
387 
388  for (struct test* t = tests; t->param; t++)
389  {
390  ndbout_c("testing %s", t->param);
391  {
392  const Config* c =
393  create_config("[ndbd]", "NoOfReplicas=1",
394  t->param,
395  "[ndb_mgmd]", "HostName=localhost",
396  "[mysqld]", NULL);
397  if (t->result)
398  {
399  CHECK(c);
400  delete c;
401  }
402  else
403  {
404  CHECK(c == NULL);
405  }
406  }
407  {
408  const Config* c =
409  create_mycnf("[cluster_config]",
410  "ndb_mgmd=localhost",
411  "ndbd=localhost,localhost",
412  "ndbapi=localhost",
413  "NoOfReplicas=1",
414  t->param,
415  NULL);
416  if (t->result)
417  {
418  CHECK(c);
419  delete c;
420  }
421  else
422  {
423  CHECK(c == NULL);
424  }
425  }
426  }
427 
428 }
429 
430 static void
431 test_hostname_mycnf(void)
432 {
433  // Check the special rule for my.cnf that says
434  // the two hostname specs must match
435  {
436  // Valid config, ndbd=localhost, matches HostName=localhost
437  const Config* c =
438  create_mycnf("[cluster_config]",
439  "ndb_mgmd=localhost",
440  "ndbd=localhost,localhost",
441  "ndbapi=localhost",
442  "NoOfReplicas=1",
443  "[cluster_config.ndbd.1]",
444  "HostName=localhost",
445  NULL);
446  CHECK(c);
447  delete c;
448  }
449 
450  {
451  // Invalid config, ndbd=localhost, does not match HostName=host1
452  const Config* c =
453  create_mycnf("[cluster_config]",
454  "ndb_mgmd=localhost",
455  "ndbd=localhost,localhost",
456  "ndbapi=localhost",
457  "NoOfReplicas=1",
458  "[cluster_config.ndbd.1]",
459  "HostName=host1",
460  NULL);
461  CHECK(c == NULL);
462  }
463 }
464 
465 #include <NdbTap.hpp>
466 
467 #include <EventLogger.hpp>
468 extern EventLogger* g_eventLogger;
469 
470 TAPTEST(MgmConfig)
471 {
472  ndb_init();
473  g_eventLogger->createConsoleHandler();
474  diff_config();
475  CHECK(check_params());
476  checksum_config();
477  test_param_values();
478  test_hostname_mycnf();
479 #if 0
480  print_restart_info();
481 #endif
482  ndb_end(0);
483  return 1; // OK
484 }