List:Commits« Previous MessageNext Message »
From:Magnus Svensson Date:November 6 2008 1:53pm
Subject:bzr push into mysql-5.1 branch (msvensson:3046)
View as plain text  
 3046 Magnus Svensson	2008-11-06 [merge]
      Merge
modified:
  storage/ndb/include/portlib/NdbThread.h
  storage/ndb/include/transporter/TransporterRegistry.hpp
  storage/ndb/include/util/SocketServer.hpp
  storage/ndb/src/common/portlib/NdbThread.c
  storage/ndb/src/common/transporter/TransporterRegistry.cpp
  storage/ndb/src/common/util/SocketServer.cpp
  storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
  storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
  storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
  storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
  storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
  storage/ndb/src/kernel/main.cpp
  storage/ndb/src/kernel/vm/Configuration.cpp
  storage/ndb/src/kernel/vm/Configuration.hpp
  storage/ndb/src/kernel/vm/DynArr256.cpp
  storage/ndb/src/kernel/vm/WatchDog.cpp
  storage/ndb/src/kernel/vm/WatchDog.hpp
  storage/ndb/src/ndbapi/TransporterFacade.cpp
  storage/ndb/test/ndbapi/testMgm.cpp
  storage/ndb/test/ndbapi/testNodeRestart.cpp
  storage/ndb/test/ndbapi/testScanFilter.cpp
  storage/ndb/test/ndbapi/test_event_merge.cpp

=== modified file 'storage/ndb/include/kernel/NodeInfo.hpp'
--- a/storage/ndb/include/kernel/NodeInfo.hpp	2007-01-24 05:24:35 +0000
+++ b/storage/ndb/include/kernel/NodeInfo.hpp	2008-11-04 08:43:06 +0000
@@ -18,6 +18,7 @@
 
 #include <NdbOut.hpp>
 #include <mgmapi_config_parameters.h>
