MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConfigManager.cpp
1 /* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 
17 #include "ConfigManager.hpp"
18 #include "MgmtSrvr.hpp"
19 #include <NdbDir.hpp>
20 
21 #include <NdbConfig.h>
22 #include <NdbSleep.h>
23 #include <kernel/GlobalSignalNumbers.h>
24 #include <SignalSender.hpp>
25 #include <NdbApiSignal.hpp>
26 #include <signaldata/NFCompleteRep.hpp>
27 #include <signaldata/NodeFailRep.hpp>
28 #include <signaldata/ApiRegSignalData.hpp>
29 #include <ndb_version.h>
30 
31 #include <EventLogger.hpp>
32 extern EventLogger * g_eventLogger;
33 
34 extern "C" const char* opt_ndb_connectstring;
35 extern "C" int opt_ndb_nodeid;
36 
37 ConfigManager::ConfigManager(const MgmtSrvr::MgmtOpts& opts,
38  const char* configdir) :
39  MgmtThread("ConfigManager"),
40  m_opts(opts),
41  m_facade(NULL),
42  m_ss(NULL),
43  m_config_mutex(NULL),
44  m_config(NULL),
45  m_config_retriever(opt_ndb_connectstring,
46  opt_ndb_nodeid,
47  NDB_VERSION,
49  opts.bind_address),
50  m_config_state(CS_UNINITIALIZED),
51  m_previous_state(CS_UNINITIALIZED),
52  m_prepared_config(NULL),
53  m_node_id(0),
54  m_configdir(configdir)
55 {
56 }
57 
58 
59 ConfigManager::~ConfigManager()
60 {
61  delete m_config;
62  delete m_prepared_config;
63  if (m_ss)
64  delete m_ss;
65  NdbMutex_Destroy(m_config_mutex);
66 }
67 
68 
77 static bool
78 alone_on_host(Config* conf,
79  Uint32 own_type,
80  Uint32 own_nodeid)
81 {
82  ConfigIter iter(conf, CFG_SECTION_NODE);
83  for (iter.first(); iter.valid(); iter.next())
84  {
85  Uint32 type;
86  if(iter.get(CFG_TYPE_OF_SECTION, &type) ||
87  type != own_type)
88  continue;
89 
90  Uint32 nodeid;
91  if(iter.get(CFG_NODE_ID, &nodeid) ||
92  nodeid == own_nodeid)
93  continue;
94 
95  const char * hostname;
96  if(iter.get(CFG_NODE_HOST, &hostname))
97  continue;
98 
99  if (SocketServer::tryBind(0,hostname))
100  {
101  // Another MGM node was also setup on this host
102  g_eventLogger->debug("Not alone on host %s, node %d " \
103  "will also run here",
104  hostname, nodeid);
105  return false;
106  }
107  }
108  return true;
109 }
110 
111 
120 NodeId
121 ConfigManager::find_nodeid_from_configdir(void)
122 {
123  BaseString config_name;
124  NdbDir::Iterator iter;
125 
126  if (iter.open(m_configdir) != 0)
127  return 0;
128 
129  const char* name;
130  unsigned found_nodeid= 0;
131  unsigned nodeid;
132  char extra; // Avoid matching ndb_2_config.bin.2.tmp
133  unsigned version, max_version = 0;
134  while ((name = iter.next_file()) != NULL)
135  {
136  if (sscanf(name,
137  "ndb_%u_config.bin.%u%c",
138  &nodeid, &version, &extra) == 2)
139  {
140  // ndbout_c("match: %s", name);
141 
142  if (nodeid != found_nodeid)
143  {
144  if (found_nodeid != 0)
145  return 0; // Found more than one nodeid
146  found_nodeid= nodeid;
147  }
148 
149  if (version > max_version)
150  max_version = version;
151  }
152  }
153 
154  if (max_version == 0)
155  return 0;
156 
157  config_name.assfmt("%s%sndb_%u_config.bin.%u",
158  m_configdir, DIR_SEPARATOR, found_nodeid, max_version);
159 
160  Config* conf;
161  if (!(conf = load_saved_config(config_name)))
162  return 0;
163 
164  if (!m_config_retriever.verifyConfig(conf->m_configValues,
165  found_nodeid) ||
166  !alone_on_host(conf, NDB_MGM_NODE_TYPE_MGM, found_nodeid))
167  {
168  delete conf;
169  return 0;
170  }
171 
172  delete conf;
173  return found_nodeid;
174 }
175 
176 
186 static NodeId
187 find_own_nodeid(Config* conf)
188 {
189  NodeId found_nodeid= 0;
190  ConfigIter iter(conf, CFG_SECTION_NODE);
191  for (iter.first(); iter.valid(); iter.next())
192  {
193  Uint32 type;
194  if(iter.get(CFG_TYPE_OF_SECTION, &type) ||
195  type != NDB_MGM_NODE_TYPE_MGM)
196  continue;
197 
198  Uint32 nodeid;
199  require(iter.get(CFG_NODE_ID, &nodeid) == 0);
200 
201  const char * hostname;
202  if(iter.get(CFG_NODE_HOST, &hostname))
203  continue;
204 
205  if (SocketServer::tryBind(0,hostname))
206  {
207  // This node is setup to run on this host
208  if (found_nodeid == 0)
209  found_nodeid = nodeid;
210  else
211  return 0; // More than one host on this node
212  }
213  }
214  return found_nodeid;
215 }
216 
217 
218 NodeId
219 ConfigManager::find_nodeid_from_config(void)
220 {
221  if (!m_opts.mycnf &&
222  !m_opts.config_filename)
223  return 0;
224 
225  Config* conf = load_config();
226  if (conf == NULL)
227  return 0;
228 
229  NodeId found_nodeid = find_own_nodeid(conf);
230  if (found_nodeid == 0 ||
231  !m_config_retriever.verifyConfig(conf->m_configValues, found_nodeid))
232  {
233  delete conf;
234  return 0;
235  }
236 
237  return found_nodeid;
238 }
239 
240 
241 bool
242 ConfigManager::init_nodeid(void)
243 {
244  DBUG_ENTER("ConfigManager::init_nodeid");
245 
246  NodeId nodeid = m_config_retriever.get_configuration_nodeid();
247  if (nodeid)
248  {
249  // Nodeid was specifed on command line or in NDB_CONNECTSTRING
250  g_eventLogger->debug("Got nodeid: %d from command line " \
251  "or NDB_CONNECTSTRING", nodeid);
252  m_node_id = nodeid;
253  DBUG_RETURN(true);
254  }
255 
256  nodeid = find_nodeid_from_configdir();
257  if (nodeid)
258  {
259  // Found nodeid by searching in configdir
260  g_eventLogger->debug("Got nodeid: %d from searching in configdir",
261  nodeid);
262  m_node_id = nodeid;
263  DBUG_RETURN(true);
264  }
265 
266  nodeid = find_nodeid_from_config();
267  if (nodeid)
268  {
269  // Found nodeid by looking in the config given on command line
270  g_eventLogger->debug("Got nodeid: %d from config file given " \
271  "on command line",
272  nodeid);
273  m_node_id = nodeid;
274  DBUG_RETURN(true);
275  }
276 
277  // We _could_ try connecting to other running mgmd(s)
278  // and fetch our nodeid. But, that introduces a dependency
279  // that is not beneficial for a shared nothing cluster, since
280  // it might only work when other mgmd(s) are started. If all
281  // mgmd(s) is down it would require manual intervention.
282  // Better to require the node id to always be specified
283  // on the command line(or the above _local_ magic)
284 
285  g_eventLogger->error("Could not determine which nodeid to use for "\
286  "this node. Specify it with --ndb-nodeid=<nodeid> "\
287  "on command line");
288  DBUG_RETURN(false);
289 }
290 
291 
292 static void
293 reset_dynamic_ports_in_config(const Config* config)
294 {
295  ConfigIter iter(config, CFG_SECTION_CONNECTION);
296 
297  for(;iter.valid();iter.next()) {
298  Uint32 port;
299  require(iter.get(CFG_CONNECTION_SERVER_PORT, &port) == 0);
300 
301  if ((int)port < 0)
302  {
303  port = 0;
304  ConfigValues::Iterator i2(config->m_configValues->m_config,
305  iter.m_config);
306  require(i2.set(CFG_CONNECTION_SERVER_PORT, port));
307  }
308  }
309 }
310 
311 
312 bool
314 {
315  DBUG_ENTER("ConfigManager::init");
316 
317  m_config_mutex = NdbMutex_Create();
318  if (!m_config_mutex)
319  {
320  g_eventLogger->error("Failed to create mutex in ConfigManager!");
321  DBUG_RETURN(false);
322  }
323 
324  require(m_config_state == CS_UNINITIALIZED);
325 
326  if (m_config_retriever.hasError())
327  {
328  g_eventLogger->error("%s", m_config_retriever.getErrorString());
329  DBUG_RETURN(false);
330  }
331 
332  if (!init_nodeid())
333  DBUG_RETURN(false);
334 
335  if (m_opts.initial && !delete_saved_configs())
336  DBUG_RETURN(false);
337 
338  if (failed_config_change_exists())
339  DBUG_RETURN(false);
340 
341  BaseString config_bin_name;
342  if (saved_config_exists(config_bin_name))
343  {
344  Config* conf = NULL;
345  if (!(conf = load_saved_config(config_bin_name)))
346  DBUG_RETURN(false);
347 
348  if (!config_ok(conf))
349  DBUG_RETURN(false);
350 
351  set_config(conf);
352  m_config_state = CS_CONFIRMED;
353 
354  g_eventLogger->info("Loaded config from '%s'", config_bin_name.c_str());
355 
356  if (m_opts.reload && // --reload
357  (m_opts.mycnf || m_opts.config_filename))
358  {
359  Config* new_conf = load_config();
360  if (new_conf == NULL)
361  DBUG_RETURN(false);
362 
366  m_config_change.config_loaded(new_conf);
367  g_eventLogger->info("Loaded configuration from '%s', will try " \
368  "to set it once started",
369  m_opts.mycnf ? "my.cnf" : m_opts.config_filename);
370  }
371  }
372  else
373  {
374  if (m_opts.mycnf || m_opts.config_filename)
375  {
376  Config* conf = load_config();
377  if (conf == NULL)
378  DBUG_RETURN(false);
379 
380  if (!config_ok(conf))
381  DBUG_RETURN(false);
382 
383  /*
384  Set this node as primary node for config.ini/my.cnf
385  in order to make it possible that make sure an old
386  config.ini is only loaded with --force
387  */
388  if (!conf->setPrimaryMgmNode(m_node_id))
389  {
390  g_eventLogger->error("Failed to set primary MGM node");
391  DBUG_RETURN(false);
392  }
393 
394  /* Use the initial config for now */
395  set_config(conf);
396 
397  g_eventLogger->info("Got initial configuration from '%s', will try " \
398  "to set it when all ndb_mgmd(s) started",
399  m_opts.mycnf ? "my.cnf" : m_opts.config_filename);
400  m_config_change.m_initial_config = new Config(conf); // Copy config
401  m_config_state = CS_INITIAL;
402 
403  if (!init_checkers(m_config_change.m_initial_config))
404  DBUG_RETURN(false);
405  }
406  else
407  {
408  Config* conf = NULL;
409  if (!(conf = fetch_config()))
410  {
411  g_eventLogger->error("Could not fetch config!");
412  DBUG_RETURN(false);
413  }
414 
415  /*
416  The fetched config may contain dynamic ports for
417  ndbd(s) which have to be reset to 0 before using
418  the config
419  */
420  reset_dynamic_ports_in_config(conf);
421 
422  if (!config_ok(conf))
423  DBUG_RETURN(false);
424 
425  /* Use the fetched config for now */
426  set_config(conf);
427 
428  if (m_config->getGeneration() == 0)
429  {
430  g_eventLogger->info("Fetched initial configuration, " \
431  "generation: %d, name: '%s'. "\
432  "Will try to set it when all ndb_mgmd(s) started",
433  m_config->getGeneration(), m_config->getName());
434  m_config_state= CS_INITIAL;
435  m_config_change.m_initial_config = new Config(conf); // Copy config
436 
437  if (!init_checkers(m_config_change.m_initial_config))
438  DBUG_RETURN(false);
439  }
440  else
441  {
442  g_eventLogger->info("Fetched confirmed configuration, " \
443  "generation: %d, name: '%s'. " \
444  "Trying to write it to disk...",
445  m_config->getGeneration(), m_config->getName());
446  if (!prepareConfigChange(m_config))
447  {
448  abortConfigChange();
449  g_eventLogger->error("Failed to write the fetched config to disk");
450  DBUG_RETURN(false);
451  }
452  commitConfigChange();
453  m_config_state = CS_CONFIRMED;
454  g_eventLogger->info("The fetched configuration has been saved!");
455  }
456  }
457  }
458 
459  require(m_config_state != CS_UNINITIALIZED);
460  DBUG_RETURN(true);
461 }
462 
463 
464 bool
465 ConfigManager::prepareConfigChange(const Config* config)
466 {
467  if (m_prepared_config)
468  {
469  g_eventLogger->error("Can't prepare configuration change " \
470  "when already prepared");
471  return false;
472  }
473 
474  Uint32 generation= config->getGeneration();
475  if (generation == 0)
476  {
477  g_eventLogger->error("Can't prepare configuration change for "\
478  "configuration with generation 0");
479  return false;
480  }
481 
482  assert(m_node_id);
483  m_config_name.assfmt("%s%sndb_%u_config.bin.%u",
484  m_configdir, DIR_SEPARATOR, m_node_id, generation);
485  g_eventLogger->debug("Preparing configuration, generation: %d name: %s",
486  generation, m_config_name.c_str());
487 
488  /* Check file name is free */
489  if (access(m_config_name.c_str(), F_OK) == 0)
490  {
491  g_eventLogger->error("The file '%s' already exist while preparing",
492  m_config_name.c_str());
493  return false;
494  }
495 
496  /* Pack the config */
497  UtilBuffer buf;
498  if(!config->pack(buf))
499  {
500  /* Failed to pack config */
501  g_eventLogger->error("Failed to pack configuration while preparing");
502  return false;
503  }
504 
505  /* Write config to temporary file */
506  BaseString prep_config_name(m_config_name);
507  prep_config_name.append(".tmp");
508  FILE * f = fopen(prep_config_name.c_str(), IF_WIN("wbc", "w"));
509  if(f == NULL)
510  {
511  g_eventLogger->error("Failed to open file '%s' while preparing, errno: %d",
512  prep_config_name.c_str(), errno);
513  return false;
514  }
515 
516  if(fwrite(buf.get_data(), 1, buf.length(), f) != (size_t)buf.length())
517  {
518  g_eventLogger->error("Failed to write file '%s' while preparing, errno: %d",
519  prep_config_name.c_str(), errno);
520  fclose(f);
521  unlink(prep_config_name.c_str());
522  return false;
523  }
524 
525  if (fflush(f))
526  {
527  g_eventLogger->error("Failed to flush file '%s' while preparing, errno: %d",
528  prep_config_name.c_str(), errno);
529  fclose(f);
530  unlink(prep_config_name.c_str());
531  return false;
532  }
533 
534 #ifdef __WIN__
535  /*
536  File is opened with the commit flag "c" so
537  that the contents of the file buffer are written
538  directly to disk when fflush is called
539  */
540 #else
541  if (fsync(fileno(f)))
542  {
543  g_eventLogger->error("Failed to sync file '%s' while preparing, errno: %d",
544  prep_config_name.c_str(), errno);
545  fclose(f);
546  unlink(prep_config_name.c_str());
547  return false;
548  }
549 #endif
550  fclose(f);
551 
552  m_prepared_config = new Config(config); // Copy
553  g_eventLogger->debug("Configuration prepared");
554 
555  return true;
556 }
557 
558 
559 void
560 ConfigManager::commitConfigChange(void)
561 {
562  require(m_prepared_config != 0);
563 
564  /* Set new config locally and in all subscribers */
565  set_config(m_prepared_config);
566  m_prepared_config= NULL;
567 
568  /* Rename file to real name */
569  require(m_config_name.length());
570  BaseString prep_config_name(m_config_name);
571  prep_config_name.append(".tmp");
572  if(rename(prep_config_name.c_str(), m_config_name.c_str()))
573  {
574  g_eventLogger->error("rename from '%s' to '%s' failed while committing, " \
575  "errno: %d",
576  prep_config_name.c_str(), m_config_name.c_str(),
577  errno);
578  // Crash and leave the prepared config file in place
579  abort();
580  }
581  m_config_name.clear();
582 
583  g_eventLogger->info("Configuration %d commited", m_config->getGeneration());
584 }
585 
586 
587 static void
588 check_no_dynamic_ports_in_config(const Config* config)
589 {
590  bool ok = true;
591  ConfigIter iter(config, CFG_SECTION_CONNECTION);
592 
593  for(;iter.valid();iter.next()) {
594  Uint32 n1, n2;
595  require(iter.get(CFG_CONNECTION_NODE_1, &n1) == 0 &&
596  iter.get(CFG_CONNECTION_NODE_2, &n2) == 0);
597 
598  Uint32 port_value;
599  require(iter.get(CFG_CONNECTION_SERVER_PORT, &port_value) == 0);
600 
601  int port = (int)port_value;
602  if (port < 0)
603  {
604  g_eventLogger->error("INTERNAL ERROR: Found dynamic ports with "
605  "value in config, n1: %d, n2: %d, port: %u",
606  n1, n2, port);
607  ok = false;
608  }
609  }
610  require(ok);
611 }
612 
613 
614 void
615 ConfigManager::set_config(Config* new_config)
616 {
617  // Check that config does not contain any dynamic ports
618  check_no_dynamic_ports_in_config(new_config);
619 
620  delete m_config;
621  m_config = new_config;
622 
623  // Removed cache of packed config
624  m_packed_config.clear();
625 
626  for (unsigned i = 0; i < m_subscribers.size(); i++)
627  m_subscribers[i]->config_changed(m_node_id, new_config);
628 }
629 
630 
631 int
632 ConfigManager::add_config_change_subscriber(ConfigSubscriber* subscriber)
633 {
634  return m_subscribers.push_back(subscriber);
635 }
636 
637 
638 bool
639 ConfigManager::config_ok(const Config* conf)
640 {
641  assert(m_node_id);
642  if (!m_config_retriever.verifyConfig(conf->m_configValues, m_node_id))
643  {
644  g_eventLogger->error("%s", m_config_retriever.getErrorString());
645  return false;
646  }
647 
648  // Check DataDir exist
649  ConfigIter iter(conf, CFG_SECTION_NODE);
650  require(iter.find(CFG_NODE_ID, m_node_id) == 0);
651 
652  const char *datadir;
653  require(iter.get(CFG_NODE_DATADIR, &datadir) == 0);
654 
655  if (strcmp(datadir, "") != 0 && // datadir != ""
656  access(datadir, F_OK)) // dir exists
657  {
658  g_eventLogger->error("Directory '%s' specified with DataDir " \
659  "in configuration does not exist.", \
660  datadir);
661  return false;
662  }
663  return true;
664 }
665 
666 
667 void
668 ConfigManager::abortConfigChange(void)
669 {
670  /* Should always succeed */
671 
672  /* Remove the prepared file */
673  BaseString prep_config_name(m_config_name);
674  prep_config_name.append(".tmp");
675  unlink(prep_config_name.c_str());
676  m_config_name.clear();
677 
678  delete m_prepared_config;
679  m_prepared_config= NULL;
680 }
681 
682 
683 
684 void
685 ConfigManager::sendConfigChangeImplRef(SignalSender& ss, NodeId nodeId,
686  ConfigChangeRef::ErrorCode error) const
687 {
688  SimpleSignal ssig;
689  ConfigChangeImplRef* const ref =
690  CAST_PTR(ConfigChangeImplRef, ssig.getDataPtrSend());
691  ref->errorCode = error;
692 
693  g_eventLogger->debug("Send CONFIG_CHANGE_IMPL_REF to node: %d, error: %d",
694  nodeId, error);
695 
696  ss.sendSignal(nodeId, ssig,
697  MGM_CONFIG_MAN, GSN_CONFIG_CHANGE_IMPL_REF,
698  ConfigChangeImplRef::SignalLength);
699 }
700 
701 
702 
703 void
704 ConfigManager::execCONFIG_CHANGE_IMPL_REQ(SignalSender& ss, SimpleSignal* sig)
705 {
706  NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
707  const ConfigChangeImplReq * const req =
708  CAST_CONSTPTR(ConfigChangeImplReq, sig->getDataPtr());
709 
710  g_eventLogger->debug("Got CONFIG_CHANGE_IMPL_REQ from node: %d, "\
711  "requestType: %d",
712  nodeId, req->requestType);
713 
714  if (!m_defragger.defragment(sig))
715  return; // More fragments to come
716 
717  Guard g(m_config_mutex);
718 
719  switch(req->requestType){
720  case ConfigChangeImplReq::Prepare:{
721  if (sig->header.m_noOfSections != 1)
722  {
723  sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::NoConfigData);
724  return;
725  }
726 
728  if (!cf.unpack(sig->ptr[0].p, req->length))
729  {
730  sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::FailedToUnpack);
731  return;
732  }
733 
734  Config new_config(cf.getConfigValues());
735  Uint32 new_generation = new_config.getGeneration();
736  Uint32 curr_generation = m_config->getGeneration();
737  const char* new_name = new_config.getName();
738  const char* curr_name = m_config->getName();
739 
740  if (m_config->illegal_change(&new_config))
741  {
742  sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::IllegalConfigChange);
743  return;
744  }
745 
746  if (req->initial)
747  {
748  // Check own state
749  if (m_config_state != CS_INITIAL)
750  {
751  g_eventLogger->warning("Refusing to start initial " \
752  "configuration change since this node " \
753  "is not in INITIAL state");
754  sendConfigChangeImplRef(ss, nodeId,
755  ConfigChangeRef::IllegalInitialState);
756  return;
757  }
758 
759  // Check generation
760  if (new_generation != 0)
761  {
762  g_eventLogger->warning("Refusing to start initial " \
763  "configuration change since new " \
764  "generation is not 0 (new_generation: %d)",
765  new_generation);
766  sendConfigChangeImplRef(ss, nodeId,
767  ConfigChangeRef::IllegalInitialGeneration);
768  return;
769  }
770  new_generation = 1;
771 
772  // Check config is equal to our initial config
773  // but skip check if message is from self...
774  if (nodeId != refToNode(ss.getOwnRef()))
775  {
776  Config new_config_copy(&new_config);
777  require(new_config_copy.setName(new_name));
778  unsigned exclude[]= {CFG_SECTION_SYSTEM, 0};
779  if (!new_config_copy.equal(m_config_change.m_initial_config, exclude))
780  {
781  BaseString buf;
782  g_eventLogger->warning
783  ("Refusing to start initial config " \
784  "change when nodes have different " \
785  "config\n" \
786  "This is the actual diff:\n%s",
787  new_config_copy.diff2str(m_config_change.m_initial_config, buf));
788  sendConfigChangeImplRef(ss, nodeId,
789  ConfigChangeRef::DifferentInitial);
790  return;
791  }
792 
793  /*
794  Scrap the new_config, it's been used to check that other node
795  started from equal initial config, now it's not needed anymore
796  */
797  delete m_config_change.m_initial_config;
798  m_config_change.m_initial_config = NULL;
799  }
800  }
801  else
802  {
803 
804  // Check that new config has same primary mgm node as current
805  Uint32 curr_primary = m_config->getPrimaryMgmNode();
806  Uint32 new_primary = new_config.getPrimaryMgmNode();
807  if (new_primary != curr_primary)
808  {
809  g_eventLogger->warning("Refusing to start configuration change " \
810  "requested by node %d, the new config uses " \
811  "different primary mgm node %d. " \
812  "Current primary mmgm node is %d.",
813  nodeId, new_primary, curr_primary);
814  sendConfigChangeImplRef(ss, nodeId,
815  ConfigChangeRef::NotPrimaryMgmNode);
816  return;
817  }
818 
819  if (new_generation == 0 ||
820  new_generation != curr_generation)
821  {
822  BaseString buf;
823  g_eventLogger->warning("Refusing to start config change " \
824  "requested by node with different " \
825  "generation: %d. Our generation: %d\n" \
826  "This is the actual diff:\n%s",
827  new_generation, curr_generation,
828  new_config.diff2str(m_config, buf));
829  sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::InvalidGeneration);
830  return;
831  }
832  new_generation++;
833 
834  // Check same cluster name
835  if (strcmp(new_name, curr_name))
836  {
837  BaseString buf;
838  g_eventLogger->warning("Refusing to start config change " \
839  "requested by node with different " \
840  "name: '%s'. Our name: '%s'\n" \
841  "This is the actual diff:\n%s",
842  new_name, curr_name,
843  new_config.diff2str(m_config, buf));
844  sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::InvalidConfigName);
845  return;
846  }
847  }
848 
849  // Set new generation
850  if(!new_config.setGeneration(new_generation))
851  {
852  g_eventLogger->error("Failed to set new generation to %d",
853  new_generation);
854  sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::InternalError);
855  return;
856  }
857 
858  if (!prepareConfigChange(&new_config))
859  {
860  sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::PrepareFailed);
861  return;
862  }
863  break;
864  }
865 
866  case ConfigChangeImplReq::Commit:
867  commitConfigChange();
868 
869  // All nodes has agreed on config -> CONFIRMED
870  m_config_state = CS_CONFIRMED;
871 
872  break;
873 
874  case ConfigChangeImplReq::Abort:
875  abortConfigChange();
876  break;
877 
878  default:
879  g_eventLogger->error("execCONFIG_CHANGE_IMPL_REQ: unhandled state");
880  abort();
881  break;
882  }
883 
884  /* Send CONF */
885  SimpleSignal ssig;
886  ConfigChangeImplConf* const conf =
887  CAST_PTR(ConfigChangeImplConf, ssig.getDataPtrSend());
888  conf->requestType = req->requestType;
889 
890  g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_CONF to node: %d",
891  nodeId);
892 
893  ss.sendSignal(nodeId, ssig,
894  MGM_CONFIG_MAN,
895  GSN_CONFIG_CHANGE_IMPL_CONF,
896  ConfigChangeImplConf::SignalLength);
897 }
898 
899 
900 void ConfigManager::set_config_change_state(ConfigChangeState::States state)
901 {
902  if (state == ConfigChangeState::IDLE)
903  {
904  // Rebuild m_all_mgm so that each node in config is included
905  // new mgm nodes might have been added
906  assert(m_config_change.m_error == ConfigChangeRef::OK);
907  m_config->get_nodemask(m_all_mgm, NDB_MGM_NODE_TYPE_MGM);
908  }
909 
910  m_config_change.m_state.m_current_state = state;
911 }
912 
913 
914 void
915 ConfigManager::execCONFIG_CHANGE_IMPL_REF(SignalSender& ss, SimpleSignal* sig)
916 {
917  NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
918  g_eventLogger->debug("Got CONFIG_CHANGE_IMPL_REF from node: %d", nodeId);
919 
920  const ConfigChangeImplRef * const ref =
921  CAST_CONSTPTR(ConfigChangeImplRef, sig->getDataPtr());
922  g_eventLogger->warning("Node %d refused configuration change, error: %d",
923  nodeId, ref->errorCode);
924 
925  /* Remember the original error code */
926  if (m_config_change.m_error == 0)
927  m_config_change.m_error = (ConfigChangeRef::ErrorCode)ref->errorCode;
928 
929  switch(m_config_change.m_state){
930  case ConfigChangeState::ABORT:
931  case ConfigChangeState::PREPARING:{
932  /* Got ref while preparing (or already decided to abort) */
933  m_config_change.m_contacted_nodes.clear(nodeId);
934  set_config_change_state(ConfigChangeState::ABORT);
935 
936  m_waiting_for.clear(nodeId);
937  if (!m_waiting_for.isclear())
938  return;
939 
940  startAbortConfigChange(ss);
941  break;
942  }
943  case ConfigChangeState::COMITTING:
944  /* Got ref while comitting, impossible */
945  abort();
946  break;
947 
948  case ConfigChangeState::ABORTING:
949  /* Got ref while aborting, impossible */
950  abort();
951  break;
952 
953  default:
954  g_eventLogger->error("execCONFIG_CHANGE_IMPL_REF: unhandled state");
955  abort();
956  break;
957  }
958 }
959 
960 
961 void
962 ConfigManager::execCONFIG_CHANGE_IMPL_CONF(SignalSender& ss, SimpleSignal* sig)
963 {
964  NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
965  const ConfigChangeImplConf * const conf =
966  CAST_CONSTPTR(ConfigChangeImplConf, sig->getDataPtr());
967  g_eventLogger->debug("Got CONFIG_CHANGE_IMPL_CONF from node %d", nodeId);
968 
969  switch(m_config_change.m_state){
970  case ConfigChangeState::PREPARING:{
971  require(conf->requestType == ConfigChangeImplReq::Prepare);
972  m_waiting_for.clear(nodeId);
973  if (!m_waiting_for.isclear())
974  return;
975 
976  // send to next
977  int res = sendConfigChangeImplReq(ss, m_config_change.m_new_config);
978  if (res > 0)
979  {
980  // sent to new node...
981  return;
982  }
983  else if (res < 0)
984  {
985  // send failed, start abort
986  startAbortConfigChange(ss);
987  return;
988  }
989 
994  delete m_config_change.m_new_config;
995  m_config_change.m_new_config = 0;
996 
997  /* Send commit to all nodes */
998  SimpleSignal ssig;
999  ConfigChangeImplReq* const req =
1000  CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
1001 
1002  req->requestType = ConfigChangeImplReq::Commit;
1003 
1004  g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_REQ(commit)");
1005  require(m_waiting_for.isclear());
1006  m_waiting_for = ss.broadcastSignal(m_config_change.m_contacted_nodes, ssig,
1007  MGM_CONFIG_MAN,
1008  GSN_CONFIG_CHANGE_IMPL_REQ,
1009  ConfigChangeImplReq::SignalLength);
1010  if (m_waiting_for.isclear())
1011  set_config_change_state(ConfigChangeState::IDLE);
1012  else
1013  set_config_change_state(ConfigChangeState::COMITTING);
1014  break;
1015  }
1016 
1017  case ConfigChangeState::COMITTING:{
1018  require(conf->requestType == ConfigChangeImplReq::Commit);
1019 
1020  m_waiting_for.clear(nodeId);
1021  if (!m_waiting_for.isclear())
1022  return;
1023 
1024  require(m_config_change.m_client_ref != RNIL);
1025  require(m_config_change.m_error == 0);
1026  if (m_config_change.m_client_ref == ss.getOwnRef())
1027  {
1028  g_eventLogger->info("Config change completed! New generation: %d",
1029  m_config->getGeneration());
1030  }
1031  else
1032  {
1033  /* Send CONF to requestor */
1034  sendConfigChangeConf(ss, m_config_change.m_client_ref);
1035  }
1036  m_config_change.m_client_ref = RNIL;
1037  set_config_change_state(ConfigChangeState::IDLE);
1038  break;
1039  }
1040 
1041  case ConfigChangeState::ABORT:{
1042  m_waiting_for.clear(nodeId);
1043  if (!m_waiting_for.isclear())
1044  return;
1045 
1046  startAbortConfigChange(ss);
1047  break;
1048  }
1049 
1050  case ConfigChangeState::ABORTING:{
1051  m_waiting_for.clear(nodeId);
1052  if (!m_waiting_for.isclear())
1053  return;
1054 
1055  require(m_config_change.m_client_ref != RNIL);
1056  require(m_config_change.m_error);
1057  if (m_config_change.m_client_ref == ss.getOwnRef())
1058  {
1059  g_eventLogger->
1060  error("Configuration change failed! error: %d '%s'",
1061  m_config_change.m_error,
1062  ConfigChangeRef::errorMessage(m_config_change.m_error));
1063  exit(1);
1064  }
1065  else
1066  {
1067  /* Send ref to the requestor */
1068  sendConfigChangeRef(ss, m_config_change.m_client_ref,
1069  m_config_change.m_error);
1070  }
1071  m_config_change.m_error= ConfigChangeRef::OK;
1072  m_config_change.m_client_ref = RNIL;
1073  set_config_change_state(ConfigChangeState::IDLE);
1074  break;
1075  }
1076 
1077  default:
1078  g_eventLogger->error("execCONFIG_CHANGE_IMPL_CONF: unhandled state");
1079  abort();
1080  break;
1081  }
1082 }
1083 
1084 
1085 void
1086 ConfigManager::sendConfigChangeRef(SignalSender& ss, BlockReference to,
1087  ConfigChangeRef::ErrorCode error) const
1088 {
1089  NodeId nodeId = refToNode(to);
1090  SimpleSignal ssig;
1091  ConfigChangeRef* const ref =
1092  CAST_PTR(ConfigChangeRef, ssig.getDataPtrSend());
1093  ref->errorCode = error;
1094 
1095  g_eventLogger->debug("Send CONFIG_CHANGE_REF to node: %d, error: %d",
1096  nodeId, error);
1097 
1098  ss.sendSignal(nodeId, ssig, refToBlock(to),
1099  GSN_CONFIG_CHANGE_REF, ConfigChangeRef::SignalLength);
1100 }
1101 
1102 
1103 void
1104 ConfigManager::sendConfigChangeConf(SignalSender& ss, BlockReference to) const
1105 {
1106  NodeId nodeId = refToNode(to);
1107  SimpleSignal ssig;
1108 
1109  g_eventLogger->debug("Send CONFIG_CHANGE_CONF to node: %d", nodeId);
1110 
1111  ss.sendSignal(nodeId, ssig, refToBlock(to),
1112  GSN_CONFIG_CHANGE_CONF, ConfigChangeConf::SignalLength);
1113 }
1114 
1115 
1116 void
1117 ConfigManager::startConfigChange(SignalSender& ss, Uint32 ref)
1118 {
1119  if (m_config_state == CS_INITIAL)
1120  {
1121  g_eventLogger->info("Starting initial configuration change");
1122  }
1123  else
1124  {
1125  require(m_config_state == CS_CONFIRMED);
1126  g_eventLogger->info("Starting configuration change, generation: %d",
1127  m_config_change.m_new_config->getGeneration());
1128  }
1129  m_config_change.m_contacted_nodes.clear();
1130  m_config_change.m_client_ref = ref;
1131  if (sendConfigChangeImplReq(ss, m_config_change.m_new_config) <= 0)
1132  {
1133  g_eventLogger->error("Failed to start configuration change!");
1134  exit(1);
1135  }
1136 }
1137 
1138 void
1139 ConfigManager::startAbortConfigChange(SignalSender& ss)
1140 {
1141  /* Abort all other nodes */
1142  SimpleSignal ssig;
1143  ConfigChangeImplReq* const req =
1144  CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
1145  req->requestType = ConfigChangeImplReq::Abort;
1146 
1147  g_eventLogger->debug
1148  ("Sending CONFIG_CHANGE_IMPL_REQ(abort) to %s",
1149  BaseString::getPrettyText(m_config_change.m_contacted_nodes).c_str());
1150 
1151  require(m_waiting_for.isclear());
1152  m_waiting_for = ss.broadcastSignal(m_config_change.m_contacted_nodes, ssig,
1153  MGM_CONFIG_MAN,
1154  GSN_CONFIG_CHANGE_IMPL_REQ,
1155  ConfigChangeImplReq::SignalLength);
1156 
1157  if (m_config_change.m_new_config)
1158  {
1159  delete m_config_change.m_new_config;
1160  m_config_change.m_new_config = 0;
1161  }
1162 
1163  if (m_waiting_for.isclear())
1164  {
1168  m_waiting_for.set(ss.getOwnNodeId());
1169  ConfigChangeImplConf* const conf =
1170  CAST_PTR(ConfigChangeImplConf, ssig.getDataPtrSend());
1171  conf->requestType = ConfigChangeImplReq::Abort;
1172 
1173  ss.sendSignal(ss.getOwnNodeId(), ssig,
1174  MGM_CONFIG_MAN,
1175  GSN_CONFIG_CHANGE_IMPL_CONF,
1176  ConfigChangeImplConf::SignalLength);
1177  }
1178 
1179  set_config_change_state(ConfigChangeState::ABORTING);
1180 }
1181 
1182 int
1183 ConfigManager::sendConfigChangeImplReq(SignalSender& ss, const Config* conf)
1184 {
1185  require(m_waiting_for.isclear());
1186  require(m_config_change.m_client_ref != RNIL);
1187 
1188  if (m_config_change.m_contacted_nodes.isclear())
1189  {
1190  require(m_config_change.m_state == ConfigChangeState::IDLE);
1191  }
1192  else
1193  {
1194  require(m_config_change.m_state == ConfigChangeState::PREPARING);
1195  }
1196 
1197  set_config_change_state(ConfigChangeState::PREPARING);
1198 
1199  NodeBitmask nodes = m_all_mgm;
1200  nodes.bitANDC(m_config_change.m_contacted_nodes);
1201  if (nodes.isclear())
1202  {
1203  return 0; // all done
1204  }
1205 
1210  SimpleSignal ssig;
1211 
1212  UtilBuffer buf;
1213  conf->pack(buf);
1214  ssig.ptr[0].p = (Uint32*)buf.get_data();
1215  ssig.ptr[0].sz = (buf.length() + 3) / 4;
1216  ssig.header.m_noOfSections = 1;
1217 
1218  ConfigChangeImplReq* const req =
1219  CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
1220  req->requestType = ConfigChangeImplReq::Prepare;
1221  req->initial = (m_config_state == CS_INITIAL);
1222  req->length = buf.length();
1223 
1224  Uint32 i = nodes.find(0);
1225  g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_REQ(prepare) to %u", i);
1226  int result = ss.sendFragmentedSignal(i, ssig, MGM_CONFIG_MAN,
1227  GSN_CONFIG_CHANGE_IMPL_REQ,
1228  ConfigChangeImplReq::SignalLength);
1229  if (result != 0)
1230  {
1231  g_eventLogger->warning("Failed to send configuration change "
1232  "prepare to node: %d, result: %d",
1233  i, result);
1234  return -1;
1235  }
1236 
1237  m_waiting_for.set(i);
1238  m_config_change.m_contacted_nodes.set(i);
1239 
1240  return 1;
1241 }
1242 
1243 void
1244 ConfigManager::execCONFIG_CHANGE_REQ(SignalSender& ss, SimpleSignal* sig)
1245 {
1246  BlockReference from = sig->header.theSendersBlockRef;
1247  const ConfigChangeReq * const req =
1248  CAST_CONSTPTR(ConfigChangeReq, sig->getDataPtr());
1249 
1250  if (!m_defragger.defragment(sig))
1251  return; // More fragments to come
1252 
1253  if (!m_started.equal(m_all_mgm)) // Not all started
1254  {
1255  sendConfigChangeRef(ss, from, ConfigChangeRef::NotAllStarted);
1256  return;
1257  }
1258 
1259  if (m_all_mgm.find(0) != m_facade->ownId()) // Not the master
1260  {
1261  sendConfigChangeRef(ss, from, ConfigChangeRef::NotMaster);
1262  return;
1263  }
1264 
1265  if (m_config_change.m_state != ConfigChangeState::IDLE)
1266  {
1267  sendConfigChangeRef(ss, from, ConfigChangeRef::ConfigChangeOnGoing);
1268  return;
1269  }
1270  require(m_config_change.m_error == ConfigChangeRef::OK);
1271 
1272  if (sig->header.m_noOfSections != 1)
1273  {
1274  sendConfigChangeRef(ss, from, ConfigChangeRef::NoConfigData);
1275  return;
1276  }
1277 
1279  if (!cf.unpack(sig->ptr[0].p, req->length))
1280  {
1281  sendConfigChangeRef(ss, from, ConfigChangeRef::FailedToUnpack);
1282  return;
1283  }
1284 
1285  Config * new_config = new Config(cf.getConfigValues());
1286  if (!config_ok(new_config))
1287  {
1288  g_eventLogger->warning("Refusing to start config change, the config "\
1289  "is not ok");
1290  sendConfigChangeRef(ss, from, ConfigChangeRef::ConfigNotOk);
1291  delete new_config;
1292  return;
1293  }
1294 
1295  m_config_change.m_new_config = new_config;
1296  startConfigChange(ss, from);
1297 
1298  return;
1299 }
1300 
1301 
1302 static Uint32
1303 config_check_checksum(const Config* config)
1304 {
1305  Config copy(config);
1306 
1307  // Make constants of a few values in SYSTEM section that are
1308  // not part of the checksum used for "config check"
1309  copy.setName("CHECKSUM");
1310  copy.setPrimaryMgmNode(0);
1311 
1312  Uint32 checksum = copy.checksum();
1313 
1314  return checksum;
1315 }
1316 
1317 
1318 void
1319 ConfigManager::execCONFIG_CHECK_REQ(SignalSender& ss, SimpleSignal* sig)
1320 {
1321  Guard g(m_config_mutex);
1322  BlockReference from = sig->header.theSendersBlockRef;
1323  NodeId nodeId = refToNode(from);
1324  const ConfigCheckReq * const req =
1325  CAST_CONSTPTR(ConfigCheckReq, sig->getDataPtr());
1326 
1327  Uint32 other_generation = req->generation;
1328  ConfigState other_state = (ConfigState)req->state;
1329 
1330  Uint32 generation = m_config->getGeneration();
1331 
1332  // checksum
1333  Uint32 checksum = config_check_checksum(m_config);
1334  Uint32 other_checksum = req->checksum;
1335  if (sig->header.theLength == ConfigCheckReq::SignalLengthBeforeChecksum)
1336  {
1337  // Other side uses old version without checksum, use our checksum to
1338  // bypass the checks
1339  g_eventLogger->debug("Other mgmd does not have checksum, using own");
1340  other_checksum = checksum;
1341  }
1342 
1343  if (m_prepared_config || m_config_change.m_new_config)
1344  {
1345  g_eventLogger->debug("Got CONFIG_CHECK_REQ from node: %d while "
1346  "config change in progress (m_prepared_config). "
1347  "Returning incorrect state, causing it to be retried",
1348  nodeId);
1349  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongState,
1350  generation, other_generation,
1351  m_config_state, CS_UNINITIALIZED);
1352  return;
1353  }
1354 
1355  if (m_config_change.m_loaded_config && ss.getOwnNodeId() < nodeId)
1356  {
1357  g_eventLogger->debug("Got CONFIG_CHECK_REQ from node: %d while "
1358  "having a loaded config (and my node is lower: %d). "
1359  "Returning incorrect state, causing it to be retried",
1360  nodeId,
1361  ss.getOwnNodeId());
1362  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongState,
1363  generation, other_generation,
1364  m_config_state, CS_UNINITIALIZED);
1365  return;
1366  }
1367 
1368  g_eventLogger->debug("Got CONFIG_CHECK_REQ from node: %d. "
1369  "Our generation: %d, other generation: %d, "
1370  "our state: %d, other state: %d, "
1371  "our checksum: 0x%.8x, other checksum: 0x%.8x",
1372  nodeId, generation, other_generation,
1373  m_config_state, other_state,
1374  checksum, other_checksum);
1375 
1376  switch (m_config_state)
1377  {
1378  default:
1379  case CS_UNINITIALIZED:
1380  g_eventLogger->error("execCONFIG_CHECK_REQ: unhandled state");
1381  abort();
1382  break;
1383 
1384  case CS_INITIAL:
1385  if (other_state != CS_INITIAL)
1386  {
1387  g_eventLogger->warning("Refusing CONGIG_CHECK_REQ from %u, "
1388  " it's not CS_INITIAL (I am). "
1389  " Waiting for my check",
1390  nodeId);
1391  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongState,
1392  generation, other_generation,
1393  m_config_state, other_state);
1394  return;
1395  }
1396 
1397  require(generation == 0);
1398  if (other_generation != generation)
1399  {
1400  g_eventLogger->warning("Refusing other node, it has different " \
1401  "generation: %d, expected: %d",
1402  other_generation, generation);
1403  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongGeneration,
1404  generation, other_generation,
1405  m_config_state, other_state);
1406  return;
1407  }
1408 
1409  if (other_checksum != checksum)
1410  {
1411  g_eventLogger->warning("Refusing other node, it has different "
1412  "checksum: 0x%.8x, expected: 0x%.8x",
1413  other_checksum, checksum);
1414  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongChecksum,
1415  generation, other_generation,
1416  m_config_state, other_state);
1417  return;
1418  }
1419  break;
1420 
1421  case CS_CONFIRMED:
1422 
1423  if (other_state != CS_CONFIRMED)
1424  {
1425  g_eventLogger->warning("Refusing other node, it's in different " \
1426  "state: %d, expected: %d",
1427  other_state, m_config_state);
1428  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongState,
1429  generation, other_generation,
1430  m_config_state, other_state);
1431  return;
1432  }
1433 
1434  if (other_generation == generation)
1435  {
1436  // Same generation, make sure it has same checksum
1437  if (other_checksum != checksum)
1438  {
1439  g_eventLogger->warning("Refusing other node, it has different "
1440  "checksum: 0x%.8x, expected: 0x%.8x",
1441  other_checksum, checksum);
1442  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongChecksum,
1443  generation, other_generation,
1444  m_config_state, other_state);
1445  return;
1446  }
1447  // OK!
1448  }
1449  else if (other_generation < generation)
1450  {
1451  g_eventLogger->warning("Refusing other node, it has lower " \
1452  " generation: %d, expected: %d",
1453  other_generation, generation);
1454  sendConfigCheckRef(ss, from, ConfigCheckRef::WrongGeneration,
1455  generation, other_generation,
1456  m_config_state, other_state);
1457  return;
1458  }
1459  else
1460  {
1461  g_eventLogger->error("Other node has higher generation: %d, this " \
1462  "node is out of sync with generation: %d",
1463  other_generation, generation);
1464  exit(1);
1465  }
1466 
1467  break;
1468  }
1469 
1470  sendConfigCheckConf(ss, from);
1471  return;
1472 }
1473 
1474 
1475 void
1476 ConfigManager::sendConfigCheckReq(SignalSender& ss, NodeBitmask to)
1477 {
1478  SimpleSignal ssig;
1479  ConfigCheckReq* const req =
1480  CAST_PTR(ConfigCheckReq, ssig.getDataPtrSend());
1481  req->state = m_config_state;
1482  req->generation = m_config->getGeneration();
1483  req->checksum = config_check_checksum(m_config);
1484 
1485  g_eventLogger->debug("Sending CONFIG_CHECK_REQ to %s",
1486  BaseString::getPrettyText(to).c_str());
1487 
1488  require(m_waiting_for.isclear());
1489  m_waiting_for = ss.broadcastSignal(to, ssig, MGM_CONFIG_MAN,
1490  GSN_CONFIG_CHECK_REQ,
1491  ConfigCheckReq::SignalLength);
1492 }
1493 
1494 static bool
1495 send_config_in_check_ref(Uint32 x)
1496 {
1497  if (x >= NDB_MAKE_VERSION(7,0,8))
1498  return true;
1499  return false;
1500 }
1501 
1502 void
1503 ConfigManager::sendConfigCheckRef(SignalSender& ss, BlockReference to,
1504  ConfigCheckRef::ErrorCode error,
1505  Uint32 generation,
1506  Uint32 other_generation,
1507  ConfigState state,
1508  ConfigState other_state) const
1509 {
1510  int result;
1511  NodeId nodeId = refToNode(to);
1512  SimpleSignal ssig;
1513  ConfigCheckRef* const ref =
1514  CAST_PTR(ConfigCheckRef, ssig.getDataPtrSend());
1515  ref->error = error;
1516  ref->generation = other_generation;
1517  ref->expected_generation = generation;
1518  ref->state = other_state;
1519  ref->expected_state = state;
1520 
1521  g_eventLogger->debug("Send CONFIG_CHECK_REF with error: %d to node: %d",
1522  error, nodeId);
1523 
1524  if (!send_config_in_check_ref(ss.getNodeInfo(nodeId).m_info.m_version))
1525  {
1526  result = ss.sendSignal(nodeId, ssig, MGM_CONFIG_MAN,
1527  GSN_CONFIG_CHECK_REF, ConfigCheckRef::SignalLength);
1528  }
1529  else
1530  {
1531  UtilBuffer buf;
1532  m_config->pack(buf);
1533  ssig.ptr[0].p = (Uint32*)buf.get_data();
1534  ssig.ptr[0].sz = (buf.length() + 3) / 4;
1535  ssig.header.m_noOfSections = 1;
1536 
1537  ref->length = buf.length();
1538 
1539  g_eventLogger->debug("Sending CONFIG_CHECK_REF with config");
1540 
1541  result = ss.sendFragmentedSignal(nodeId, ssig, MGM_CONFIG_MAN,
1542  GSN_CONFIG_CHECK_REF,
1543  ConfigCheckRef::SignalLengthWithConfig);
1544  }
1545 
1546  if (result != 0)
1547  {
1548  g_eventLogger->warning("Failed to send CONFIG_CHECK_REF "
1549  "to node: %d, result: %d",
1550  nodeId, result);
1551  }
1552 }
1553 
1554 void
1555 ConfigManager::sendConfigCheckConf(SignalSender& ss, BlockReference to) const
1556 {
1557  NodeId nodeId = refToNode(to);
1558  SimpleSignal ssig;
1559  ConfigCheckConf* const conf =
1560  CAST_PTR(ConfigCheckConf, ssig.getDataPtrSend());
1561  conf->state = m_config_state;
1562  conf->generation = m_config->getGeneration();
1563 
1564  g_eventLogger->debug("Send CONFIG_CHECK_CONF to node: %d", nodeId);
1565 
1566  ss.sendSignal(nodeId, ssig, MGM_CONFIG_MAN,
1567  GSN_CONFIG_CHECK_CONF, ConfigCheckConf::SignalLength);
1568 }
1569 
1570 
1571 void
1572 ConfigManager::execCONFIG_CHECK_CONF(SignalSender& ss, SimpleSignal* sig)
1573 {
1574  BlockReference from = sig->header.theSendersBlockRef;
1575  NodeId nodeId = refToNode(from);
1576  assert(m_waiting_for.get(nodeId));
1577  m_waiting_for.clear(nodeId);
1578  m_checked.set(nodeId);
1579 
1580  g_eventLogger->debug("Got CONFIG_CHECK_CONF from node: %d",
1581  nodeId);
1582 
1583  return;
1584 }
1585 
1586 
1587 void
1588 ConfigManager::execCONFIG_CHECK_REF(SignalSender& ss, SimpleSignal* sig)
1589 {
1590  BlockReference from = sig->header.theSendersBlockRef;
1591  NodeId nodeId = refToNode(from);
1592  assert(m_waiting_for.get(nodeId));
1593 
1594  const ConfigCheckRef* const ref =
1595  CAST_CONSTPTR(ConfigCheckRef, sig->getDataPtr());
1596 
1597  if (!m_defragger.defragment(sig))
1598  return; // More fragments to come
1599 
1600  g_eventLogger->debug("Got CONFIG_CHECK_REF from node %d, "
1601  "error: %d, message: '%s', "
1602  "generation: %d, expected generation: %d, "
1603  "state: %d, expected state: %d own-state: %u",
1604  nodeId, ref->error,
1605  ConfigCheckRef::errorMessage(ref->error),
1606  ref->generation, ref->expected_generation,
1607  ref->state, ref->expected_state,
1608  m_config_state);
1609 
1610  assert(ref->generation != ref->expected_generation ||
1611  ref->state != ref->expected_state ||
1612  ref->error == ConfigCheckRef::WrongChecksum);
1613  if((Uint32)m_config_state != ref->state)
1614  {
1615  // The config state changed while this check was in the air
1616  // drop the signal and thus cause it to run again later
1617  require(!m_checked.get(nodeId));
1618  m_waiting_for.clear(nodeId);
1619  return;
1620  }
1621 
1622  switch(m_config_state)
1623  {
1624  default:
1625  case CS_UNINITIALIZED:
1626  g_eventLogger->error("execCONFIG_CHECK_REF: unhandled state");
1627  abort();
1628  break;
1629 
1630  case CS_INITIAL:
1631  if (ref->expected_state == CS_CONFIRMED)
1632  {
1633  if (sig->header.theLength != ConfigCheckRef::SignalLengthWithConfig)
1634  break; // No config in the REF -> no action
1635 
1636  // The other node has sent it's config in the signal, use it if equal
1637  assert(sig->header.m_noOfSections == 1);
1638 
1640  require(cf.unpack(sig->ptr[0].p, ref->length));
1641 
1642  Config other_config(cf.getConfigValues());
1643  assert(other_config.getGeneration() > 0);
1644 
1645  unsigned exclude[]= {CFG_SECTION_SYSTEM, 0};
1646  if (!other_config.equal(m_config, exclude))
1647  {
1648  BaseString buf;
1649  g_eventLogger->error("This node was started --initial with "
1650  "a config which is _not_ equal to the one "
1651  "node %d is using. Refusing to start with "
1652  "different configurations, diff: \n%s",
1653  nodeId,
1654  other_config.diff2str(m_config, buf, exclude));
1655  exit(1);
1656  }
1657 
1658  g_eventLogger->info("This node was started --inital with "
1659  "a config equal to the one node %d is using. "
1660  "Will use the config with generation %d "
1661  "from node %d!",
1662  nodeId, other_config.getGeneration(), nodeId);
1663 
1664  if (! prepareConfigChange(&other_config))
1665  {
1666  abortConfigChange();
1667  g_eventLogger->error("Failed to write the fetched config to disk");
1668  exit(1);
1669  }
1670  commitConfigChange();
1671  m_config_state = CS_CONFIRMED;
1672  g_eventLogger->info("The fetched configuration has been saved!");
1673  m_waiting_for.clear(nodeId);
1674  m_checked.set(nodeId);
1675  delete m_config_change.m_initial_config;
1676  m_config_change.m_initial_config = NULL;
1677  return;
1678  }
1679  break;
1680 
1681  case CS_CONFIRMED:
1682  if (ref->expected_state == CS_INITIAL)
1683  {
1684  g_eventLogger->info("Waiting for peer");
1685  m_waiting_for.clear(nodeId);
1686  return;
1687  }
1688  break;
1689  }
1690 
1691  if (ref->error == ConfigCheckRef::WrongChecksum &&
1692  m_node_id < nodeId)
1693  {
1694  g_eventLogger->warning("Ignoring CONFIG_CHECK_REF for wrong checksum "
1695  "other node has higher node id and should "
1696  "shutdown");
1697  return;
1698  }
1699 
1700  g_eventLogger->error("Terminating");
1701  exit(1);
1702 }
1703 
1704 void
1705 ConfigManager::set_facade(TransporterFacade * f)
1706 {
1707  m_facade = f;
1708  m_ss = new SignalSender(f, MGM_CONFIG_MAN);
1709  require(m_ss != 0);
1710 }
1711 
1712 bool
1713 ConfigManager::ConfigChange::config_loaded(Config* config)
1714 {
1715  if (m_loaded_config != 0)
1716  return false;
1717  m_loaded_config = config;
1718  return true;
1719 }
1720 
1721 Config*
1722 ConfigManager::prepareLoadedConfig(Config * new_conf)
1723 {
1724  /* Copy the necessary values from old to new config */
1725  if (!new_conf->setGeneration(m_config->getGeneration()))
1726  {
1727  g_eventLogger->error("Failed to copy generation from old config");
1728  delete new_conf;
1729  return 0;
1730  }
1731 
1732  if (!new_conf->setName(m_config->getName()))
1733  {
1734  g_eventLogger->error("Failed to copy name from old config");
1735  delete new_conf;
1736  return 0;
1737  }
1738 
1739  if (!new_conf->setPrimaryMgmNode(m_config->getPrimaryMgmNode()))
1740  {
1741  g_eventLogger->error("Failed to copy primary mgm node from old config");
1742  delete new_conf;
1743  return 0;
1744  }
1745 
1746  /* Check if config has changed */
1747  if (!m_config->equal(new_conf))
1748  {
1749  /* Loaded config is different */
1750  BaseString buf;
1751  g_eventLogger->info("Detected change of %s on disk, will try to "
1752  "set it. "
1753  "This is the actual diff:\n%s",
1754  m_opts.mycnf ? "my.cnf" : m_opts.config_filename,
1755  m_config->diff2str(new_conf, buf));
1756 
1757  return new_conf;
1758  }
1759  else
1760  {
1761  /* Loaded config was equal to current */
1762  g_eventLogger->info("Config equal!");
1763  delete new_conf;
1764  }
1765  return 0;
1766 }
1767 
1768 void
1769 ConfigManager::run()
1770 {
1771  assert(m_facade);
1772  SignalSender & ss = * m_ss;
1773 
1774  if (!m_opts.config_cache)
1775  {
1776  /* Stop receiving signals by closing ConfigManager's
1777  block in TransporterFacade */
1778  delete m_ss;
1779  m_ss = NULL;
1780 
1781  /* Confirm the present config, free the space that was allocated for a
1782  new one, and terminate the manager thread */
1783  m_config_change.release();
1784  m_config_state = CS_CONFIRMED;
1785  ndbout_c("== ConfigManager disabled -- manager thread will exit ==");
1786  return;
1787  }
1788 
1789  ss.lock();
1790 
1791  // Build bitmaks of all mgm nodes in config
1792  m_config->get_nodemask(m_all_mgm, NDB_MGM_NODE_TYPE_MGM);
1793 
1794  // exclude nowait-nodes from config change protcol
1795  m_all_mgm.bitANDC(m_opts.nowait_nodes);
1796  m_all_mgm.set(m_facade->ownId()); // Never exclude own node
1797 
1798  start_checkers();
1799 
1800  while (!is_stopped())
1801  {
1802 
1803  if (m_config_change.m_state == ConfigChangeState::IDLE)
1804  {
1805  bool print_state = false;
1806  if (m_previous_state != m_config_state)
1807  {
1808  print_state = true;
1809  m_previous_state = m_config_state;
1810  }
1811 
1812  /*
1813  Check if it's necessary to start something to get
1814  out of the current state
1815  */
1816  switch (m_config_state){
1817 
1818  case CS_UNINITIALIZED:
1819  abort();
1820  break;
1821 
1822  case CS_INITIAL:
1823  /*
1824  INITIAL => CONFIRMED
1825  When all mgm nodes has been started and checked that they
1826  are also in INITIAL, the node with the lowest node id
1827  will start an initial config change. When completed
1828  all nodes will be in CONFIRMED
1829  */
1830 
1831  if (print_state)
1832  ndbout_c("==INITIAL==");
1833 
1834  if (m_config_change.m_initial_config && // Updated config.ini was found
1835  m_started.equal(m_all_mgm) && // All mgmd started
1836  m_checked.equal(m_started) && // All nodes checked
1837  m_all_mgm.find(0) == m_facade->ownId()) // Lowest nodeid
1838  {
1839  Config* new_conf = m_config_change.m_initial_config;
1840  m_config_change.m_initial_config = 0;
1841  m_config_change.m_new_config = new_conf;
1842  startConfigChange(ss, ss.getOwnRef());
1843  }
1844  break;
1845 
1846  case CS_CONFIRMED:
1847  if (print_state)
1848  ndbout_c("==CONFIRMED==");
1849 
1850  if (m_config_change.m_loaded_config != 0 &&
1851  m_config_change.m_new_config == 0 &&
1852  m_started.equal(m_all_mgm) &&
1853  m_checked.equal(m_started))
1854  {
1855  Config* new_conf = m_config_change.m_loaded_config;
1856  m_config_change.m_loaded_config = 0;
1857  m_config_change.m_new_config = prepareLoadedConfig(new_conf);
1858  }
1859 
1860  if (m_config_change.m_new_config && // Updated config.ini was found
1861  m_started.equal(m_all_mgm) && // All mgmd started
1862  m_checked.equal(m_started)) // All nodes checked
1863  {
1864  startConfigChange(ss, ss.getOwnRef());
1865  }
1866 
1867  break;
1868 
1869  default:
1870  break;
1871  }
1872 
1873  // Send CHECK_CONFIG to all nodes not yet checked
1874  if (m_waiting_for.isclear() && // Nothing outstanding
1875  m_prepared_config == 0 && // and no config change ongoing
1876  !m_checked.equal(m_started)) // Some nodes have not been checked
1877  {
1878  NodeBitmask not_checked;
1879  not_checked.assign(m_started);
1880  not_checked.bitANDC(m_checked);
1881  sendConfigCheckReq(ss, not_checked);
1882  }
1883 
1884  handle_exclude_nodes();
1885  }
1886 
1887  SimpleSignal *sig = ss.waitFor((Uint32)1000);
1888  if (!sig)
1889  continue;
1890 
1891  switch (sig->readSignalNumber()) {
1892 
1893  case GSN_CONFIG_CHANGE_REQ:
1894  execCONFIG_CHANGE_REQ(ss, sig);
1895  break;
1896 
1897  case GSN_CONFIG_CHANGE_IMPL_REQ:
1898  execCONFIG_CHANGE_IMPL_REQ(ss, sig);
1899  break;
1900 
1901  case GSN_CONFIG_CHANGE_IMPL_REF:
1902  execCONFIG_CHANGE_IMPL_REF(ss, sig);
1903  break;
1904 
1905  case GSN_CONFIG_CHANGE_IMPL_CONF:
1906  execCONFIG_CHANGE_IMPL_CONF(ss, sig);
1907  break;
1908 
1909  case GSN_NF_COMPLETEREP:{
1910  const NFCompleteRep * const rep =
1911  CAST_CONSTPTR(NFCompleteRep, sig->getDataPtr());
1912  NodeId nodeId= rep->failedNodeId;
1913 
1914  if (m_all_mgm.get(nodeId)) // Not mgm node
1915  break;
1916 
1917  ndbout_c("Node %d failed", nodeId);
1918  m_started.clear(nodeId);
1919  m_checked.clear(nodeId);
1920  m_defragger.node_failed(nodeId);
1921 
1922  if (m_config_change.m_state != ConfigChangeState::IDLE)
1923  {
1924  g_eventLogger->info("Node %d failed during config change!!",
1925  nodeId);
1926  g_eventLogger->warning("Node failure handling of config "
1927  "change protocol not yet implemented!! "
1928  "No more configuration changes can occur, "
1929  "but the node will continue to serve the "
1930  "last good configuration");
1931  // TODO start take over of config change protocol
1932  }
1933  break;
1934  }
1935 
1936  case GSN_NODE_FAILREP:
1937  // ignore, NF_COMPLETEREP will come
1938  break;
1939 
1940  case GSN_API_REGCONF:{
1941  NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
1942  if (m_all_mgm.get(nodeId) && // Is a mgm node
1943  !m_started.get(nodeId)) // Not already marked as started
1944  {
1945  g_eventLogger->info("Node %d connected", nodeId);
1946  m_started.set(nodeId);
1947  }
1948  break;
1949  }
1950 
1951  case GSN_CONFIG_CHECK_REQ:
1952  execCONFIG_CHECK_REQ(ss, sig);
1953  break;
1954 
1955  case GSN_CONFIG_CHECK_REF:
1956  execCONFIG_CHECK_REF(ss, sig);
1957  break;
1958 
1959  case GSN_CONFIG_CHECK_CONF:
1960  execCONFIG_CHECK_CONF(ss, sig);
1961  break;
1962 
1963  case GSN_TAKE_OVERTCCONF:
1964  case GSN_CONNECT_REP:
1965  break;
1966 
1967  default:
1968  sig->print();
1969  g_eventLogger->error("Unknown signal received. SignalNumber: "
1970  "%i from (%d, 0x%x)",
1971  sig->readSignalNumber(),
1972  refToNode(sig->header.theSendersBlockRef),
1973  refToBlock(sig->header.theSendersBlockRef));
1974  abort();
1975  break;
1976  }
1977  }
1978  stop_checkers();
1979  ss.unlock();
1980 }
1981 
1982 
1983 #include "InitConfigFileParser.hpp"
1984 
1985 Config*
1986 ConfigManager::load_init_config(const char* config_filename)
1987 {
1988  InitConfigFileParser parser;
1989  return parser.parseConfig(config_filename);
1990 }
1991 
1992 
1993 Config*
1994 ConfigManager::load_init_mycnf(void)
1995 {
1996  InitConfigFileParser parser;
1997  return parser.parse_mycnf();
1998 }
1999 
2000 
2001 Config*
2002 ConfigManager::load_config(const char* config_filename, bool mycnf,
2003  BaseString& msg)
2004 {
2005  Config* new_conf = NULL;
2006  if (mycnf && (new_conf = load_init_mycnf()) == NULL)
2007  {
2008  msg.assign("Could not load configuration from 'my.cnf'");
2009  return NULL;
2010  }
2011  else if (config_filename &&
2012  (new_conf = load_init_config(config_filename)) == NULL)
2013  {
2014  msg.assfmt("Could not load configuration from '%s'",
2015  config_filename);
2016  return NULL;
2017  }
2018 
2019  return new_conf;
2020 }
2021 
2022 
2023 Config*
2024 ConfigManager::load_config(void) const
2025 {
2026  BaseString msg;
2027  Config* new_conf = NULL;
2028  if ((new_conf = load_config(m_opts.config_filename,
2029  m_opts.mycnf, msg)) == NULL)
2030  {
2031  g_eventLogger->error(msg);
2032  return NULL;
2033  }
2034  return new_conf;
2035 }
2036 
2037 
2038 Config*
2039 ConfigManager::fetch_config(void)
2040 {
2041  DBUG_ENTER("ConfigManager::fetch_config");
2042 
2043  while(true)
2044  {
2045  /* Loop until config loaded from other mgmd(s) */
2046  char buf[128];
2047  g_eventLogger->info("Trying to get configuration from other mgmd(s) "\
2048  "using '%s'...",
2049  m_config_retriever.get_connectstring(buf, sizeof(buf)));
2050 
2051  if (m_config_retriever.is_connected() ||
2052  m_config_retriever.do_connect(30 /* retry */,
2053  1 /* delay */,
2054  0 /* verbose */) == 0)
2055  {
2056  g_eventLogger->info("Connected to '%s:%d'...",
2057  m_config_retriever.get_mgmd_host(),
2058  m_config_retriever.get_mgmd_port());
2059  break;
2060  }
2061  }
2062  // read config from other management server
2063  ndb_mgm_configuration * tmp =
2064  m_config_retriever.getConfig(m_config_retriever.get_mgmHandle());
2065 
2066  // Disconnect from other mgmd
2067  m_config_retriever.disconnect();
2068 
2069  if (tmp == NULL) {
2070  g_eventLogger->error("%s", m_config_retriever.getErrorString());
2071  DBUG_RETURN(false);
2072  }
2073 
2074  DBUG_RETURN(new Config(tmp));
2075 }
2076 
2077 
2078 static bool
2079 delete_file(const char* file_name)
2080 {
2081 #ifdef _WIN32
2082  if (DeleteFile(file_name) == 0)
2083  {
2084  g_eventLogger->error("Failed to delete file '%s', error: %d",
2085  file_name, GetLastError());
2086  return false;
2087  }
2088 #else
2089  if (unlink(file_name) == -1)
2090  {
2091  g_eventLogger->error("Failed to delete file '%s', error: %d",
2092  file_name, errno);
2093  return false;
2094  }
2095 #endif
2096  return true;
2097 }
2098 
2099 
2100 bool
2101 ConfigManager::delete_saved_configs(void) const
2102 {
2103  NdbDir::Iterator iter;
2104 
2105  if (iter.open(m_configdir) != 0)
2106  return false;
2107 
2108  bool result = true;
2109  const char* name;
2110  unsigned nodeid;
2111  char extra; // Avoid matching ndb_2_config.bin.2.tmp
2112  BaseString full_name;
2113  unsigned version;
2114  while ((name= iter.next_file()) != NULL)
2115  {
2116  if (sscanf(name,
2117  "ndb_%u_config.bin.%u%c",
2118  &nodeid, &version, &extra) == 2)
2119  {
2120  // ndbout_c("match: %s", name);
2121 
2122  if (nodeid != m_node_id)
2123  continue;
2124 
2125  // Delete the file
2126  full_name.assfmt("%s%s%s", m_configdir, DIR_SEPARATOR, name);
2127  g_eventLogger->debug("Deleting binary config file '%s'",
2128  full_name.c_str());
2129  if (!delete_file(full_name.c_str()))
2130  {
2131  // Make function return false, but continue and try
2132  // to delete other files
2133  result = false;
2134  }
2135  }
2136  }
2137 
2138  return result;
2139 }
2140 
2141 
2142 bool
2143 ConfigManager::saved_config_exists(BaseString& config_name) const
2144 {
2145  NdbDir::Iterator iter;
2146 
2147  if (iter.open(m_configdir) != 0)
2148  return false;
2149 
2150  const char* name;
2151  unsigned nodeid;
2152  char extra; // Avoid matching ndb_2_config.bin.2.tmp
2153  unsigned version, max_version= 0;
2154  while ((name= iter.next_file()) != NULL)
2155  {
2156  if (sscanf(name,
2157  "ndb_%u_config.bin.%u%c",
2158  &nodeid, &version, &extra) == 2)
2159  {
2160  // ndbout_c("match: %s", name);
2161 
2162  if (nodeid != m_node_id)
2163  continue;
2164 
2165  if (version>max_version)
2166  max_version= version;
2167  }
2168  }
2169 
2170  if (max_version == 0)
2171  return false;
2172 
2173  config_name.assfmt("%s%sndb_%u_config.bin.%u",
2174  m_configdir, DIR_SEPARATOR, m_node_id, max_version);
2175  return true;
2176 }
2177 
2178 
2179 
2180 bool
2181 ConfigManager::failed_config_change_exists() const
2182 {
2183  NdbDir::Iterator iter;
2184 
2185  if (iter.open(m_configdir) != 0)
2186  return false;
2187 
2188  const char* name;
2189  char tmp;
2190  unsigned nodeid;
2191  unsigned version;
2192  while ((name= iter.next_file()) != NULL)
2193  {
2194  // Check for a previously failed config
2195  // change, ie. ndb_<nodeid>_config.bin.X.tmp exist
2196  if (sscanf(name,
2197  "ndb_%u_config.bin.%u.tm%c",
2198  &nodeid, &version, &tmp) == 3 &&
2199  tmp == 'p')
2200  {
2201  if (nodeid != m_node_id)
2202  continue;
2203 
2204  g_eventLogger->error("Found binary configuration file '%s%s%s' from "
2205  "previous failed attempt to change config. This "
2206  "error must be manually resolved by removing the "
2207  "file(ie. ROLLBACK) or renaming the file to it's "
2208  "name without the .tmp extension(ie COMMIT). Make "
2209  "sure to check the other nodes so that they all "
2210  "have the same configuration generation.",
2211  m_configdir, DIR_SEPARATOR, name);
2212  return true;
2213  }
2214  }
2215 
2216  return false;
2217 }
2218 
2219 
2220 Config*
2221 ConfigManager::load_saved_config(const BaseString& config_name)
2222 {
2223  struct ndb_mgm_configuration * tmp =
2224  m_config_retriever.getConfig(config_name.c_str());
2225  if(tmp == NULL)
2226  {
2227  g_eventLogger->error("Failed to load config from '%s', error: '%s'",
2228  config_name.c_str(),
2229  m_config_retriever.getErrorString());
2230  return NULL;
2231  }
2232 
2233  Config* conf = new Config(tmp);
2234  if (conf == NULL)
2235  g_eventLogger->error("Failed to load config, out of memory");
2236  return conf;
2237 }
2238 
2239 bool
2240 ConfigManager::get_packed_config(ndb_mgm_node_type nodetype,
2241  BaseString* buf64, BaseString& error)
2242 {
2243  Guard g(m_config_mutex);
2244 
2245  /*
2246  Only allow the config to be exported if it's been confirmed
2247  or if another mgmd is asking for it
2248  */
2249  switch(m_config_state)
2250  {
2251  case CS_INITIAL:
2252  if (nodetype == NDB_MGM_NODE_TYPE_MGM)
2253  ; // allow other mgmd to fetch initial configuration
2254  else
2255  {
2256  error.assign("The cluster configuration is not yet confirmed "
2257  "by all defined management servers. ");
2258  if (m_config_change.m_state != ConfigChangeState::IDLE)
2259  {
2260  error.append("Initial configuration change is in progress.");
2261  }
2262  else
2263  {
2264  NodeBitmask not_started(m_all_mgm);
2265  not_started.bitANDC(m_checked);
2266  error.append("This management server is still waiting for node ");
2267  error.append(BaseString::getPrettyText(not_started));
2268  error.append(" to connect.");
2269  }
2270  return false;
2271  }
2272  break;
2273 
2274  case CS_CONFIRMED:
2275  // OK
2276  break;
2277 
2278  default:
2279  error.assign("get_packed_config, unknown config state: %d",
2280  m_config_state);
2281  return false;
2282  break;
2283 
2284  }
2285 
2286  require(m_config != 0);
2287  if (buf64)
2288  {
2289  if (!m_packed_config.length())
2290  {
2291  // No packed config exist, generate a new one
2292  Config config_copy(m_config);
2293  if (!m_dynamic_ports.set_in_config(&config_copy))
2294  {
2295  error.assign("get_packed_config, failed to set dynamic ports in config");
2296  return false;
2297  }
2298 
2299  if (!config_copy.pack64(m_packed_config))
2300  {
2301  error.assign("get_packed_config, failed to pack config_copy");
2302  return false;
2303  }
2304  }
2305  buf64->assign(m_packed_config, m_packed_config.length());
2306  }
2307  return true;
2308 }
2309 
2310 
2311 bool
2312 ConfigManager::init_checkers(const Config* config)
2313 {
2314 
2315  // Init one thread for each other mgmd
2316  // in the config and check which version it has. If version
2317  // does not have config manager, set this node to ignore
2318  // that node in the config change protocol
2319 
2320  BaseString connect_string;
2321  ConfigIter iter(config, CFG_SECTION_NODE);
2322  for (iter.first(); iter.valid(); iter.next())
2323  {
2324 
2325  // Only MGM nodes
2326  Uint32 type;
2327  if (iter.get(CFG_TYPE_OF_SECTION, &type) ||
2328  type != NODE_TYPE_MGM)
2329  continue;
2330 
2331  // Not this node
2332  Uint32 nodeid;
2333  if(iter.get(CFG_NODE_ID, &nodeid) ||
2334  nodeid == m_node_id)
2335  continue;
2336 
2337  const char* hostname;
2338  Uint32 port;
2339  require(!iter.get(CFG_NODE_HOST, &hostname));
2340  require(!iter.get(CFG_MGM_PORT, &port));
2341  connect_string.assfmt("%s:%u",hostname,port);
2342 
2343  ConfigChecker* checker =
2344  new ConfigChecker(*this, connect_string.c_str(),
2345  m_opts.bind_address, nodeid);
2346  if (!checker)
2347  {
2348  g_eventLogger->error("Failed to create ConfigChecker");
2349  return false;
2350  }
2351 
2352  if (!checker->init())
2353  return false;
2354 
2355  m_checkers.push_back(checker);
2356  }
2357  return true;
2358 }
2359 
2360 
2361 void
2362 ConfigManager::start_checkers(void)
2363 {
2364  for (unsigned i = 0; i < m_checkers.size(); i++)
2365  m_checkers[i]->start();
2366 }
2367 
2368 
2369 void
2370 ConfigManager::stop_checkers(void)
2371 {
2372  for (unsigned i = 0; i < m_checkers.size(); i++)
2373  {
2374  ConfigChecker* checker = m_checkers[i];
2375  ndbout << "stop checker " << i << endl;
2376  checker->stop();
2377  delete checker;
2378  }
2379 }
2380 
2381 
2382 ConfigManager::ConfigChecker::ConfigChecker(ConfigManager& manager,
2383  const char* connect_string,
2384  const char * bindaddress,
2385  NodeId nodeid) :
2386  MgmtThread("ConfigChecker"),
2387  m_manager(manager),
2388  m_config_retriever(opt_ndb_connectstring, opt_ndb_nodeid, NDB_VERSION,
2389  NDB_MGM_NODE_TYPE_MGM, bindaddress),
2390  m_connect_string(connect_string),
2391  m_nodeid(nodeid)
2392 {
2393 }
2394 
2395 
2396 bool
2398 {
2399  if (m_config_retriever.hasError())
2400  {
2401  g_eventLogger->error("%s", m_config_retriever.getErrorString());
2402  return false;
2403  }
2404 
2405  return true;
2406 }
2407 
2408 
2409 void
2410 ConfigManager::ConfigChecker::run()
2411 {
2412  // Connect to other mgmd inifintely until thread is stopped
2413  // or connect suceeds
2414  g_eventLogger->debug("ConfigChecker, connecting to '%s'",
2415  m_connect_string.c_str());
2416  while(m_config_retriever.do_connect(0 /* retry */,
2417  1 /* delay */,
2418  0 /* verbose */) != 0)
2419  {
2420  if (is_stopped())
2421  {
2422  g_eventLogger->debug("ConfigChecker, thread is stopped");
2423  return; // Thread is stopped
2424  }
2425 
2426  NdbSleep_SecSleep(1);
2427  }
2428 
2429  // Connected
2430  g_eventLogger->debug("ConfigChecker, connected to '%s'",
2431  m_connect_string.c_str());
2432 
2433  // Check version
2434  int major, minor, build;
2435  char ver_str[50];
2436  if (!ndb_mgm_get_version(m_config_retriever.get_mgmHandle(),
2437  &major, &minor, &build,
2438  sizeof(ver_str), ver_str))
2439  {
2440  g_eventLogger->error("Could not get version from mgmd on '%s'",
2441  m_connect_string.c_str());
2442  return;
2443  }
2444  g_eventLogger->debug("mgmd on '%s' has version %d.%d.%d",
2445  m_connect_string.c_str(), major, minor, build);
2446 
2447  // Versions prior to 7 don't have ConfigManager
2448  // exclude it from config change protocol
2449  if (major < 7)
2450  {
2451  g_eventLogger->info("Excluding node %d with version %d.%d.%d from "
2452  "config change protocol",
2453  m_nodeid, major, minor, build);
2454  m_manager.m_exclude_nodes.push_back(m_nodeid);
2455  }
2456 
2457  return;
2458 }
2459 
2460 
2461 void
2462 ConfigManager::handle_exclude_nodes(void)
2463 {
2464 
2465  if (!m_waiting_for.isclear())
2466  return; // Other things going on
2467 
2468  switch (m_config_state)
2469  {
2470  case CS_INITIAL:
2471  m_exclude_nodes.lock();
2472  for (unsigned i = 0; i < m_exclude_nodes.size(); i++)
2473  {
2474  NodeId nodeid = m_exclude_nodes[i];
2475  g_eventLogger->debug("Handle exclusion of node %d", nodeid);
2476  m_all_mgm.clear(nodeid);
2477  }
2478  m_exclude_nodes.unlock();
2479  break;
2480 
2481  default:
2482  break;
2483  }
2484  m_exclude_nodes.clear();
2485 
2486 }
2487 
2488 
2489 static bool
2490 check_dynamic_port_configured(const Config* config,
2491  int node1, int node2,
2492  BaseString& msg)
2493 {
2494  ConfigIter iter(config, CFG_SECTION_CONNECTION);
2495 
2496  for(;iter.valid();iter.next()) {
2497  Uint32 n1, n2;
2498  if (iter.get(CFG_CONNECTION_NODE_1, &n1) != 0 ||
2499  iter.get(CFG_CONNECTION_NODE_2, &n2) != 0)
2500  {
2501  msg.assign("Could not get node1 or node2 from connection section");
2502  return false;
2503  }
2504 
2505  if((n1 == (Uint32)node1 && n2 == (Uint32)node2) ||
2506  (n1 == (Uint32)node2 && n2 == (Uint32)node1))
2507  break;
2508  }
2509  if(!iter.valid()) {
2510  msg.assfmt("Unable to find connection between nodes %d -> %d",
2511  node1, node2);
2512  return false;
2513  }
2514 
2515  Uint32 port;
2516  if(iter.get(CFG_CONNECTION_SERVER_PORT, &port) != 0) {
2517  msg.assign("Unable to get current value of CFG_CONNECTION_SERVER_PORT");
2518  return false;
2519  }
2520 
2521  if (port != 0)
2522  {
2523  // Dynamic ports is zero in configuration
2524  msg.assfmt("Server port for %d -> %d is not marked as dynamic, value: %u",
2525  node1, node2, port);
2526  return false;
2527  }
2528  return true;
2529 }
2530 
2531 
2532 bool
2533 ConfigManager::set_dynamic_port(int node1, int node2, int value,
2534  BaseString& msg){
2535 
2536  Guard g(m_config_mutex);
2537  if (!check_dynamic_port_configured(m_config,
2538  node1, node2, msg))
2539  return false;
2540 
2541  if (!m_dynamic_ports.set(node1, node2, value))
2542  {
2543  msg.assfmt("Could not set dynamic port for %d -> %d", node1, node2);
2544  return false;
2545  }
2546 
2547  // Removed cache of packed config, need to be recreated
2548  // to include the new dynamic port
2549  m_packed_config.clear();
2550 
2551  return true;
2552 }
2553 
2554 
2555 bool
2556 ConfigManager::get_dynamic_port(int node1, int node2, int *value,
2557  BaseString& msg) const {
2558 
2559  Guard g(m_config_mutex);
2560  if (!check_dynamic_port_configured(m_config,
2561  node1, node2, msg))
2562  return false;
2563 
2564  if (!m_dynamic_ports.get(node1, node2, value))
2565  {
2566  msg.assfmt("Could not get dynamic port for %d -> %d", node1, node2);
2567  return false;
2568  }
2569  return true;
2570 }
2571 
2572 
2573 bool ConfigManager::DynamicPorts::check(int& node1, int& node2) const
2574 {
2575  // Always use smaller node first
2576  if (node1 > node2)
2577  {
2578  int tmp = node1;
2579  node1 = node2;
2580  node2 = tmp;
2581  }
2582 
2583  // Only NDB nodes can be dynamic port server
2584  if (node1 <= 0 || node1 >= MAX_NDB_NODES)
2585  return false;
2586  if (node2 <= 0 || node2 >= MAX_NODES)
2587  return false;
2588  if (node1 == node2)
2589  return false;
2590 
2591  return true;
2592 }
2593 
2594 
2595 bool ConfigManager::DynamicPorts::set(int node1, int node2, int port)
2596 {
2597  if (!check(node1, node2))
2598  return false;
2599 
2600  if (!m_ports.insert(NodePair(node1, node2), port, true))
2601  return false;
2602 
2603  return true;
2604 }
2605 
2606 
2607 bool ConfigManager::DynamicPorts::get(int node1, int node2, int* port) const
2608 {
2609  if (!check(node1, node2))
2610  return false;
2611 
2612  int value = 0; // Return 0 if not found
2613  (void)m_ports.search(NodePair(node1, node2), value);
2614 
2615  *port = (int)value;
2616  return true;
2617 }
2618 
2619 
2620 bool
2621 ConfigManager::DynamicPorts::set_in_config(Config* config)
2622 {
2623  bool result = true;
2624  ConfigIter iter(config, CFG_SECTION_CONNECTION);
2625 
2626  for(;iter.valid();iter.next()) {
2627  Uint32 port = 0;
2628  if (iter.get(CFG_CONNECTION_SERVER_PORT, &port) != 0 ||
2629  port != 0)
2630  continue; // Not configured as dynamic port
2631 
2632  Uint32 n1, n2;
2633  require(iter.get(CFG_CONNECTION_NODE_1, &n1) == 0 &&
2634  iter.get(CFG_CONNECTION_NODE_2, &n2) == 0);
2635 
2636  int dyn_port;
2637  if (!get(n1, n2, &dyn_port) || dyn_port == 0)
2638  continue; // No dynamic port registered
2639 
2640  // Write the dynamic port to config
2641  port = (Uint32)dyn_port;
2642  ConfigValues::Iterator i2(config->m_configValues->m_config,
2643  iter.m_config);
2644  if(i2.set(CFG_CONNECTION_SERVER_PORT, port) == false)
2645  result = false;
2646  }
2647  return result;
2648 }
2649 
2650 
2651 template class Vector<ConfigSubscriber*>;
2653