#At file:///home/msvensson/mysql/6.4/ based on revid:msvensson@stripped
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
=== modified file 'storage/ndb/include/kernel/signaldata/ConfigChange.hpp'
--- a/storage/ndb/include/kernel/signaldata/ConfigChange.hpp 2008-12-16 16:27:47 +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,
- ConfigNotOk = 5,
-
- InternalError = 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 FailedToUnpack:
- return "Failed to unpack the configuration";
- case IllegalConfigChange:
- return "Illegal config change";
-
+ 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 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/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp 2008-12-16 16:41:33 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp 2008-12-17 16:18:23 +0000
@@ -3133,7 +3133,6 @@ 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 16:27:47 +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),
@@ -722,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;
}
@@ -769,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;
@@ -874,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:{
@@ -990,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",
@@ -1035,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!");
@@ -1044,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;
@@ -1174,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)
{
=== modified file 'storage/ndb/src/mgmsrv/ConfigManager.hpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.hpp 2008-12-16 15:53:28 +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;
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-12-17 15:40:11 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-12-17 16:18:23 +0000
@@ -3932,7 +3932,7 @@ MgmtSrvr::change_config(Config& new_conf
default:
report_unknown_signal(signal);
- return SEND_OR_RECEIVE_FAILED;
+ return false;
}
}
=== 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 commit into mysql-5.1 branch (msvensson:3178) | Magnus Svensson | 17 Dec |