+#include <ndb_version.h>
 
 class NodeInfo {
 public:
@@ -60,6 +61,27 @@ NodeInfo::getType() const {
   return (NodeType)m_type;
 }
 
+
+class NdbVersion {
+  Uint32 m_ver;
+public:
+  NdbVersion(Uint32 ver) : m_ver(ver) {};
+
+  friend NdbOut& operator<<(NdbOut&, const NdbVersion&);
+};
+
+
+inline
+NdbOut&
+operator<<(NdbOut& ndbout, const NdbVersion& ver){
+  ndbout.print("%d.%d.%d",
+               ndbGetMajor(ver.m_ver),
+               ndbGetMinor(ver.m_ver),
+               ndbGetBuild(ver.m_ver));
+  return ndbout;
+}
+
+
 inline
 NdbOut &
 operator<<(NdbOut& ndbout, const NodeInfo & info){
@@ -82,8 +104,8 @@ operator<<(NdbOut& ndbout, const NodeInf
     break;
   }
 
-  ndbout << " ndb version: " << info.m_version
-	 << " mysql version; " << info.m_mysql_version
+  ndbout << " ndb version: " << NdbVersion(info.m_version)
+	 << " mysql version: " << NdbVersion(info.m_mysql_version)
 	 << " connect count: " << info.m_connectCount
 	 << "]";
   return ndbout;

=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp	2008-10-31 15:25:01 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp	2008-11-05 07:57:18 +0000
@@ -409,7 +409,7 @@ ndb_mgm_call(NdbMgmHandle handle,
   out.println("");
 
   if (cmd_bulk)
-    out.println("%s", cmd_bulk);
+    out.println(cmd_bulk);
 
   DBUG_CHECK_TIMEDOUT_RET(handle, in, out, NULL);
 

=== modified file 'storage/ndb/src/mgmsrv/ConfigManager.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.cpp	2008-10-24 12:41:10 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigManager.cpp	2008-11-06 10:54:21 +0000
@@ -16,6 +16,7 @@
 
 #include "ConfigManager.hpp"
 #include "MgmtSrvr.hpp"
+#include "DirIterator.hpp"
 
 #include <NdbConfig.h>
 
@@ -40,7 +41,8 @@ require(bool v)
 
 extern "C" const char* opt_connect_str;
 
-ConfigManager::ConfigManager(const MgmtSrvr::MgmtOpts& opts) :
+ConfigManager::ConfigManager(const MgmtSrvr::MgmtOpts& opts,
+                             const char* datadir) :
   MgmtThread("ConfigManager"),
   m_opts(opts),
   m_facade(NULL),
@@ -57,7 +59,7 @@ ConfigManager::ConfigManager(const MgmtS
   m_client_ref(RNIL),
   m_prepared_config(NULL),
   m_node_id(0),
-  m_datadir(NULL)
+  m_datadir(datadir)
 {
 }
 
@@ -71,54 +73,223 @@ ConfigManager::~ConfigManager()
 }
 
 
+/**
+   alone_on_host
+
+   Check if this is the only node of "type" on
+   this host
+
+*/
+
+static bool
+alone_on_host(Config* conf,
+              Uint32 own_type,
+              Uint32 own_nodeid)
+{
+  ConfigIter iter(conf, CFG_SECTION_NODE);
+  for (iter.first(); iter.valid(); iter.next())
+  {
+    Uint32 type;
+    if(iter.get(CFG_TYPE_OF_SECTION, &type) ||
+       type != own_type)
+      continue;
+
+    Uint32 nodeid;
+    if(iter.get(CFG_NODE_ID, &nodeid) ||
+       nodeid == own_nodeid)
+      continue;
+
+    const char * hostname;
+    if(iter.get(CFG_NODE_HOST, &hostname))
+      continue;
+
+    if (SocketServer::tryBind(0,hostname))
+    {
+      // Another MGM node was also setup on this host
+      g_eventLogger->debug("Not alone on host %s, node %d "     \
+                           "will also run here",
+                           hostname, nodeid);
+      return false;
+    }
+  }
+  return true;
+}
+
+
+/**
+   find_nodeid_from_datadir
+
+   Check if datadir only contains config files
+   with one nodeid -> read the latest and confirm
+   there should only be one mgm node on this host
+*/
+
+NodeId
+ConfigManager::find_nodeid_from_datadir(void)
+{
+  BaseString config_name;
+  DirIterator iter;
+
+  if (iter.open(m_datadir) != 0)
+    return 0;
+
+  const char* name;
+  unsigned found_nodeid= 0;
+  unsigned nodeid;
+  char extra; // Avoid matching ndb_2_config.bin.2.tmp
+  unsigned version, max_version = 0;
+  while ((name = iter.next_file()) != NULL)
+  {
+    if (sscanf(name,
+               "ndb_%u_config.bin.%u%c",
+               &nodeid, &version, &extra) == 2)
+    {
+      ndbout_c("match: %s", name);
+
+      if (nodeid != found_nodeid)
+      {
+        if (found_nodeid != 0)
+          return 0; // Found more than one nodeid
+        found_nodeid= nodeid;
+      }
+
+      if (version > max_version)
+        max_version = version;
+    }
+  }
+
+  if (max_version == 0)
+    return 0;
+
+  config_name.assfmt("%s%sndb_%u_config.bin.%u",
+                     m_datadir, DIR_SEPARATOR, found_nodeid, max_version);
+
+  Config* conf;
+  if (!(conf = load_saved_config(config_name)))
+    return 0;
+
+  if (!m_config_retriever.verifyConfig(conf->m_configValues,
+                                       found_nodeid) ||
+      !alone_on_host(conf, NDB_MGM_NODE_TYPE_MGM, found_nodeid))
+  {
+    delete conf;
+    return 0;
+  }
+
+  delete conf;
+  return found_nodeid;
+}
+
+
+/**
+   find_own_nodeid
+
+   Return the nodeid of the MGM node
+   defined to run on this host
+
+   Return 0 if more than one node is defined
+*/
+
+static NodeId
+find_own_nodeid(Config* conf)
+{
+  NodeId found_nodeid= 0;
+  ConfigIter iter(conf, CFG_SECTION_NODE);
+  for (iter.first(); iter.valid(); iter.next())
+  {
+    Uint32 type;
+    if(iter.get(CFG_TYPE_OF_SECTION, &type) ||
+       type != NDB_MGM_NODE_TYPE_MGM)
+      continue;
+
+    Uint32 nodeid;
+    require(iter.get(CFG_NODE_ID, &nodeid) == 0);
+
+    const char * hostname;
+    if(iter.get(CFG_NODE_HOST, &hostname))
+      continue;
+
+    if (SocketServer::tryBind(0,hostname))
+    {
+      // This node is setup to run on this host
+      if (found_nodeid == 0)
+        found_nodeid = nodeid;
+      else
+        return 0; // More than one host on this node
+    }
+  }
+  return found_nodeid;
+}
+
+
+NodeId
+ConfigManager::find_nodeid_from_config(void)
+{
+  if (!m_opts.mycnf &&
+      !m_opts.config_filename)
+    return 0;
+
+  Config* conf = load_config();
+  if (conf == NULL)
+    return 0;
+
+  NodeId found_nodeid = find_own_nodeid(conf);
+  if (found_nodeid == 0 ||
+      !m_config_retriever.verifyConfig(conf->m_configValues, found_nodeid))
+  {
+    delete conf;
+    return 0;
+  }
+
+  return found_nodeid;
+
+}
+
 
 bool
 ConfigManager::init_nodeid(void)
 {
   DBUG_ENTER("ConfigManager::init_nodeid");
 
-  NodeId nodeid= m_config_retriever.get_configuration_nodeid();
-  DBUG_PRINT("info", ("nodeid: %d", nodeid));
-
+  NodeId nodeid = m_config_retriever.get_configuration_nodeid();
   if (nodeid)
   {
     // Nodeid was specifed on command line or in NDB_CONNECTSTRING
-    m_node_id= nodeid;
+    g_eventLogger->debug("Got nodeid: %d from command line "    \
+                         "or NDB_CONNECTSTRING", m_node_id);
+    m_node_id = nodeid;
+    DBUG_RETURN(true);
+  }
+
+  nodeid = find_nodeid_from_datadir();
+  if (nodeid)
+  {
+    // Found nodeid by searching in datadir
+    g_eventLogger->debug("Got nodeid: %d from searching in datadir",
+                         nodeid);
+    m_node_id = nodeid;
+    DBUG_RETURN(true);
+  }
+
+  nodeid = find_nodeid_from_config();
+  if (nodeid)
+  {
+    // Found nodeid by looking in the config given on command line
+    g_eventLogger->debug("Got nodeid: %d from config file given "       \
+                         "on command line",
+                         nodeid);
+    m_node_id = nodeid;
     DBUG_RETURN(true);
   }
 
-#if 0
+
   // We _could_ try connecting to other running mgmd(s)
   // and fetch our nodeid. But, that introduces a dependency
   // that is not beneficial for a shared nothing cluster, since
   // it might only work when other mgmd(s) are started. If all
   // mgmd(s) is down it would require manual intervention.
   // Better to require the node id to always be specified
-  // on the command line(or some other "local" magic by
-  // examining --datadir)
-
-  // Try to alloc nodeid from other mgmd
-  char buf[128];
-  g_eventLogger->info("Trying to get nodeid from other mgmd(s) "\
-                      "using '%s'...",
-                      m_config_retriever.get_connectstring(buf, sizeof(buf)));
-
-  if (m_config_retriever.do_connect(3, /* retry */
-                                    1, /* delay */
-                                    0  /* verbose */) == 0)
-  {
-    g_eventLogger->info("Connected...");
-
-    nodeid = m_config_retriever.allocNodeId(3, /* retry */
-                                            1  /* delay */);
-    if (nodeid == 0)
-    {
-      // Failed to alloc nodeid from other mgmd
-      g_eventLogger->error(m_config_retriever.getErrorString());
-      DBUG_RETURN(false);
-    }
-  }
-#endif
+  // on the command line(or the above _local_ magic)
 
   g_eventLogger->error("Could not determine which nodeid to use for "\
                        "this node. Specify it with --ndb-nodeid=<nodeid> "\
@@ -147,34 +318,6 @@ ConfigManager::init(void)
     DBUG_RETURN(false);
   }
 
-  // Check datadir
-  if (m_opts.datadir)
-  {
-    // Specified on commmand line
-    if (access(m_opts.datadir, F_OK))
-    {
-      g_eventLogger->error("Directory '%s' specified with --datadir "   \
-                           "does not exist", m_opts.datadir);
-      DBUG_RETURN(false);
-    }
-    m_datadir= m_opts.datadir;
-  }
-  else
-  {
-    // Compiled in path MYSQLCLUSTERDIR
-    if (access(MYSQLCLUSTERDIR, F_OK))
-    {
-      g_eventLogger->error("The default data directory '%s' "            \
-                           "does not exist. Either create it or "       \
-                           "specify a different directory with "        \
-                           "--datadir=<path>",
-                           MYSQLCLUSTERDIR);
-      DBUG_RETURN(false);
-    }
-    m_datadir= MYSQLCLUSTERDIR;
-  }
-  DBUG_PRINT("info", ("datadir: %s", m_datadir));
-
   if (!init_nodeid())
     DBUG_RETURN(false);
 
@@ -184,6 +327,7 @@ ConfigManager::init(void)
     Config* conf = NULL;
     if (!(conf = load_saved_config(config_bin_name)))
       DBUG_RETURN(false);
+    g_eventLogger->info("Loaded config from '%s'", config_bin_name.c_str());
 
     if (!config_ok(conf))
       DBUG_RETURN(false);
@@ -193,19 +337,9 @@ ConfigManager::init(void)
 
     if (m_opts.mycnf || m_opts.config_filename)
     {
-      Config* new_conf = NULL;
-      if (m_opts.mycnf && (new_conf = load_init_mycnf()) == NULL)
-      {
-        g_eventLogger->error("Could not load configuration from 'my.cnf'");
+      Config* new_conf = load_config();
+      if (new_conf == NULL)
         DBUG_RETURN(false);
-      }
-      else if (m_opts.config_filename &&
-               (new_conf = load_init_config(m_opts.config_filename)) == NULL)
-      {
-        g_eventLogger->error("Could not load configuration from '%s'",
-                             m_opts.config_filename);
-        DBUG_RETURN(false);
-      }
 
       /* Copy the necessary values from old to new config */
       if (!new_conf->setGeneration(m_config->getGeneration()))
@@ -244,19 +378,9 @@ ConfigManager::init(void)
   {
     if (m_opts.mycnf || m_opts.config_filename)
     {
-      Config* conf = NULL;
-      if (m_opts.mycnf && (conf = load_init_mycnf()) == NULL)
-      {
-        g_eventLogger->error("Could not load configuration from 'my.cnf'");
+      Config* conf = load_config();
+      if (conf == NULL)
         DBUG_RETURN(false);
-      }
-      else if (m_opts.config_filename &&
-               (conf = load_init_config(m_opts.config_filename)) == NULL)
-      {
-        g_eventLogger->error("Could not load initial configuration from '%s'",
-                             m_opts.config_filename);
-        DBUG_RETURN(false);
-      }
 
       if (!config_ok(conf))
         DBUG_RETURN(false);
@@ -339,7 +463,7 @@ ConfigManager::prepareConfigChange(const
   m_config_name.assfmt("%s/ndb_%u_config.bin.%u",
                        m_datadir, m_node_id, generation);
   g_eventLogger->debug("Preparing configuration, generation: %d name: %s",
-                      m_config_name.c_str());
+                       generation, m_config_name.c_str());
 
   /* Check file name is free */
   if (access(m_config_name.c_str(), F_OK) == 0)
@@ -487,7 +611,7 @@ ConfigManager::config_ok(const Config* c
       // Using the builtin default --datadir
       g_eventLogger->error("The builtin data directory '%s' does "      \
                            "not match DataDir=%s specified in "         \
-                           "configuation. Either specify --datadir=%s " \
+                           "configuration. Either specify --datadir=%s " \
                            "on command line or remove the DataDir=%s "  \
                            "from configuration in order to use the "    \
                            "builtin default.",
@@ -1423,7 +1547,7 @@ ConfigManager::run()
 #include "InitConfigFileParser.hpp"
 
 Config*
-ConfigManager::load_init_config(const char* config_filename)
+ConfigManager::load_init_config(const char* config_filename) const
 {
    InitConfigFileParser parser;
    g_eventLogger->info("Reading cluster configuration from '%s'",
@@ -1433,7 +1557,7 @@ ConfigManager::load_init_config(const ch
 
 
 Config*
-ConfigManager::load_init_mycnf(void)
+ConfigManager::load_init_mycnf(void) const
 {
   InitConfigFileParser parser;
   g_eventLogger->info("Reading cluster configuration using my.cnf");
@@ -1442,6 +1566,26 @@ ConfigManager::load_init_mycnf(void)
 
 
 Config*
+ConfigManager::load_config(void) const
+{
+  Config* new_conf = NULL;
+  if (m_opts.mycnf && (new_conf = load_init_mycnf()) == NULL)
+  {
+    g_eventLogger->error("Could not load configuration from 'my.cnf'");
+    return NULL;
+  }
+  else if (m_opts.config_filename &&
+           (new_conf = load_init_config(m_opts.config_filename)) == NULL)
+  {
+    g_eventLogger->error("Could not load configuration from '%s'",
+                         m_opts.config_filename);
+    return NULL;
+  }
+  return new_conf;
+}
+
+
+Config*
 ConfigManager::fetch_config(void)
 {
   DBUG_ENTER("ConfigManager::fetch_config");
@@ -1479,8 +1623,6 @@ ConfigManager::fetch_config(void)
 }
 
 
-#include "DirIterator.hpp"
-
 bool
 ConfigManager::saved_config_exists(BaseString& config_name) const
 {
@@ -1531,7 +1673,6 @@ ConfigManager::load_saved_config(const B
     return NULL;
   }
 
-  g_eventLogger->info("Loaded config from '%s'", config_name.c_str());
   Config* conf = new Config(tmp);
   if (conf == NULL)
     g_eventLogger->error("Failed to load config, out of memory");

=== modified file 'storage/ndb/src/mgmsrv/ConfigManager.hpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.hpp	2008-10-21 12:41:59 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigManager.hpp	2008-11-06 10:54:21 +0000
@@ -72,13 +72,16 @@ class ConfigManager : public MgmtThread 
   const char* m_datadir;
 
   /* Functions used from 'init' */
-  Config* load_init_config(const char*);
-  Config* load_init_mycnf(void);
+  Config* load_init_config(const char*) const;
+  Config* load_init_mycnf(void) const;
+  Config* load_config(void) const;
   Config* fetch_config(void);
   bool save_config(const Config* conf);
   bool save_config(void);
   bool saved_config_exists(BaseString& config_name) const;
   Config* load_saved_config(const BaseString& config_name);
+  NodeId find_nodeid_from_datadir(void);
+  NodeId find_nodeid_from_config(void);
   bool init_nodeid(void);
 
   /* Set the new config and inform subscribers */
@@ -129,7 +132,8 @@ class ConfigManager : public MgmtThread 
   void sendConfigCheckConf(SignalSender& ss, BlockReference to) const;
 
 public:
-  ConfigManager(const MgmtSrvr::MgmtOpts&);
+  ConfigManager(const MgmtSrvr::MgmtOpts&,
+                const char* datadir);
   virtual ~ConfigManager();
   bool init();
   void set_facade(TransporterFacade* facade) { m_facade= facade; };

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-10-28 15:25:34 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-11-06 10:56:21 +0000
@@ -306,14 +306,86 @@ MgmtSrvr::MgmtSrvr(const MgmtOpts& opts,
 }
 
 
+static bool
+create_directory(const char* dir)
+{
+#ifdef __WIN__
+  if (CreateDirectory(dir, NULL) == 0)
+  {
+    g_eventLogger->warning("Failed to create directory '%s', error: %d",
+                           dir, GetLastError());
+    return false;
+  }
+#else
+  if (mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR ) != 0)
+  {
+    g_eventLogger->warning("Failed to create directory '%s', error: %d",
+                           dir, errno);
+    return false;
+  }
+#endif
+  return true;
+}
+
+
+/*
+  check_datadir
+
+  Make sure datadir exist and try to create it if not
+
+*/
+
+const char*
+MgmtSrvr::check_datadir() const
+{
+  if (m_opts.datadir)
+  {
+    // Specified on commmand line
+    if (access(m_opts.datadir, F_OK))
+    {
+      g_eventLogger->error("Directory '%s' specified with --datadir "   \
+                           "does not exist", m_opts.datadir);
+      return NULL;
+    }
+    return m_opts.datadir;
+  }
+  else
+  {
+    // Compiled in path MYSQLCLUSTERDIR
+    if (access(MYSQLCLUSTERDIR, F_OK))
+    {
+      g_eventLogger->info("The default data directory '%s' "            \
+                          "does not exist. Trying to create it...",
+                          MYSQLCLUSTERDIR);
+
+      if (!create_directory(MYSQLCLUSTERDIR) ||
+          access(MYSQLCLUSTERDIR, F_OK))
+      {
+        g_eventLogger->error("Could not create directory '%s'. "        \
+                             "Either create it manually or "            \
+                             "specify a different directory with "      \
+                             "--datadir=<path>",
+                             MYSQLCLUSTERDIR);
+        return NULL;
+      }
+
+      g_eventLogger->info("Sucessfully created data directory");
+    }
+    return MYSQLCLUSTERDIR;
+  }
+}
+
 
 bool
 MgmtSrvr::init()
 {
   DBUG_ENTER("MgmtSrvr::init");
 
+  const char* datadir;
+  if (!(datadir= check_datadir()))
+    DBUG_RETURN(false);
 
-  if (!(m_config_manager= new ConfigManager(m_opts)))
+  if (!(m_config_manager= new ConfigManager(m_opts, datadir)))
   {
     g_eventLogger->error("Failed to create ConfigManager");
     DBUG_RETURN(false);
@@ -610,6 +682,9 @@ MgmtSrvr::setClusterLog(const Config* co
 
   if (m_opts.non_interactive)
     g_eventLogger->createConsoleHandler();
+
+  if (m_opts.verbose)
+    g_eventLogger->enable(Logger::LL_DEBUG);
 }
 
 
@@ -3474,7 +3549,7 @@ bool MgmtSrvr::connect_to_self()
 
   buf.assfmt("%s:%u",
              m_opts.bind_address ? m_opts.bind_address : "localhost",
-             getPort());
+             m_port);
   ndb_mgm_set_connectstring(mgm_handle, buf.c_str());
 
   if(ndb_mgm_connect(mgm_handle, 0, 0, 0) < 0)
@@ -3720,6 +3795,89 @@ int MgmtSrvr::ndbinfo(Uint32 tableId, 
 }
 
 
+int
+MgmtSrvr::change_config(Config& new_config)
+{
+  SignalSender ss(theFacade);
+  ss.lock();
+
+  SimpleSignal ssig;
+  UtilBuffer buf;
+  new_config.pack(buf);
+  ssig.ptr[0].p = (Uint32*)buf.get_data();
+  ssig.ptr[0].sz = (buf.length() + 3) / 4;
+  ssig.header.m_noOfSections = 1;
+
+  ConfigChangeReq *req= CAST_PTR(ConfigChangeReq, ssig.getDataPtrSend());
+  req->length = buf.length();
+
+  NodeBitmask mgm_nodes;
+  ss.getNodes(mgm_nodes, NodeInfo::MGM);
+
+  NodeId nodeId= ss.find_confirmed_node(mgm_nodes);
+  if (nodeId == 0)
+    return -1; // Hrmpf?
+
+  if (ss.sendSignal(nodeId, ssig,
+                    MGM_CONFIG_MAN, GSN_CONFIG_CHANGE_REQ,
+                    ConfigChangeReq::SignalLength) != SEND_OK)
+    return SEND_OR_RECEIVE_FAILED;
+  mgm_nodes.clear(nodeId);
+
+  bool done = false;
+  while(!done)
+  {
+    SimpleSignal *signal= ss.waitFor();
+
+    switch(signal->readSignalNumber()){
+    case GSN_CONFIG_CHANGE_CONF:
+      done= true;
+      break;
+    case GSN_CONFIG_CHANGE_REF:
+    {
+      const ConfigChangeRef * const ref =
+        CAST_CONSTPTR(ConfigChangeRef, signal->getDataPtr());
+      g_eventLogger->debug("Got CONFIG_CHANGE_REF, error: %d", ref->errorCode);
+      switch(ref->errorCode)
+      {
+      case ConfigChangeRef::NotMaster:{
+        // Retry with next node if any
+        NodeId nodeId= ss.find_confirmed_node(mgm_nodes);
+        if (nodeId == 0)
+          return -1; // Hrmpf?
+
+        if (ss.sendSignal(nodeId, ssig,
+                          MGM_CONFIG_MAN, GSN_CONFIG_CHANGE_REQ,
+                          ConfigChangeReq::SignalLength) != SEND_OK)
+          return SEND_OR_RECEIVE_FAILED;
+        mgm_nodes.clear(nodeId);
+        break;
+      }
+
+      default:
+        return ref->errorCode;
+      }
+
+      break;
+    }
+
+    case GSN_API_REGCONF:
+      // Ignore;
+      break;
+
+    default:
+      report_unknown_signal(signal);
+      return SEND_OR_RECEIVE_FAILED;
+
+    }
+  }
+
+  g_eventLogger->info("Config change completed");
+
+  return 0;
+}
+
+
 template class MutexVector<NodeId>;
 template class MutexVector<Ndb_mgmd_event_service::Event_listener>;
 template class Vector<EventSubscribeReq>;

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2008-10-27 11:13:34 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2008-11-06 10:56:21 +0000
@@ -131,6 +131,7 @@ public:
     int no_nodeid_checks;
     int print_full_config;
     const char* datadir;
+    int verbose;
   };
 
   MgmtSrvr(); // Not implemented
@@ -139,6 +140,11 @@ public:
 
   ~MgmtSrvr();
 
+private:
+  /* Function used from 'init' */
+  const char* check_datadir() const;
+
+public:
   /*
     To be called after constructor.
   */
@@ -355,7 +361,9 @@ public:
                      SOCKET_SIZE_TYPE *client_addr_len,
 		     int &error_code, BaseString &error_string,
                      int log_event = 1);
-  
+
+  int change_config(Config& new_config);
+
   /**
    *
    */

=== modified file 'storage/ndb/src/mgmsrv/Services.cpp'
--- a/storage/ndb/src/mgmsrv/Services.cpp	2008-10-27 11:13:34 +0000
+++ b/storage/ndb/src/mgmsrv/Services.cpp	2008-11-06 10:56:21 +0000
@@ -2016,8 +2016,10 @@ void MgmApiSession::setConfig(Parser_t::
     }
     delete decoded;
 
-    //m_mgmsrv.setConfig(new Config(cvf.getConfigValues()));
-
+    int res;
+    Config new_config(cvf.getConfigValues());
+    if ((res= m_mgmsrv.change_config(new_config)) != 0)
+      result.assfmt("error: %d", res);
   }
 
 done:

=== modified file 'storage/ndb/src/mgmsrv/main.cpp'
--- a/storage/ndb/src/mgmsrv/main.cpp	2008-10-21 12:41:59 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp	2008-11-06 10:38:08 +0000
@@ -119,6 +119,10 @@ static struct my_option my_long_options[
     "Data directory for this node",
     (uchar**) &opts.datadir, (uchar**) &opts.datadir, 0,
     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+  { "verbose", 'v',
+    "Write more log messages",
+    (uchar**) &opts.verbose, (uchar**) &opts.verbose, 0,
+    GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -159,6 +163,9 @@ int main(int argc, char** argv)
   /* Output to console initially */
   g_eventLogger->createConsoleHandler();
 
+  if (opts.verbose)
+    g_eventLogger->enable(Logger::LL_DEBUG);
+
   if (opts.mycnf && opts.config_filename)
   {
     g_eventLogger->error("Both --mycnf and -f is not supported");

=== modified file 'storage/ndb/src/ndbapi/ClusterMgr.cpp'
--- a/storage/ndb/src/ndbapi/ClusterMgr.cpp	2008-10-21 12:41:59 +0000
+++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp	2008-11-06 12:00:21 +0000
@@ -14,7 +14,6 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #include <ndb_global.h>
-#include <my_pthread.h>
 #include <ndb_limits.h>
 #include <util/version.h>
 
@@ -54,19 +53,19 @@ extern "C" {
 }
 ClusterMgr::ClusterMgr(TransporterFacade & _facade):
   theStop(0),
-  theFacade(_facade)
+  theFacade(_facade),
+  m_connect_count(0),
+  m_max_api_reg_req_interval(~0),
+  noOfAliveNodes(0),
+  noOfConnectedNodes(0),
+  theClusterMgrThread(NULL),
+  waitingForHB(false),
+  m_cluster_state(CS_waiting_for_clean_cache)
 {
   DBUG_ENTER("ClusterMgr::ClusterMgr");
   ndbSetOwnVersion();
   clusterMgrThreadMutex = NdbMutex_Create();
   waitForHBCond= NdbCondition_Create();
-  waitingForHB= false;
-  m_max_api_reg_req_interval= 0xFFFFFFFF; // MAX_INT
-  noOfAliveNodes= 0;
-  noOfConnectedNodes= 0;
-  theClusterMgrThread= 0;
-  m_connect_count = 0;
-  m_cluster_state = CS_waiting_for_clean_cache;
   DBUG_VOID_RETURN;
 }
 
@@ -82,16 +81,13 @@ ClusterMgr::~ClusterMgr()
 void
 ClusterMgr::init(ndb_mgm_configuration_iterator & iter){
   for(iter.first(); iter.valid(); iter.next()){
-    Uint32 tmp = 0;
-    if(iter.get(CFG_NODE_ID, &tmp))
+    Uint32 nodeId = 0;
+    if(iter.get(CFG_NODE_ID, &nodeId))
       continue;
 
-    theNodes[tmp].defined = true;
-#if 0
-    ndbout << "--------------------------------------" << endl;
-    ndbout << "--------------------------------------" << endl;
-    ndbout_c("ClusterMgr: Node %d defined as %s", tmp, config.getNodeType(tmp));
-#endif
+    // Check array bounds + don't allow node 0 to be touched
+    assert(nodeId > 0 && nodeId < MAX_NODES);
+    theNodes[nodeId].defined = true;
 
     unsigned type;
     if(iter.get(CFG_TYPE_OF_SECTION, &type))
@@ -99,52 +95,57 @@ ClusterMgr::init(ndb_mgm_configuration_i
 
     switch(type){
     case NODE_TYPE_DB:
-      theNodes[tmp].m_info.m_type = NodeInfo::DB;
+      theNodes[nodeId].m_info.m_type = NodeInfo::DB;
       break;
     case NODE_TYPE_API:
-      theNodes[tmp].m_info.m_type = NodeInfo::API;
+      theNodes[nodeId].m_info.m_type = NodeInfo::API;
       break;
     case NODE_TYPE_MGM:
-      theNodes[tmp].m_info.m_type = NodeInfo::MGM;
+      theNodes[nodeId].m_info.m_type = NodeInfo::MGM;
       break;
     default:
       type = type;
-#if 0
-      ndbout_c("ClusterMgr: Unknown node type: %d", type);
-#endif
+      break;
     }
   }
+
+  /* Init own node info */
+  Node &node= theNodes[theFacade.ownId()];
+  assert(node.defined);
+  node.m_api_reg_conf= true;
+
+#if 0
+  print_nodes("init");
+#endif
+
 }
 
 void
 ClusterMgr::startThread() {
-  NdbMutex_Lock(clusterMgrThreadMutex);
-  
+  Guard g(clusterMgrThreadMutex);
+
   theStop = 0;
-  
   theClusterMgrThread = NdbThread_Create(runClusterMgr_C,
                                          (void**)this,
                                          32768,
                                          "ndb_clustermgr",
                                          NDB_THREAD_PRIO_LOW);
-  NdbMutex_Unlock(clusterMgrThreadMutex);
 }
 
 void
 ClusterMgr::doStop( ){
   DBUG_ENTER("ClusterMgr::doStop");
-  NdbMutex_Lock(clusterMgrThreadMutex);
-  if(theStop){
-    NdbMutex_Unlock(clusterMgrThreadMutex);
+  Guard g(clusterMgrThreadMutex);
+  if(theStop)
     DBUG_VOID_RETURN;
-  }
+
   void *status;
   theStop = 1;
   if (theClusterMgrThread) {
     NdbThread_WaitFor(theClusterMgrThread, &status);  
     NdbThread_Destroy(&theClusterMgrThread);
   }
-  NdbMutex_Unlock(clusterMgrThreadMutex);
+
   DBUG_VOID_RETURN;
 }
 
@@ -165,14 +166,14 @@ ClusterMgr::forceHB()
     NodeBitmask ndb_nodes;
     ndb_nodes.clear();
     waitForHBFromNodes.clear();
-    for(Uint32 i = 0; i < MAX_NDB_NODES; i++)
+    for(Uint32 i = 1; i < MAX_NDB_NODES; i++)
     {
-      if(!theNodes[i].defined)
+      const Node &node= getNodeInfo(i);
+      if(!node.defined)
         continue;
-      if(theNodes[i].m_info.m_type == NodeInfo::DB)
+      if(node.m_info.getType() == NodeInfo::DB)
       {
         ndb_nodes.set(i);
-        const ClusterMgr::Node &node= getNodeInfo(i);
         waitForHBFromNodes.bitOR(node.m_state.m_connected_nodes);
       }
     }
@@ -233,9 +234,13 @@ ClusterMgr::threadMain( ){
   NDB_TICKS now = NdbTick_CurrentMillisecond();
 
   while(!theStop){
-    /**
-     * Start of Secure area for use of Transporter
-     */
+
+    /* Sleep at least 100ms between each heartbet check */
+    NDB_TICKS before = now;
+    NdbSleep_MilliSleep(100);
+    now = NdbTick_CurrentMillisecond();
+    timeSlept = (now - before);
+
     if (m_cluster_state == CS_waiting_for_clean_cache &&
         theFacade.m_globalDictCache)
     {
@@ -243,17 +248,19 @@ ClusterMgr::threadMain( ){
       unsigned sz= theFacade.m_globalDictCache->get_size();
       theFacade.m_globalDictCache->unlock();
       if (sz)
-        goto next;
+        continue;
       m_cluster_state = CS_waiting_for_first_connect;
     }
 
     theFacade.lock_mutex();
-    for (int i = 1; i < MAX_NDB_NODES; i++){
+    for (int i = 1; i < MAX_NODES; i++){
       /**
        * Send register request (heartbeat) to all available nodes 
        * at specified timing intervals
        */
       const NodeId nodeId = i;
+      // Check array bounds + don't allow node 0 to be touched
+      assert(nodeId > 0 && nodeId < MAX_NODES);
       Node & theNode = theNodes[nodeId];
       
       if (!theNode.defined)
@@ -294,32 +301,10 @@ ClusterMgr::threadMain( ){
 	reportNodeFailed(i);
       }//if
     }
-    
-    /**
-     * End of secure area. Let other threads in
-     */
     theFacade.unlock_mutex();
-    
-next:
-    // Sleep for 100 ms between each Registration Heartbeat
-    NDB_TICKS before = now;
-    NdbSleep_MilliSleep(100); 
-    now = NdbTick_CurrentMillisecond();
-    timeSlept = (now - before);
   }
 }
 
-#if 0
-void
-ClusterMgr::showState(NodeId nodeId){
-  ndbout << "-- ClusterMgr - NodeId = " << nodeId << endl;
-  ndbout << "theNodeList      = " << theNodeList[nodeId] << endl;
-  ndbout << "theNodeState     = " << theNodeState[nodeId] << endl;
-  ndbout << "theNodeCount     = " << theNodeCount[nodeId] << endl;
-  ndbout << "theNodeStopDelay = " << theNodeStopDelay[nodeId] << endl;
-  ndbout << "theNodeSendDelay = " << theNodeSendDelay[nodeId] << endl;
-}
-#endif
 
 ClusterMgr::Node::Node()
   : m_state(NodeState::SL_NOTHING) { 
@@ -369,6 +354,10 @@ ClusterMgr::execAPI_REGREQ(const Uint32 
   conf->version = NDB_VERSION;
   conf->mysql_version = NDB_MYSQL_VERSION_D;
   conf->apiHeartbeatFrequency = node.hbFrequency;
+
+  conf->minDbVersion= 0;
+  conf->nodeState= node.m_state;
+
   if (theFacade.sendSignalUnCond(&signal, nodeId) == SEND_OK)
     node.m_api_reg_conf= true;
 }
@@ -382,7 +371,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32
   ndbout_c("ClusterMgr: Recd API_REGCONF from node %d", nodeId);
 #endif
 
-  assert(nodeId > 0 && nodeId < MAX_NDB_NODES);
+  assert(nodeId > 0 && nodeId < MAX_NODES);
   
   Node & node = theNodes[nodeId];
   assert(node.defined == true);
@@ -425,6 +414,15 @@ ClusterMgr::execAPI_REGCONF(const Uint32
   node.m_info.m_heartbeat_cnt = 0;
   node.hbCounter = 0;
 
+  check_wait_for_hb(nodeId);
+
+  node.hbFrequency = (apiRegConf->apiHeartbeatFrequency * 10) - 50;
+}
+
+
+void
+ClusterMgr::check_wait_for_hb(NodeId nodeId)
+{
   if(waitingForHB)
   {
     waitForHBFromNodes.clear(nodeId);
@@ -435,21 +433,24 @@ ClusterMgr::execAPI_REGCONF(const Uint32
       NdbCondition_Broadcast(waitForHBCond);
     }
   }
-  node.hbFrequency = (apiRegConf->apiHeartbeatFrequency * 10) - 50;
+  return;
 }
 
+
 void
 ClusterMgr::execAPI_REGREF(const Uint32 * theData){
   
   ApiRegRef * ref = (ApiRegRef*)theData;
   
   const NodeId nodeId = refToNode(ref->ref);
-  
-  assert(nodeId > 0 && nodeId < MAX_NDB_NODES);
-  
+
+  assert(nodeId > 0 && nodeId < MAX_NODES);
+
   Node & node = theNodes[nodeId];
   assert(node.connected == true);
   assert(node.defined == true);
+  /* Only DB nodes will send API_REGREF */
+  assert(node.m_info.getType() == NodeInfo::DB);
 
   node.compatible = false;
   set_node_alive(node, false);
@@ -465,15 +466,14 @@ ClusterMgr::execAPI_REGREF(const Uint32 
     break;
   }
 
-  waitForHBFromNodes.clear(nodeId);
-  if(waitForHBFromNodes.isclear())
-    NdbCondition_Signal(waitForHBCond);
+  check_wait_for_hb(nodeId);
 }
 
+
 void
 ClusterMgr::execNODE_FAILREP(const Uint32 * theData){
-  NodeFailRep * const nodeFail = (NodeFailRep *)&theData[0];
-  for(int i = 1; i<MAX_NDB_NODES; i++){
+  const NodeFailRep * const nodeFail = (NodeFailRep *)&theData[0];
+  for(int i = 1; i < MAX_NDB_NODES; i++){
     if(NdbNodeBitmask::get(nodeFail->theNodes, i)){
       reportNodeFailed(i);
     }
@@ -482,15 +482,16 @@ ClusterMgr::execNODE_FAILREP(const Uint3
 
 void
 ClusterMgr::execNF_COMPLETEREP(const Uint32 * theData){
-  NFCompleteRep * const nfComp = (NFCompleteRep *)theData;
+  const NFCompleteRep * const nfComp = (NFCompleteRep *)theData;
 
   const NodeId nodeId = nfComp->failedNodeId;
-  assert(nodeId > 0 && nodeId < MAX_NDB_NODES);
-  
-  if (theNodes[nodeId].nfCompleteRep == false)
+  assert(nodeId > 0 && nodeId < MAX_NODES);
+
+  Node & node = theNodes[nodeId];
+  if (node.nfCompleteRep == false)
   {
     theFacade.ReportNodeFailureComplete(nodeId);
-    theNodes[nodeId].nfCompleteRep = true;
+    node.nfCompleteRep = true;
   }
 }
 
@@ -503,7 +504,7 @@ ClusterMgr::reportConnected(NodeId nodeI
    * until we have got the first reply from NDB providing
    * us with the real time-out period to use.
    */
-  assert(nodeId > 0 && nodeId < MAX_NDB_NODES);
+  assert(nodeId > 0 && nodeId < MAX_NODES);
 
   noOfConnectedNodes++;
 
@@ -529,7 +530,7 @@ ClusterMgr::reportConnected(NodeId nodeI
 
 void
 ClusterMgr::reportDisconnected(NodeId nodeId){
-  assert(nodeId > 0 && nodeId < MAX_NDB_NODES);
+  assert(nodeId > 0 && nodeId < MAX_NODES);
   assert(noOfConnectedNodes > 0);
 
   noOfConnectedNodes--;
@@ -543,6 +544,8 @@ ClusterMgr::reportDisconnected(NodeId no
 void
 ClusterMgr::reportNodeFailed(NodeId nodeId, bool disconnect){
 
+  // Check array bounds + don't allow node 0 to be touched
+  assert(nodeId > 0 && nodeId < MAX_NODES);
   Node & theNode = theNodes[nodeId];
  
   set_node_alive(theNode, false);
@@ -574,7 +577,7 @@ ClusterMgr::reportNodeFailed(NodeId node
       m_cluster_state = CS_waiting_for_clean_cache;
     }
     NFCompleteRep rep;
-    for(Uint32 i = 1; i<MAX_NDB_NODES; i++){
+    for(Uint32 i = 1; i < MAX_NODES; i++){
       if(theNodes[i].defined && theNodes[i].nfCompleteRep == false){
 	rep.failedNodeId = i;
 	execNF_COMPLETEREP((Uint32*)&rep);
@@ -583,6 +586,32 @@ ClusterMgr::reportNodeFailed(NodeId node
   }
 }
 
+
+void
+ClusterMgr::print_nodes(const char* where, NdbOut& out)
+{
+  out << where << " >>" << endl;
+  for (NodeId n = 1; n < MAX_NODES ; n++)
+  {
+    const Node node = getNodeInfo(n);
+    if (!node.defined)
+      continue;
+    out << "node: " << n << endl;
+    out << " -";
+    out << " connected: " << node.connected;
+    out << ", compatible: " << node.compatible;
+    out << ", nf_complete_rep: " << node.nfCompleteRep;
+    out << ", alive: " << node.m_alive;
+    out << ", api_reg_conf: " << node.m_api_reg_conf;
+    out << endl;
+
+    out << " - " << node.m_info << endl;
+    out << " - " << node.m_state << endl;
+  }
+  out << "<<" << endl;
+}
+
+
 /******************************************************************************
  * Arbitrator
  ******************************************************************************/

=== modified file 'storage/ndb/src/ndbapi/ClusterMgr.hpp'
--- a/storage/ndb/src/ndbapi/ClusterMgr.hpp	2008-05-29 15:06:11 +0000
+++ b/storage/ndb/src/ndbapi/ClusterMgr.hpp	2008-11-06 12:00:21 +0000
@@ -49,7 +49,9 @@ public:
   void startThread();
 
   void forceHB();
-  void set_max_api_reg_req_interval(unsigned int millisec) { m_max_api_reg_req_interval = millisec; }
+  void set_max_api_reg_req_interval(unsigned int millisec) {
+    m_max_api_reg_req_interval = millisec;
+  }
 
 private:
   void threadMain();
@@ -104,8 +106,7 @@ private:
    * Used for controlling start/stop of the thread
    */
   NdbMutex*     clusterMgrThreadMutex;
-  
-  void showState(NodeId nodeId);
+
   void reportNodeFailed(NodeId nodeId, bool disconnect = false);
   
   /**
@@ -117,7 +118,14 @@ private:
   void execNODE_FAILREP  (const Uint32 * theData);
   void execNF_COMPLETEREP(const Uint32 * theData);
 
+  void check_wait_for_hb(NodeId nodeId);
+
   inline void set_node_alive(Node& node, bool alive){
+
+    // Only DB nodes can be "alive"
+    assert(!alive ||
+           (alive && node.m_info.getType() == NodeInfo::DB));
+
     if(node.m_alive && !alive)
     {
       assert(noOfAliveNodes);
@@ -129,11 +137,15 @@ private:
     }
     node.m_alive = alive;
   }
+
+  void print_nodes(const char* where, NdbOut& out = ndbout);
 };
 
 inline
 const ClusterMgr::Node &
 ClusterMgr::getNodeInfo(NodeId nodeId) const {
+  // Check array bounds
+  assert(nodeId >= 0 && nodeId < MAX_NODES);
   return theNodes[nodeId];
 }
 
@@ -151,6 +163,8 @@ ClusterMgr::isClusterAlive() const {
 inline
 void
 ClusterMgr::hb_received(NodeId nodeId) {
+  // Check array bounds + don't allow node 0 to be touched
+  assert(nodeId > 0 && nodeId < MAX_NODES);
   theNodes[nodeId].m_info.m_heartbeat_cnt= 0;
 }
 

=== modified file 'storage/ndb/src/ndbapi/SignalSender.cpp'
--- a/storage/ndb/src/ndbapi/SignalSender.cpp	2008-10-27 11:13:34 +0000
+++ b/storage/ndb/src/ndbapi/SignalSender.cpp	2008-11-06 10:56:21 +0000
@@ -143,7 +143,7 @@ SignalSender::getNodes(NodeBitmask& mask
                        NodeInfo::NodeType type)
 {
   mask.clear();
-  for(Uint32 i = 0; i < MAX_NODES; i++)
+  for(Uint32 i = 1; i < MAX_NODES; i++)
   {
     const ClusterMgr::Node& node= getNodeInfo(i);
     if(!node.defined)
@@ -327,16 +327,94 @@ SignalSender::execNodeStatus(void* signa
     rep->masterNodeId = 0;
     rep->noOfNodes = 1;
     NdbNodeBitmask::clear(rep->theNodes);
-    NdbNodeBitmask::set(rep->theNodes,nodeId);
+
+    // Mark ndb nodes as failed in bitmask
+    const ClusterMgr::Node node= ss->getNodeInfo(nodeId);
+    if (node.m_info.getType() ==  NodeInfo::DB)
+      NdbNodeBitmask::set(rep->theNodes, nodeId);
   }
 
   ss->m_jobBuffer.push_back(s);
   NdbCondition_Signal(ss->m_cond);
 }
 
+
+template<class T>
+NodeId
+SignalSender::find_node(const NodeBitmask& mask, T & t)
+{
+  unsigned n= 0;
+  do {
+     n= mask.find(n+1);
+
+     if (n == NodeBitmask::NotFound)
+       return 0;
+
+    assert(n < MAX_NODES);
+
+  } while (!t.found_ok(*this, getNodeInfo(n)));
+
+  return n;
+}
+
+
+class FindConfirmedNode {
+public:
+  bool found_ok(const SignalSender& ss, const ClusterMgr::Node & node){
+    return node.m_api_reg_conf;
+  }
+};
+
+
+NodeId
+SignalSender::find_confirmed_node(const NodeBitmask& mask)
+{
+  FindConfirmedNode f;
+  return find_node(mask, f);
+}
+
+
+class FindConnectedNode {
+public:
+  bool found_ok(const SignalSender& ss, const ClusterMgr::Node & node){
+    return node.connected;
+  }
+};
+
+
+NodeId
+SignalSender::find_connected_node(const NodeBitmask& mask)
+{
+  FindConnectedNode f;
+  return find_node(mask, f);
+}
+
+
+class FindAliveNode {
+public:
+  bool found_ok(const SignalSender& ss, const ClusterMgr::Node & node){
+    return node.m_alive;
+  }
+};
+
+
+NodeId
+SignalSender::find_alive_node(const NodeBitmask& mask)
+{
+  FindAliveNode f;
+  return find_node(mask, f);
+}
+
+
 #if __SUNPRO_CC != 0x560
 template SimpleSignal* SignalSender::waitFor<WaitForNode>(unsigned, WaitForNode&);
 template SimpleSignal* SignalSender::waitFor<WaitForAny>(unsigned, WaitForAny&);
+template NodeId SignalSender::find_node<FindConfirmedNode>(const NodeBitmask&,
+                                                           FindConfirmedNode&);
+template NodeId SignalSender::find_node<FindAliveNode>(const NodeBitmask&,
+                                                       FindAliveNode&);
+template NodeId SignalSender::find_node<FindConnectedNode>(const NodeBitmask&,
+                                                           FindConnectedNode&);
 #endif
 template class Vector<SimpleSignal*>;
   

=== modified file 'storage/ndb/src/ndbapi/SignalSender.hpp'
--- a/storage/ndb/src/ndbapi/SignalSender.hpp	2008-10-24 12:51:04 +0000
+++ b/storage/ndb/src/ndbapi/SignalSender.hpp	2008-11-06 10:56:21 +0000
@@ -61,6 +61,10 @@ public:
   void getNodes(NodeBitmask& mask,
                 NodeInfo::NodeType type = NodeInfo::INVALID);
 
+  NodeId find_confirmed_node(const NodeBitmask& mask);
+  NodeId find_connected_node(const NodeBitmask& mask);
+  NodeId find_alive_node(const NodeBitmask& mask);
+
   SendStatus sendSignal(Uint16 nodeId, const SimpleSignal *);
   SendStatus sendSignal(Uint16 nodeId, SimpleSignal& sig,
                         Uint16 recBlock, Uint16 gsn, Uint32 len);
@@ -93,6 +97,9 @@ private:
 
   template<class T>
   SimpleSignal * waitFor(Uint32 timeOutMillis, T & t);
+
+  template<class T>
+  NodeId find_node(const NodeBitmask& mask, T & t);
 };
 
 #endif

=== modified file 'storage/ndb/src/ndbapi/TransporterFacade.cpp'
--- a/storage/ndb/src/ndbapi/TransporterFacade.cpp	2008-11-06 10:17:49 +0000
+++ b/storage/ndb/src/ndbapi/TransporterFacade.cpp	2008-11-06 13:52:28 +0000
@@ -1659,14 +1659,14 @@ TransporterFacade::get_an_alive_node()
 #endif
   NodeId i;
   for (i = theStartNodeId; i < MAX_NDB_NODES; i++) {
-    if (getIsDbNode(i) && get_node_alive(i)){
+    if (get_node_alive(i)){
       DBUG_PRINT("info", ("Node %d is alive", i));
       theStartNodeId = ((i + 1) % MAX_NDB_NODES);
       DBUG_RETURN(i);
     }
   }
   for (i = 1; i < theStartNodeId; i++) {
-    if (getIsDbNode(i) && get_node_alive(i)){
+    if (get_node_alive(i)){
       DBUG_PRINT("info", ("Node %d is alive", i));
       theStartNodeId = ((i + 1) % MAX_NDB_NODES);
       DBUG_RETURN(i);

=== modified file 'storage/ndb/src/ndbapi/TransporterFacade.hpp'
--- a/storage/ndb/src/ndbapi/TransporterFacade.hpp	2008-10-27 17:56:57 +0000
+++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp	2008-11-04 08:43:06 +0000
@@ -381,7 +381,6 @@ TransporterFacade::getNodeGrp(NodeId n) 
 inline
 bool
 TransporterFacade::get_node_alive(NodeId n) const {
-
   const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n);
   return node.m_alive;
 }
@@ -396,9 +395,10 @@ inline
 bool
 TransporterFacade::get_node_stopping(NodeId n) const {
   const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n);
+  assert(node.m_info.getType() == NodeInfo::DB);
   return (!node.m_state.getSingleUserMode() &&
-          (node.m_state.startLevel == NodeState::SL_STOPPING_1) ||
-          (node.m_state.startLevel == NodeState::SL_STOPPING_2));
+          ((node.m_state.startLevel == NodeState::SL_STOPPING_1) ||
+           (node.m_state.startLevel == NodeState::SL_STOPPING_2)));
 }
 
 inline
@@ -406,18 +406,11 @@ bool
 TransporterFacade::getIsNodeSendable(NodeId n) const {
   const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n);
   const Uint32 startLevel = node.m_state.startLevel;
+  assert(node.m_info.getType() == NodeInfo::DB);
 
-  if (node.m_info.m_type == NodeInfo::DB) {
-    return node.compatible && (startLevel == NodeState::SL_STARTED ||
-                               startLevel == NodeState::SL_STOPPING_1 ||
-                               node.m_state.getSingleUserMode());
-  } else {
-    ndbout_c("TransporterFacade::getIsNodeSendable: Illegal node type: "
-             "%d of node: %d", 
-             node.m_info.m_type, n);
-    abort();
-    return false; // to remove compiler warning
-  }
+  return node.compatible && (startLevel == NodeState::SL_STARTED ||
+                             startLevel == NodeState::SL_STOPPING_1 ||
+                             node.m_state.getSingleUserMode());
 }
 
 inline

=== modified file 'storage/ndb/test/include/NdbMgmd.hpp'
--- a/storage/ndb/test/include/NdbMgmd.hpp	2008-09-12 09:09:01 +0000
+++ b/storage/ndb/test/include/NdbMgmd.hpp	2008-11-05 08:03:07 +0000
@@ -38,13 +38,11 @@ class NdbMgmd {
   }
 public:
   NdbMgmd() :
-    m_connect_str(getenv("NDB_CONNECTSTRING")),
     m_handle(NULL)
     {
-      if (!m_connect_str.length()){
-        fprintf(stderr, "Could not init NdbConnectString");
-        abort();
-      }
+      const char* connect_string= getenv("NDB_CONNECTSTRING");
+      if (connect_string)
+        m_connect_str.assign(connect_string);
     }
 
   ~NdbMgmd()

Thread
bzr push into mysql-5.1 branch (msvensson:3046) Magnus Svensson6 Nov