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 Svensson | 17 Dec |