List:Commits« Previous MessageNext Message »
From:Magnus Svensson Date:December 17 2008 4:19pm
Subject:bzr push into mysql-5.1 branch (msvensson:3176 to 3178)
View as plain text  
 3178 Magnus Svensson	2008-12-17 [merge]
      Merge
modified:
  storage/ndb/include/kernel/signaldata/ConfigChange.hpp
  storage/ndb/src/mgmapi/mgmapi.cpp
  storage/ndb/src/mgmsrv/Config.cpp
  storage/ndb/src/mgmsrv/Config.hpp
  storage/ndb/src/mgmsrv/ConfigManager.cpp
  storage/ndb/src/mgmsrv/ConfigManager.hpp
  storage/ndb/src/mgmsrv/MgmtSrvr.cpp
  storage/ndb/test/include/NdbMgmd.hpp
  storage/ndb/test/ndbapi/testMgm.cpp

 3177 Magnus Svensson	2008-12-17
      ndb - Remove unused function in ndb_mgmd
modified:
  storage/ndb/src/mgmsrv/Services.cpp

 3176 Magnus Svensson	2008-12-17 [merge]
      Merge
removed:
  mysql-test/suite/funcs_1/t/ndb_storedproc.test
modified:
  mysql-test/suite/funcs_1/t/disabled.def
  storage/ndb/src/mgmclient/CommandInterpreter.cpp
  storage/ndb/src/mgmsrv/MgmtSrvr.cpp
  storage/ndb/src/mgmsrv/MgmtSrvr.hpp
  storage/ndb/src/ndbapi/ClusterMgr.cpp
  storage/ndb/src/ndbapi/ClusterMgr.hpp
  storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
  storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
  storage/ndb/src/ndbapi/Ndbif.cpp
  storage/ndb/test/ndbapi/testBasic.cpp
  storage/ndb/test/ndbapi/testSingleUserMode.cpp
  storage/ndb/test/run-test/autotest-boot.sh
  storage/ndb/test/run-test/daily-basic-tests.txt
  storage/ndb/test/run-test/db.cpp

=== modified file 'storage/ndb/include/kernel/signaldata/ConfigChange.hpp'
--- a/storage/ndb/include/kernel/signaldata/ConfigChange.hpp	2008-12-16 11:53:18 +0000
+++ b/storage/ndb/include/kernel/signaldata/ConfigChange.hpp	2008-12-17 16:09:24 +0000
@@ -74,38 +74,55 @@ class ConfigChangeRef {
     ConfigChangeOnGoing     = 1,
     NotMaster               = 2,
     NoConfigData            = 3,
-    ConfigChangeAborted     = 4,
-    FailedToStart           = 5,
-    SetGenerationFailed     = 10,
-    PrepareFailed           = 11,
-    IllegalConfigChange     = 13,
-    FailedToUnpack          = 14,
-    InvalidGeneration       = 15,
-    InvalidConfigName       = 16,
-    IllegalState            = 17,
-    IllegalInitialGeneration = 18,
-    DifferentInitial        = 19,
-    NotAllStarted           = 20,
-    NotPrimaryMgmNode       = 21
-  } ;
+    ConfigNotOk             = 4,
+    InternalError           = 5,
+    PrepareFailed           = 6,
+    IllegalConfigChange     = 7,
+    FailedToUnpack          = 8,
+    InvalidGeneration       = 9,
+    InvalidConfigName       = 10,
+    IllegalInitialState     = 11,
+    IllegalInitialGeneration = 12,
+    DifferentInitial        = 13,
+    NotAllStarted           = 14,
+    NotPrimaryMgmNode       = 15
+  };
 
 public:
   STATIC_CONST( SignalLength = 1 );
 
   static const char* errorMessage(Uint32 error) {
     switch (error){
+    case ConfigChangeOnGoing:
+      return "Config change ongoing";
+    case NotMaster:
+      return "Not the config change master";
     case NoConfigData:
       return "No config data in signal";
-    case ConfigChangeAborted:
-      return "Config change was aborted";
-    case FailedToStart:
-      return "Failed to start config change";
-    case SetGenerationFailed:
-      return "setGeneration failed";
+    case ConfigNotOk:
+      return "Config is not ok";
+    case InternalError:
+      return "ConfigChangeRef, internal error";
+    case PrepareFailed:
+      return "Prepare of config change failed";
+    case IllegalConfigChange:
+      return "Illegal configuration change";
     case FailedToUnpack:
       return "Failed to unpack the configuration";
-    case IllegalConfigChange:
-      return "Illegal config change";
+    case InvalidGeneration:
+      return "Invalid generation in configuration";
+    case InvalidConfigName:
+      return "Invalid configuration name in configuration";
+    case IllegalInitialState:
+      return "Initial config change not allowed in this state";
+    case IllegalInitialGeneration:
+      return "Initial config change with generation not 0";
+    case DifferentInitial:
+      return "Different initial config files";
+    case NotAllStarted:
+      return " Not all mgm nodes are started";
+    case NotPrimaryMgmNode:
+      return "Not primary mgm node for configuration";
 
     default:
       return "ConfigChangeRef, unknown error";
@@ -138,6 +155,7 @@ private:
   Uint32 requestType;
   Uint32 initial; // Valid when requestType = Prepare
   Uint32 length; // Length of the config data in long signal
+
 };
 
 

=== modified file 'storage/ndb/include/mgmapi/mgmapi_error.h'
--- a/storage/ndb/include/mgmapi/mgmapi_error.h	2008-03-28 08:03:06 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi_error.h	2008-12-16 16:27:47 +0000
@@ -72,6 +72,10 @@ extern "C" {
     /** Unable to exit single user mode */
     NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE = 4002,
 
+    /* Service errors - Configuration change */
+    /** Unable to start config change */
+    NDB_MGM_CONFIG_CHANGE_FAILED = 4011,
+
     /* Usage errors */
     /** Usage error */
     NDB_MGM_USAGE_ERROR = 5001
@@ -109,6 +113,10 @@ extern "C" {
     { NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE,
       "Could not exit single user mode" },
 
+    /* Service errors - Configuration change */
+    { NDB_MGM_CONFIG_CHANGE_FAILED,
+      "Failed to complete configuration change" },
+
     /* Usage errors */
     { NDB_MGM_USAGE_ERROR,
       "Usage error" }

=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp	2008-12-16 02:28:02 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp	2008-12-17 16:18:23 +0000
@@ -3094,6 +3094,10 @@ extern "C"
 int
 ndb_mgm_set_configuration(NdbMgmHandle h, ndb_mgm_configuration *c)
 {
+  CHECK_HANDLE(h, 0);
+  SET_ERROR(h, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_set_configuration");
+  CHECK_CONNECTED(h, 0);
+
   const ConfigValues * cfg = (ConfigValues*)c;
 
   UtilBuffer buf;
@@ -3129,7 +3133,7 @@ ndb_mgm_set_configuration(NdbMgmHandle h
   delete reply;
 
   if(strcmp(result.c_str(), "Ok") != 0) {
-    fprintf(h->errstream, "ERROR Message: %s\n", result.c_str());
+    SET_ERROR(h, NDB_MGM_CONFIG_CHANGE_FAILED, result.c_str());
     return -1;
   }
 

=== modified file 'storage/ndb/src/mgmsrv/Config.cpp'
--- a/storage/ndb/src/mgmsrv/Config.cpp	2008-12-16 14:09:42 +0000
+++ b/storage/ndb/src/mgmsrv/Config.cpp	2008-12-17 16:18:23 +0000
@@ -233,6 +233,27 @@ Config::pack(UtilBuffer& buf) const
 }
 
 
+#include <base64.h>
+
+bool
+Config::pack64(BaseString& encoded) const
+{
+  UtilBuffer buf;
+  if (m_configValues->m_config.pack(buf) == 0)
+    return false;
+
+  // Expand the string to correct length by filling with Z
+  encoded.assfmt("%*s",
+                 base64_needed_encoded_length(buf.length()),
+                 "Z");
+
+  if (base64_encode(buf.get_data(),
+                    buf.length(),
+                    (char*)encoded.c_str()))
+    return false;
+  return true;
+}
+
 
 enum diff_types {
   DT_DIFF,            // Value differed
@@ -725,3 +746,34 @@ bool Config::illegal_change(const Config
   return illegal_change(diff_list);
 }
 
+
+void Config::getConnectString(BaseString& connectstring,
+                              const BaseString& separator) const
+{
+  bool first= true;
+  ConfigIter it(this, CFG_SECTION_NODE);
+
+  for(;it.valid(); it.next())
+  {
+    /* Get type of Node */
+    Uint32 nodeType;
+    require(it.get(CFG_TYPE_OF_SECTION, &nodeType) == 0);
+
+    if (nodeType != NODE_TYPE_MGM)
+      continue;
+
+    Uint32 port;
+    const char* hostname;
+    require(it.get(CFG_NODE_HOST, &hostname) == 0);
+    require(it.get(CFG_MGM_PORT, &port) == 0);
+
+    if (!first)
+      connectstring.append(separator);
+    first= false;
+
+    connectstring.appfmt("%s:%d", hostname, port);
+
+  }
+  ndbout << connectstring << endl;
+}
+

=== modified file 'storage/ndb/src/mgmsrv/Config.hpp'
--- a/storage/ndb/src/mgmsrv/Config.hpp	2008-12-16 11:53:18 +0000
+++ b/storage/ndb/src/mgmsrv/Config.hpp	2008-12-16 16:30:58 +0000
@@ -73,6 +73,11 @@ public:
   Uint32 pack(UtilBuffer&) const;
 
   /*
+    Pack the config as base64
+  */
+  bool pack64(BaseString&) const;
+
+  /*
     Compare against another config and return a list of
     differences in a Properties object
   */
@@ -84,6 +89,15 @@ public:
    */
   void print_diff(const Config* other) const;
 
+
+  /*
+    Get the full connectstring for this configuration. ie
+    a list of all the mgmd servers and their port separated
+    by separator.
+   */
+  void getConnectString(BaseString&,
+                        const BaseString& separator = BaseString(";")) const;
+
   /*
     Print the difference to string buffer
   */
@@ -100,6 +114,7 @@ public:
   bool equal(const Config*, const unsigned* exclude = NULL) const;
 
   struct ndb_mgm_configuration * m_configValues;
+  struct ndb_mgm_configuration * values(void) const { return m_configValues; };
 
 private:
   bool setValue(Uint32 section, Uint32 section_no,

=== modified file 'storage/ndb/src/mgmsrv/ConfigManager.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.cpp	2008-12-16 14:30:25 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigManager.cpp	2008-12-17 16:09:24 +0000
@@ -56,6 +56,7 @@ ConfigManager::ConfigManager(const MgmtS
   m_config_change_state(CCS_IDLE),
   m_config_state(CS_UNINITIALIZED),
   m_previous_state(CS_UNINITIALIZED),
+  m_config_change_error(ConfigChangeRef::OK),
   m_client_ref(RNIL),
   m_prepared_config(NULL),
   m_node_id(0),
@@ -324,6 +325,9 @@ ConfigManager::init(void)
   if (m_opts.initial && !delete_saved_configs())
     DBUG_RETURN(false);
 
+  if (failed_config_change_exists())
+    DBUG_RETURN(false);
+
   BaseString config_bin_name;
   if (saved_config_exists(config_bin_name))
   {
@@ -719,7 +723,8 @@ ConfigManager::execCONFIG_CHANGE_IMPL_RE
         g_eventLogger->warning("Refusing to start initial "             \
                                "configuration change since this node "  \
                                "is not in INITIAL state");
-        sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::IllegalState);
+        sendConfigChangeImplRef(ss, nodeId,
+                                ConfigChangeRef::IllegalInitialState);
         return;
       }
 
@@ -766,14 +771,16 @@ ConfigManager::execCONFIG_CHANGE_IMPL_RE
     else
     {
 
-      // Check that config change was started by primary mgm node
-      Uint32 primaryMgmNode = m_config->getPrimaryMgmNode();
-      if (nodeId != primaryMgmNode)
+      // Check that new config has same primary mgm node as current
+      Uint32 curr_primary = m_config->getPrimaryMgmNode();
+      Uint32 new_primary = new_config.getPrimaryMgmNode();
+      if (new_primary != curr_primary)
       {
         g_eventLogger->warning("Refusing to start configuration change " \
-                               "requested by node %d, it's not set as " \
-                               "the primary management node %d.",
-                               nodeId, primaryMgmNode);
+                               "requested by node %d, the new config uses " \
+                               "different primary mgm node %d. "      \
+                               "Current primary mmgm node is %d.",
+                               nodeId, new_primary, curr_primary);
         sendConfigChangeImplRef(ss, nodeId,
                                 ConfigChangeRef::NotPrimaryMgmNode);
         return;
@@ -814,7 +821,7 @@ ConfigManager::execCONFIG_CHANGE_IMPL_RE
     {
       g_eventLogger->error("Failed to set new generation to %d",
                            new_generation);
-      sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::SetGenerationFailed);
+      sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::InternalError);
       return;
     }
 
@@ -871,6 +878,10 @@ ConfigManager::execCONFIG_CHANGE_IMPL_RE
   g_eventLogger->warning("Node %d refused configuration change, error: %d",
                          nodeId, ref->errorCode);
 
+  /* Remember the original error code */
+  if (m_config_change_error == 0)
+    m_config_change_error = (ConfigChangeRef::ErrorCode)ref->errorCode;
+
   switch(m_config_change_state){
 
   case CCS_PREPARING:{
@@ -987,6 +998,7 @@ ConfigManager::execCONFIG_CHANGE_IMPL_CO
       return;
 
     require(m_client_ref != RNIL);
+    require(m_config_change_error == 0);
     if (m_client_ref == ss.getOwnRef())
     {
       g_eventLogger->info("Config change completed! New generation: %d",
@@ -1032,6 +1044,7 @@ ConfigManager::execCONFIG_CHANGE_IMPL_CO
       return;
 
     require(m_client_ref != RNIL);
+    require(m_config_change_error);
     if (m_client_ref == ss.getOwnRef())
     {
       g_eventLogger->error("Config change failed!");
@@ -1041,8 +1054,9 @@ ConfigManager::execCONFIG_CHANGE_IMPL_CO
     {
       /* Send ref to the requestor */
       sendConfigChangeRef(ss, m_client_ref,
-                          ConfigChangeRef::ConfigChangeAborted);
+                          m_config_change_error);
     }
+    m_config_change_error= ConfigChangeRef::OK;
     m_client_ref = RNIL;
     m_config_change_state = CCS_IDLE;
     break;
@@ -1171,6 +1185,7 @@ ConfigManager::execCONFIG_CHANGE_REQ(Sig
     sendConfigChangeRef(ss, from, ConfigChangeRef::ConfigChangeOnGoing);
     return;
   }
+  require(m_config_change_error == ConfigChangeRef::OK);
 
   if (sig->header.m_noOfSections != 1)
   {
@@ -1190,7 +1205,7 @@ ConfigManager::execCONFIG_CHANGE_REQ(Sig
   {
     g_eventLogger->warning("Refusing to start config change, the config "\
                            "is not ok");
-    sendConfigChangeRef(ss, from, ConfigChangeRef::FailedToUnpack);
+    sendConfigChangeRef(ss, from, ConfigChangeRef::ConfigNotOk);
     return;
   }
 
@@ -1691,8 +1706,8 @@ ConfigManager::delete_saved_configs(void
   const char* name;
   unsigned nodeid;
   char extra; // Avoid matching ndb_2_config.bin.2.tmp
-  unsigned version, max_version= 0;
   BaseString full_name;
+  unsigned version;
   while ((name= iter.next_file()) != NULL)
   {
     if (sscanf(name,
@@ -1758,6 +1773,47 @@ ConfigManager::saved_config_exists(BaseS
 }
 
 
+
+bool
+ConfigManager::failed_config_change_exists() const
+{
+  DirIterator iter;
+
+  if (iter.open(m_configdir) != 0)
+    return false;
+
+  const char* name;
+  char tmp;
+  unsigned nodeid;
+  unsigned version;
+  while ((name= iter.next_file()) != NULL)
+  {
+    // Check for a previously failed config
+    // change, ie. ndb_<nodeid>_config.bin.X.tmp exist
+    if (sscanf(name,
+               "ndb_%u_config.bin.%u.tm%c",
+               &nodeid, &version, &tmp) == 3 &&
+        tmp == 'p')
+    {
+      if (nodeid != m_node_id)
+        continue;
+
+      g_eventLogger->error("Found binary configuration file '%s%s%s' from "
+                           "previous failed attempt to change config. This "
+                           "error must be manually resolved by removing the "
+                           "file(ie. ROLLBACK) or renaming the file to it's "
+                           "name without the .tmp extension(ie COMMIT). Make "
+                           "sure to check the other nodes so that they all "
+                           "have the same configuration generation.",
+                           m_configdir, DIR_SEPARATOR, name);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
 Config*
 ConfigManager::load_saved_config(const BaseString& config_name)
 {

=== modified file 'storage/ndb/src/mgmsrv/ConfigManager.hpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.hpp	2008-12-16 14:30:25 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigManager.hpp	2008-12-17 16:09:24 +0000
@@ -58,6 +58,9 @@ class ConfigManager : public MgmtThread 
   ConfigState m_config_state;
   ConfigState m_previous_state;
 
+  /* The original error that caused config change to be aborted */
+  ConfigChangeRef::ErrorCode m_config_change_error;
+
   BlockReference m_client_ref;
   BaseString m_config_name;
   Config* m_prepared_config;
@@ -80,6 +83,7 @@ class ConfigManager : public MgmtThread 
   bool save_config(void);
   bool saved_config_exists(BaseString& config_name) const;
   bool delete_saved_configs(void) const;
+  bool failed_config_change_exists(void) const;
   Config* load_saved_config(const BaseString& config_name);
   NodeId find_nodeid_from_configdir(void);
   NodeId find_nodeid_from_config(void);

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-12-17 08:06:47 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-12-17 16:18:23 +0000
@@ -3844,8 +3844,8 @@ int MgmtSrvr::ndbinfo(Uint32 tableId, 
 }
 
 
-int
-MgmtSrvr::change_config(Config& new_config)
+bool
+MgmtSrvr::change_config(Config& new_config, BaseString& msg)
 {
   SignalSender ss(theFacade);
   ss.lock();
@@ -3865,12 +3865,19 @@ MgmtSrvr::change_config(Config& new_conf
 
   NodeId nodeId= ss.find_confirmed_node(mgm_nodes);
   if (nodeId == 0)
-    return -1; // Hrmpf?
+  {
+    msg = "INTERNAL ERROR Could not find any mgmd!";
+    return false;
+  }
 
   if (ss.sendSignal(nodeId, ssig,
                     MGM_CONFIG_MAN, GSN_CONFIG_CHANGE_REQ,
                     ConfigChangeReq::SignalLength) != SEND_OK)
-    return SEND_OR_RECEIVE_FAILED;
+  {
+    msg.assfmt("Could not start configuration change, send to "
+               "node %d failed", nodeId);
+    return false;
+  }
   mgm_nodes.clear(nodeId);
 
   bool done = false;
@@ -3893,18 +3900,26 @@ MgmtSrvr::change_config(Config& new_conf
         // Retry with next node if any
         NodeId nodeId= ss.find_confirmed_node(mgm_nodes);
         if (nodeId == 0)
-          return -1; // Hrmpf?
+        {
+          msg = "INTERNAL ERROR Could not find any mgmd!";
+          return false;
+        }
 
         if (ss.sendSignal(nodeId, ssig,
                           MGM_CONFIG_MAN, GSN_CONFIG_CHANGE_REQ,
                           ConfigChangeReq::SignalLength) != SEND_OK)
-          return SEND_OR_RECEIVE_FAILED;
+        {
+          msg.assfmt("Could not start configuration change, send to "
+                     "node %d failed", nodeId);
+          return false;
+        }
         mgm_nodes.clear(nodeId);
         break;
       }
 
       default:
-        return ref->errorCode;
+        msg = ConfigChangeRef::errorMessage(ref->errorCode);
+        return false;
       }
 
       break;
@@ -3917,7 +3932,7 @@ MgmtSrvr::change_config(Config& new_conf
 
     default:
       report_unknown_signal(signal);
-      return SEND_OR_RECEIVE_FAILED;
+      return false;
 
     }
   }
@@ -4009,13 +4024,8 @@ MgmtSrvr::reload_config(const char* conf
     }
   }
 
-  int res;
-  if ((res= change_config(new_conf)) != 0)
-  {
-    msg.assfmt("error: %d", res);
+  if (!change_config(new_conf, msg))
     return false;
-  }
-
   return true;
 }
 

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2008-12-17 08:06:47 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp	2008-12-17 15:40:11 +0000
@@ -363,7 +363,7 @@ public:
 		     int &error_code, BaseString &error_string,
                      int log_event = 1);
 
-  int change_config(Config& new_config);
+  bool change_config(Config& new_config, BaseString& msg);
 
   /**
    *

=== modified file 'storage/ndb/src/mgmsrv/Services.cpp'
--- a/storage/ndb/src/mgmsrv/Services.cpp	2008-12-16 14:09:42 +0000
+++ b/storage/ndb/src/mgmsrv/Services.cpp	2008-12-17 16:09:53 +0000
@@ -448,52 +448,6 @@ MgmApiSession::runSession()
   DBUG_VOID_RETURN;
 }
 
-static Properties *
-backward(const char * base, const Properties* reply){
-  Properties * ret = new Properties();
-  Properties::Iterator it(reply);
-  for(const char * name = it.first(); name != 0; name=it.next()){
-    PropertiesType type;
-    reply->getTypeOf(name, &type);
-    switch(type){
-    case PropertiesType_Uint32:{
-      Uint32 val;
-      reply->get(name, &val);
-      ret->put(name, val);
-    }
-      break;
-    case PropertiesType_char:
-      {
-	const char * val;
-	reply->get(name, &val);
-	ret->put(name, val);
-	if(!strcmp(name, "Type") && !strcmp(val, "DB")){
-	  ret->put("NoOfDiskBufferPages", (unsigned)0);
-	  ret->put("NoOfDiskFiles", (unsigned)0);
-	  ret->put("NoOfDiskClusters", (unsigned)0);
-	  ret->put("NoOfFreeDiskClusters", (unsigned)0);
-	  ret->put("NoOfDiskClustersPerDiskFile", (unsigned)0);
-	  ret->put("NoOfConcurrentCheckpointsDuringRestart", (unsigned)1);
-	  ret->put("NoOfConcurrentCheckpointsAfterRestart", (unsigned)1);
-	  ret->put("NoOfConcurrentProcessesHandleTakeover", (unsigned)1);
-	}
-      }
-      break;
-    case PropertiesType_Properties:
-      {
-	const Properties * recurse;
-	reply->get(name, &recurse);
-	Properties * val = backward(name, recurse);
-	ret->put(name, val);
-      }
-      break;
-    case PropertiesType_Uint64:
-      break;
-    }
-  }
-  return ret;
-}
-
 void
 MgmApiSession::get_nodeid(Parser_t::Context &,
 			  const class Properties &args)
@@ -2030,10 +1984,8 @@ void MgmApiSession::setConfig(Parser_t::
     }
     delete decoded;
 
-    int res;
     Config new_config(cvf.getConfigValues());
-    if ((res= m_mgmsrv.change_config(new_config)) != 0)
-      result.assfmt("error: %d", res);
+    (void)m_mgmsrv.change_config(new_config, result);
   }
 
 done:

=== modified file 'storage/ndb/test/include/NdbMgmd.hpp'
--- a/storage/ndb/test/include/NdbMgmd.hpp	2008-11-19 13:42:48 +0000
+++ b/storage/ndb/test/include/NdbMgmd.hpp	2008-12-17 16:09:24 +0000
@@ -30,8 +30,13 @@
 class NdbMgmd {
   BaseString m_connect_str;
   NdbMgmHandle m_handle;
+  Uint32 m_nodeid;
+  bool m_verbose;
   void error(const char* msg, ...) ATTRIBUTE_FORMAT(printf, 2, 3)
   {
+    if (!m_verbose)
+      return;
+
     va_list args;
     printf("NdbMgmd::");
     va_start(args, msg);
@@ -48,7 +53,7 @@ class NdbMgmd {
   }
 public:
   NdbMgmd() :
-    m_handle(NULL)
+    m_handle(NULL), m_nodeid(0), m_verbose(true)
     {
       const char* connect_string= getenv("NDB_CONNECTSTRING");
       if (connect_string)
@@ -69,14 +74,28 @@ public:
     return m_connect_str.c_str();
   }
 
-  bool connect(void) {
+  void verbose(bool yes = true){
+    m_verbose= yes;
+  }
+
+  int last_error(void) const {
+    return ndb_mgm_get_latest_error(m_handle);
+  }
+
+  const char* last_error_message(void) const {
+    return ndb_mgm_get_latest_error_desc(m_handle);
+  }
+
+  bool connect(const char* connect_string = NULL) {
     m_handle= ndb_mgm_create_handle();
     if (!m_handle){
       error("connect: ndb_mgm_create_handle failed");
       return false;
     }
 
-    if (ndb_mgm_set_connectstring(m_handle, getConnectString()) != 0){
+    if (ndb_mgm_set_connectstring(m_handle,
+                                  connect_string ?
+                                  connect_string : getConnectString()) != 0){
       error("connect: ndb_mgm_set_connectstring failed");
       return false;
     }
@@ -85,6 +104,12 @@ public:
       error("connect: ndb_mgm_connect failed");
       return false;
     }
+
+    if ((m_nodeid = ndb_mgm_get_mgmd_nodeid(m_handle)) == 0){
+      error("connect: could not get nodeid of connected mgmd");
+      return false;
+    }
+
     return true;
   }
 
@@ -100,8 +125,34 @@ public:
     return true;
   }
 
+  bool restart(bool abort = false) {
+    if (!is_connected()){
+      error("restart: not connected");
+      return false;
+    }
+
+    int disconnect= 0;
+    int node_list= m_nodeid;
+    int restarted= ndb_mgm_restart3(m_handle,
+                                    1,
+                                    &node_list,
+                                    false, /* initial */
+                                    false, /* nostart */
+                                    abort,
+                                    &disconnect);
+
+    if (restarted != 1){
+      error("restart: failed to restart node %d, restarted: %d",
+            m_nodeid, restarted);
+      return false;
+    }
+    return true;
+  }
+
   bool call(const char* cmd, const Properties& args,
-            const char* cmd_reply, Properties& reply){
+            const char* cmd_reply, Properties& reply,
+            const char* bulk = NULL,
+            bool name_value_pairs = true){
 
     if (!is_connected()){
       error("call: not connected");
@@ -153,46 +204,68 @@ public:
 	break;
       }
     }
+
+    // Emtpy line terminates argument list
     if (out.print("\n")){
       error("call: print('\n') failed at line %d", __LINE__);
       return false;
     }
 
+    // Send any bulk data
+    if (bulk && out.println(bulk)){
+      error("call: print('<bulk>') failed at line %d", __LINE__);
+      return false;
+    }
 
-    // Read the reply
     BaseString buf;
     SocketInputStream2 in(_ndb_mgm_get_socket(m_handle));
-    if (!in.gets(buf)){
-      error("call: could not read reply command");
-      return false;
-    }
+    if (cmd_reply)
+    {
+      // Read the reply header and compare against "cmd_reply"
+      if (!in.gets(buf)){
+        error("call: could not read reply command");
+        return false;
+      }
 
-    // 1. Check correct reply header
-    if (buf != cmd_reply){
-      error("call: unexpected reply command, expected: '%s', got '%s'",
-            cmd_reply, buf.c_str());
-      return false;
+      // 1. Check correct reply header
+      if (buf != cmd_reply){
+        error("call: unexpected reply command, expected: '%s', got '%s'",
+              cmd_reply, buf.c_str());
+        return false;
+      }
     }
 
-    // 2. Read colon separated name value pairs until empty line
+    // 2. Read lines until empty line
+    int line = 1;
     while(in.gets(buf)){
 
       // empty line -> end of reply
       if (buf == "")
         return true;
 
-      // Split the name value pair on first ':'
-      Vector<BaseString> name_value_pair;
-      if (buf.split(name_value_pair, ":", 2) != 2){
-        error("call: illegal name value pair '%s' received", buf.c_str());
-        return false;
-      }
+      if (name_value_pairs)
+      {
+        // 3a. Read colon separated name value pair, split
+        // the name value pair on first ':'
+        Vector<BaseString> name_value_pair;
+        if (buf.split(name_value_pair, ":", 2) != 2){
+          error("call: illegal name value pair '%s' received", buf.c_str());
+          return false;
+        }
 
-      reply.put(name_value_pair[0].trim(" ").c_str(),
-                name_value_pair[1].trim(" ").c_str());
+        reply.put(name_value_pair[0].trim(" ").c_str(),
+                  name_value_pair[1].trim(" ").c_str());
+      }
+      else
+      {
+        // 3b. Not name value pair, save the line into "reply"
+        // using unique key
+        reply.put("line", line++, buf.c_str());
+      }
     }
 
     error("call: should never come here");
+    reply.print();
     abort();
     return false;
   }
@@ -216,6 +289,22 @@ public:
     return true;
   }
 
+  bool set_config(Config& config){
+
+    if (!is_connected()){
+      error("set_config: not connected");
+      return false;
+    }
+
+    if (ndb_mgm_set_configuration(m_handle,
+                                  config.values()) != 0)
+    {
+      error("set_config: ndb_mgm_set_configuration failed");
+      return false;
+    }
+    return true;
+  }
+
   bool end_session(void){
     if (!is_connected()){
       error("end_session: not connected");

=== modified file 'storage/ndb/test/ndbapi/testMgm.cpp'
--- a/storage/ndb/test/ndbapi/testMgm.cpp	2008-12-17 08:06:47 +0000
+++ b/storage/ndb/test/ndbapi/testMgm.cpp	2008-12-17 16:18:23 +0000
@@ -681,7 +681,6 @@ int runSetConfigUntilStopped(NDBT_Contex
   while(!ctx->isTestStopped() &&
         (result= runSetConfig(ctx, step)) == NDBT_OK)
     ;
-  ctx->stopTest();
   return result;
 }
 
@@ -712,7 +711,6 @@ int runGetConfigUntilStopped(NDBT_Contex
   while(!ctx->isTestStopped() &&
         (result= runGetConfig(ctx, step)) == NDBT_OK)
     ;
-  ctx->stopTest();
   return result;
 }
 
@@ -917,7 +915,6 @@ int runTestStatusUntilStopped(NDBT_Conte
   while(!ctx->isTestStopped() &&
         (result= runTestStatus(ctx, step)) == NDBT_OK)
     ;
-  ctx->stopTest();
   return result;
 }
 
@@ -1240,7 +1237,6 @@ int runTestGetNodeIdUntilStopped(NDBT_Co
   while(!ctx->isTestStopped() &&
         (result= runTestGetNodeId(ctx, step)) == NDBT_OK)
     ;
-  ctx->stopTest();
   return result;
 }
 
@@ -1256,6 +1252,598 @@ int runSleepAndStop(NDBT_Context* ctx, N
 }
 
 
+static bool
+get_version(NdbMgmd& mgmd,
+            Properties& reply)
+{
+  Properties args;
+  if (!mgmd.call("get version", args,
+                 "version", reply))
+  {
+    g_err << "get_version: mgmd.call failed" << endl;
+    return false;
+  }
+
+  //reply.print();
+  return true;
+}
+
+int runTestGetVersion(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbMgmd mgmd;
+
+  if (!mgmd.connect())
+    return NDBT_FAILED;
+
+  Properties reply;
+  if (!get_version(mgmd, reply))
+   return NDBT_FAILED;
+
+  return NDBT_OK;
+}
+
+int runTestGetVersionUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result= NDBT_OK;
+  while(!ctx->isTestStopped() &&
+        (result= runTestGetVersion(ctx, step)) == NDBT_OK)
+    ;
+  return result;
+}
+
+static bool
+show_config(NdbMgmd& mgmd,
+            const Properties& args,
+            Properties& reply)
+{
+  if (!mgmd.call("show config", args,
+                 "show config reply", reply, NULL, false))
+  {
+    g_err << "show_config: mgmd.call failed" << endl;
+    return false;
+  }
+
+  // reply.print();
+  return true;
+}
+
+
+int runCheckConfig(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbMgmd mgmd;
+
+  // Connect to any mgmd and get the config
+  if (!mgmd.connect())
+    return NDBT_FAILED;
+
+  Properties args1;
+  Properties config1;
+  if (!show_config(mgmd, args1, config1))
+    return NDBT_FAILED;
+
+  // Get the binary config
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return NDBT_FAILED;
+
+  // Extract list of connectstrings to each mgmd
+  BaseString connectstring;
+  conf.getConnectString(connectstring, ";");
+
+  Vector<BaseString> mgmds;
+  connectstring.split(mgmds, ";");
+
+  // Connect to each mgmd and check
+  // they all have the same config
+  for (size_t i = 0; i < mgmds.size(); i++)
+  {
+    NdbMgmd mgmd2;
+    g_info << "Connecting to " << mgmds[i].c_str() << endl;
+    if (!mgmd2.connect(mgmds[i].c_str()))
+      return NDBT_FAILED;
+
+    Properties args2;
+    Properties config2;
+    if (!show_config(mgmd, args2, config2))
+      return NDBT_FAILED;
+
+    // Compare config1 and config2 line by line
+    Uint32 line = 1;
+    const char* value1;
+    const char* value2;
+    while (true)
+    {
+      if (config1.get("line", line, &value1))
+      {
+        // config1 had line, so should config2
+        if (config2.get("line", line, &value2))
+        {
+          // both configs had line, check they are equal
+          if (strcmp(value1, value2) != 0)
+          {
+            g_err << "the value on line " << line << "didn't match!" << endl;
+            g_err << "config1, value: " << value1 << endl;
+            g_err << "config2, value: " << value2 << endl;
+            return NDBT_FAILED;
+          }
+          // g_info << line << ": " << value1 << " = " << value2 << endl;
+        }
+        else
+        {
+          g_err << "config2 didn't have line " << line << "!" << endl;
+          return NDBT_FAILED;
+        }
+      }
+      else
+      {
+        // Make sure config2 does not have this line either and end loop
+        if (config2.get("line", line, &value2))
+        {
+          g_err << "config2 had line " << line << " not in config1!" << endl;
+          return NDBT_FAILED;
+        }
+
+        // End of loop
+        g_info << "There was " << line << " lines in config" << endl;
+        break;
+      }
+      line++;
+    }
+    if (line == 0)
+    {
+      g_err << "FAIL: config should have lines!" << endl;
+      return NDBT_FAILED;
+    }
+
+    // Compare the binary config
+    Config conf2;
+    if (!mgmd.get_config(conf2))
+      return NDBT_FAILED;
+
+    if (!conf.equal(&conf2))
+    {
+      g_err << "The binary config was different! host: " << mgmds[i] << endl;
+      return NDBT_FAILED;
+    }
+
+  }
+
+  return NDBT_OK;
+}
+
+
+static bool
+reload_config(NdbMgmd& mgmd,
+              const Properties& args,
+              Properties& reply)
+{
+  if (!mgmd.call("reload config", args,
+                 "reload config reply", reply))
+  {
+    g_err << "reload config: mgmd.call failed" << endl;
+    return false;
+  }
+
+  //reply.print();
+  return true;
+}
+
+
+static bool reload_config_result_contains(NdbMgmd& mgmd,
+                                          const Properties& args,
+                                          const char* expected_result)
+{
+  Properties reply;
+  if (!reload_config(mgmd, args, reply))
+    return false;
+  return result_contains(reply, expected_result);
+}
+
+
+static bool
+check_reload_config_both_config_and_mycnf(NdbMgmd& mgmd)
+{
+  Properties args;
+  // Send reload command with both config_filename and mycnf set
+  args.put("config_filename", "some filename");
+  args.put("mycnf", 1);
+  return reload_config_result_contains(mgmd, args,
+                                       "ERROR: Both mycnf and config_filename");
+}
+
+static bool
+check_reload_config_invalid_config_filename(NdbMgmd& mgmd)
+{
+  Properties args;
+  // Send reload command with an invalid config_filename
+  args.put("config_filename", "nonexisting_file");
+  return reload_config_result_contains(mgmd, args,
+                                       "Could not load configuration "
+                                       "from 'nonexisting_file");
+}
+
+
+int runTestReloadConfig(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbMgmd mgmd;
+
+  if (!mgmd.connect())
+    return NDBT_FAILED;
+
+  int result= NDBT_FAILED;
+  if (
+      check_reload_config_both_config_and_mycnf(mgmd) &&
+      check_reload_config_invalid_config_filename(mgmd) &&
+      true)
+    result= NDBT_OK;
+
+  if (!mgmd.end_session())
+    result= NDBT_FAILED;
+
+  return result;
+}
+
+
+static bool
+set_config(NdbMgmd& mgmd,
+           const Properties& args,
+           BaseString encoded_config,
+           Properties& reply)
+{
+
+  // Fill in default values of other args
+  Properties call_args(args);
+  if (!call_args.contains("Content-Type"))
+    call_args.put("Content-Type", "ndbconfig/octet-stream");
+  if (!call_args.contains("Content-Transfer-Encoding"))
+    call_args.put("Content-Transfer-Encoding", "base64");
+  if (!call_args.contains("Content-Length"))
+    call_args.put("Content-Length",
+                  encoded_config.length() ? encoded_config.length() - 1 : 1);
+
+  if (!mgmd.call("set config", call_args,
+                 "set config reply", reply,
+                 encoded_config.c_str()))
+  {
+    g_err << "set config: mgmd.call failed" << endl;
+    return false;
+  }
+
+  //reply.print();
+  return true;
+}
+
+
+static bool set_config_result_contains(NdbMgmd& mgmd,
+                                       const Properties& args,
+                                       const BaseString& encoded_config,
+                                       const char* expected_result)
+{
+  Properties reply;
+  if (!set_config(mgmd, args, encoded_config, reply))
+    return false;
+  return result_contains(reply, expected_result);
+}
+
+
+static bool set_config_result_contains(NdbMgmd& mgmd,
+                                       const Config& conf,
+                                       const char* expected_result)
+{
+  Properties reply;
+  Properties args;
+
+  BaseString encoded_config;
+  if (!conf.pack64(encoded_config))
+    return false;
+
+  if (!set_config(mgmd, args, encoded_config, reply))
+    return false;
+  return result_contains(reply, expected_result);
+}
+
+
+static bool
+check_set_config_invalid_content_type(NdbMgmd& mgmd)
+{
+  Properties args;
+  args.put("Content-Type", "illegal type");
+  return set_config_result_contains(mgmd, args, BaseString(""),
+                                    "Unhandled content type 'illegal type'");
+}
+
+static bool
+check_set_config_invalid_content_encoding(NdbMgmd& mgmd)
+{
+  Properties args;
+  args.put("Content-Transfer-Encoding", "illegal encoding");
+  return set_config_result_contains(mgmd, args, BaseString(""),
+                                    "Unhandled content encoding "
+                                    "'illegal encoding'");
+}
+
+static bool
+check_set_config_too_large_content_length(NdbMgmd& mgmd)
+{
+  Properties args;
+  args.put("Content-Length", 1024*1024 + 1);
+  return set_config_result_contains(mgmd, args, BaseString(""),
+                                    "Illegal config length size 1048577");
+}
+
+static bool
+check_set_config_too_small_content_length(NdbMgmd& mgmd)
+{
+  Properties args;
+  args.put("Content-Length", (Uint32)0);
+  return set_config_result_contains(mgmd, args, BaseString(""),
+                                    "Illegal config length size 0");
+}
+
+static bool
+check_set_config_wrong_config_length(NdbMgmd& mgmd)
+{
+
+  // Get the binary config
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  BaseString encoded_config;
+  if (!conf.pack64(encoded_config))
+    return false;
+
+  Properties args;
+  args.put("Content-Length", encoded_config.length() - 20);
+  bool res = set_config_result_contains(mgmd, args, encoded_config,
+                                        "Failed to unpack config");
+
+  if (res){
+    /*
+      There are now additional 20 bytes of junk that has been
+      sent to  mgmd, send a new line and read the result to get rid of it
+    */
+    Properties args, reply;
+    if (!mgmd.call("", args,
+                   NULL, reply))
+      return false;
+  }
+  return res;
+}
+
+static bool
+check_set_config_any_node(NDBT_Context* ctx, NDBT_Step* step, NdbMgmd& mgmd)
+{
+
+  // Get the binary config
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  // Extract list of connectstrings to each mgmd
+  BaseString connectstring;
+  conf.getConnectString(connectstring, ";");
+
+  Vector<BaseString> mgmds;
+  connectstring.split(mgmds, ";");
+
+  // Connect to each mgmd and check
+  // they all have the same config
+  for (size_t i = 0; i < mgmds.size(); i++)
+  {
+    NdbMgmd mgmd2;
+    g_info << "Connecting to " << mgmds[i].c_str() << endl;
+    if (!mgmd2.connect(mgmds[i].c_str()))
+      return false;
+
+    // Get the binary config
+    Config conf2;
+    if (!mgmd2.get_config(conf2))
+      return false;
+
+#if 0
+    // Change one value in the config
+    if (!conf2.setValue(CFG_SECTION_NODE, 0,
+                        CFG_NODE_ARBIT_DELAY,
+#endif
+
+    // Set the modified config
+    if (!mgmd2.set_config(conf2))
+      return false;
+
+    // Check that all mgmds now have the new config
+    if (runCheckConfig(ctx, step) != NDBT_OK)
+      return false;
+
+  }
+
+  return true;
+}
+
+static bool
+check_set_config_fail_wrong_generation(NdbMgmd& mgmd)
+{
+  // Get the binary config
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  // Change generation
+  if (!conf.setGeneration(conf.getGeneration() + 10))
+    return false;
+
+  // Set the modified config
+  return set_config_result_contains(mgmd, conf,
+                                    "Invalid generation in");
+}
+
+static bool
+check_set_config_fail_wrong_name(NdbMgmd& mgmd)
+{
+  // Get the binary config
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  // Change name
+  if (!conf.setName("NEWNAME"))
+    return false;
+
+  // Set the modified config
+  return set_config_result_contains(mgmd, conf,
+                                    "Invalid configuration name");
+}
+
+static bool
+check_set_config_fail_wrong_primary(NdbMgmd& mgmd)
+{
+  // Get the binary config
+  Config conf;
+  if (!mgmd.get_config(conf))
+    return false;
+
+  // Change primary and thus make this configuration invalid
+  if (!conf.setPrimaryMgmNode(conf.getPrimaryMgmNode()+10))
+    return false;
+
+  // Set the modified config
+  return set_config_result_contains(mgmd, conf,
+                                    "Not primary mgm node");
+}
+
+int runTestSetConfig(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbMgmd mgmd;
+
+  if (!mgmd.connect())
+    return NDBT_FAILED;
+
+  int result= NDBT_FAILED;
+  if (
+      check_set_config_invalid_content_type(mgmd) &&
+      check_set_config_invalid_content_encoding(mgmd) &&
+      check_set_config_too_large_content_length(mgmd) &&
+      check_set_config_too_small_content_length(mgmd) &&
+      check_set_config_wrong_config_length(mgmd) &&
+      check_set_config_any_node(ctx, step, mgmd) &&
+      check_set_config_fail_wrong_generation(mgmd) &&
+      check_set_config_fail_wrong_name(mgmd) &&
+      check_set_config_fail_wrong_primary(mgmd) &&
+      true)
+    result= NDBT_OK;
+
+  if (!mgmd.end_session())
+    result= NDBT_FAILED;
+
+  return result;
+}
+
+int runTestSetConfigParallel(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbMgmd mgmd;
+
+  if (!mgmd.connect())
+    return NDBT_FAILED;
+
+  int result = NDBT_OK;
+  int loops = ctx->getNumLoops();
+  int sucessful = 0;
+
+  int invalid_generation = 0, config_change_ongoing = 0;
+
+  /*
+    continue looping until "loops" number of successful
+    changes have been made from this thread
+  */
+  while (sucessful < loops &&
+         !ctx->isTestStopped() &&
+         result == NDBT_OK)
+  {
+    // Get the binary config
+    Config conf;
+    if (!mgmd.get_config(conf))
+      return NDBT_FAILED;
+
+    /* Set the config and check for valid errors */
+    mgmd.verbose(false);
+    if (mgmd.set_config(conf))
+    {
+      /* Config change suceeded */
+      sucessful++;
+    }
+    else
+    {
+      /* Config change failed */
+      if (mgmd.last_error() != NDB_MGM_CONFIG_CHANGE_FAILED)
+      {
+        g_err << "Config change failed with unexpected error: "
+              << mgmd.last_error() << endl;
+        result = NDBT_FAILED;
+        continue;
+      }
+
+      BaseString error(mgmd.last_error_message());
+      if (error == "Invalid generation in configuration")
+        invalid_generation++;
+      else
+      if (error == "Config change ongoing")
+        config_change_ongoing++;
+      else
+      {
+        g_err << "Config change failed with unexpected error: '"
+              << error << "'" << endl;
+        result = NDBT_FAILED;
+
+      }
+    }
+  }
+
+  ndbout << "Thread " << step->getStepNo()
+         << ", sucess: " << sucessful
+         << ", ongoing: " << config_change_ongoing
+         << ", invalid_generation: " << invalid_generation << endl;
+  return result;
+}
+
+int runTestSetConfigParallelUntilStopped(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result= NDBT_OK;
+  while(!ctx->isTestStopped() &&
+        (result= runTestSetConfigParallel(ctx, step)) == NDBT_OK)
+    ;
+  return result;
+}
+
+
+#ifdef NOT_YET
+static bool
+check_restart_connected(NdbMgmd& mgmd)
+{
+  if (!mgmd.restart())
+    return false;
+  return true;
+ }
+
+int runTestRestartMgmd(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbMgmd mgmd;
+
+  if (!mgmd.connect())
+    return NDBT_FAILED;
+
+  int result= NDBT_FAILED;
+  if (
+      check_restart_connected(mgmd) &&
+      true)
+    result= NDBT_OK;
+
+  if (!mgmd.end_session())
+    result= NDBT_FAILED;
+
+  return result;
+}
+#endif
+
 
 NDBT_TESTSUITE(testMgm);
 DRIVER(DummyDriver); /* turn off use of NdbApi */
@@ -1297,7 +1885,22 @@ TESTCASE("ApiMgmStructEventTimeout",
 TESTCASE("SetConfig",
 	 "Tests the ndb_mgm_set_configuration function"){
   INITIALIZER(runSetConfig);
-
+}
+TESTCASE("CheckConfig",
+	 "Connect to each ndb_mgmd and check they have the same configuration"){
+  INITIALIZER(runCheckConfig);
+}
+TESTCASE("TestReloadConfig",
+	 "Test of 'reload config'"){
+  INITIALIZER(runTestReloadConfig);
+}
+TESTCASE("TestSetConfig",
+	 "Test of 'set config'"){
+  INITIALIZER(runTestSetConfig);
+}
+TESTCASE("TestSetConfigParallel",
+	 "Test of 'set config' from 5 threads"){
+  STEPS(runTestSetConfigParallel, 5);
 }
 TESTCASE("GetConfig", "Run ndb_mgm_get_configuration in parallel"){
   STEPS(runGetConfig, 100);
@@ -1322,14 +1925,34 @@ TESTCASE("TestStatus200",
 TESTCASE("TestGetNodeId",
 	 "Test 'get nodeid'"){
   INITIALIZER(runTestGetNodeId);
+}
 
+TESTCASE("TestGetVersion",
+	 "Test 'get version'"){
+  INITIALIZER(runTestGetVersion);
+}
+#ifdef NOT_YET
+TESTCASE("TestRestartMgmd",
+        "Test restart of ndb_mgmd(s)"){
+  INITIALIZER(runTestRestartMgmd);
 }
+#endif
 TESTCASE("Stress",
 	 "Run everything while changing config"){
   STEP(runTestGetNodeIdUntilStopped);
   STEP(runSetConfigUntilStopped);
   STEPS(runGetConfigUntilStopped, 10);
   STEPS(runTestStatusUntilStopped, 10);
+//  STEPS(runTestGetVersionUntilStopped, 5);
+  STEP(runSleepAndStop);
+}
+TESTCASE("Stress2",
+	 "Run everything while changing config in parallel"){
+  STEP(runTestGetNodeIdUntilStopped);
+  STEPS(runTestSetConfigParallelUntilStopped, 5);
+  STEPS(runGetConfigUntilStopped, 10);
+  STEPS(runTestStatusUntilStopped, 10);
+//  STEPS(runTestGetVersionUntilStopped, 5);
   STEP(runSleepAndStop);
 }
 NDBT_TESTSUITE_END(testMgm);

Thread
bzr push into mysql-5.1 branch (msvensson:3176 to 3178) Magnus Svensson17 Dec