1467 lines
44 KiB
C++
1467 lines
44 KiB
C++
/*
|
|
Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <NDBT.hpp>
|
|
#include <NDBT_Test.hpp>
|
|
#include <portlib/NdbDir.hpp>
|
|
#include "ConfigFactory.hpp"
|
|
#include <NdbMgmd.hpp>
|
|
#include <NdbProcess.hpp>
|
|
#include <NDBT_Find.hpp>
|
|
#include <NDBT_Workingdir.hpp>
|
|
#include <NdbEnv.h>
|
|
|
|
static const char * exe_valgrind = 0;
|
|
static const char * arg_valgrind = 0;
|
|
|
|
static bool file_exists(const char* path, Uint32 timeout = 1)
|
|
{
|
|
g_info << "File '" << path << "' ";
|
|
/**
|
|
* ndb_mgmd does currently not fsync the directory
|
|
* after committing config-bin,
|
|
* which means that it can be on disk, wo/ being visible
|
|
* remedy this by retrying some
|
|
*/
|
|
for (Uint32 i = 0; i < 10 * timeout; i++)
|
|
{
|
|
if (access(path, F_OK) == 0)
|
|
{
|
|
g_info << "exists" << endl;
|
|
return true;
|
|
}
|
|
if (i == 0)
|
|
{
|
|
g_info << "does not exist, retrying...";
|
|
}
|
|
NdbSleep_MilliSleep(100);
|
|
}
|
|
g_info << "does not exist" << endl;
|
|
return false;
|
|
}
|
|
|
|
// Util function that concatenate strings to form a path
|
|
|
|
static BaseString path(const char* first, ...)
|
|
{
|
|
BaseString path;
|
|
path.assign(first);
|
|
|
|
const char* str;
|
|
va_list args;
|
|
va_start(args, first);
|
|
while ((str = va_arg(args, const char*)) != NULL)
|
|
{
|
|
path.appfmt("%s%s", DIR_SEPARATOR, str);
|
|
}
|
|
va_end(args);
|
|
return path;
|
|
}
|
|
|
|
class Mgmd
|
|
{
|
|
NdbProcess* m_proc;
|
|
int m_nodeid;
|
|
BaseString m_name;
|
|
BaseString m_exe;
|
|
NdbMgmd m_mgmd_client;
|
|
|
|
Mgmd(const Mgmd& other); // Not implemented
|
|
public:
|
|
|
|
Mgmd(int nodeid) :
|
|
m_proc(NULL),
|
|
m_nodeid(nodeid)
|
|
{
|
|
m_name.assfmt("ndb_mgmd_%d", nodeid);
|
|
|
|
NDBT_find_ndb_mgmd(m_exe);
|
|
}
|
|
|
|
~Mgmd()
|
|
{
|
|
if (m_proc)
|
|
{
|
|
//stop the proces
|
|
stop();
|
|
}
|
|
|
|
}
|
|
|
|
const char* name(void) const
|
|
{
|
|
return m_name.c_str();
|
|
}
|
|
|
|
const char* exe(void) const
|
|
{
|
|
return m_exe.c_str();
|
|
}
|
|
|
|
bool start(const char* working_dir, NdbProcess::Args& args)
|
|
{
|
|
g_info << "Starting " << name() << " ";
|
|
for (unsigned i = 0; i < args.args().size(); i++)
|
|
g_info << args.args()[i].c_str() << " ";
|
|
g_info << endl;
|
|
|
|
if (exe_valgrind == 0)
|
|
{
|
|
m_proc = NdbProcess::create(name(),
|
|
exe(),
|
|
working_dir,
|
|
args);
|
|
}
|
|
else
|
|
{
|
|
NdbProcess::Args copy;
|
|
if (arg_valgrind)
|
|
{
|
|
copy.add(arg_valgrind);
|
|
}
|
|
copy.add(exe());
|
|
copy.add(args);
|
|
m_proc = NdbProcess::create(name(),
|
|
BaseString(exe_valgrind),
|
|
working_dir,
|
|
copy);
|
|
}
|
|
return (m_proc != NULL);
|
|
}
|
|
|
|
bool start_from_config_ini(const char* working_dir,
|
|
const char* first_extra_arg = NULL, ...)
|
|
{
|
|
NdbProcess::Args args;
|
|
args.add("--no-defaults");
|
|
args.add("--configdir=.");
|
|
args.add("-f config.ini");
|
|
args.add("--ndb-nodeid=", m_nodeid);
|
|
args.add("--nodaemon");
|
|
args.add("--log-name=", name());
|
|
args.add("--verbose");
|
|
|
|
if (first_extra_arg)
|
|
{
|
|
// Append any extra args
|
|
va_list extra_args;
|
|
const char* str = first_extra_arg;
|
|
va_start(extra_args, first_extra_arg);
|
|
do
|
|
{
|
|
args.add(str);
|
|
} while ((str = va_arg(extra_args, const char*)) != NULL);
|
|
va_end(extra_args);
|
|
}
|
|
|
|
return start(working_dir, args);
|
|
}
|
|
|
|
bool start(const char* working_dir,
|
|
const char* first_extra_arg = NULL, ...)
|
|
{
|
|
NdbProcess::Args args;
|
|
args.add("--no-defaults");
|
|
args.add("--configdir=.");
|
|
args.add("--ndb-nodeid=", m_nodeid);
|
|
args.add("--nodaemon");
|
|
args.add("--log-name=", name());
|
|
args.add("--verbose");
|
|
|
|
if (first_extra_arg)
|
|
{
|
|
// Append any extra args
|
|
va_list extra_args;
|
|
const char* str = first_extra_arg;
|
|
va_start(extra_args, first_extra_arg);
|
|
do
|
|
{
|
|
args.add(str);
|
|
} while ((str = va_arg(extra_args, const char*)) != NULL);
|
|
va_end(extra_args);
|
|
}
|
|
|
|
return start(working_dir, args);
|
|
}
|
|
|
|
bool stop(void)
|
|
{
|
|
g_info << "Stopping " << name() << endl;
|
|
|
|
// Diconnect and close our "builtin" client
|
|
m_mgmd_client.close();
|
|
|
|
if (m_proc == 0 || !m_proc->stop())
|
|
{
|
|
fprintf(stderr, "Failed to stop process %s\n", name());
|
|
return false; // Can't kill with -9 -> fatal error
|
|
}
|
|
int ret;
|
|
if (!m_proc->wait(ret, 300))
|
|
{
|
|
fprintf(stderr, "Failed to wait for process %s\n", name());
|
|
return false; // Can't wait after kill with -9 -> fatal error
|
|
}
|
|
|
|
if (ret != 9)
|
|
{
|
|
fprintf(stderr, "stop ret: %u\n", ret);
|
|
return false; // Can't wait after kill with -9 -> fatal error
|
|
}
|
|
|
|
delete m_proc;
|
|
m_proc = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool wait(int& ret, int timeout = 300)
|
|
{
|
|
g_info << "Waiting for " << name() << endl;
|
|
|
|
if (m_proc == 0 || !m_proc->wait(ret, timeout))
|
|
{
|
|
fprintf(stderr, "Failed to wait for process %s\n", name());
|
|
return false;
|
|
}
|
|
delete m_proc;
|
|
m_proc = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
const BaseString connectstring(const Properties& config)
|
|
{
|
|
const char* hostname;
|
|
require(get_section_string(config, m_name.c_str(),
|
|
"HostName", &hostname));
|
|
|
|
Uint32 port;
|
|
require(get_section_uint32(config, m_name.c_str(),
|
|
"PortNumber", &port));
|
|
|
|
BaseString constr;
|
|
constr.assfmt("%s:%d", hostname, port);
|
|
return constr;
|
|
}
|
|
|
|
bool connect(const Properties& config,
|
|
int num_retries = 60, int retry_delay_in_seconds = 1)
|
|
{
|
|
BaseString constr = connectstring(config);
|
|
g_info << "Connecting to " << name() << " @ " << constr.c_str() << endl;
|
|
|
|
return m_mgmd_client.connect(constr.c_str(),
|
|
num_retries,
|
|
retry_delay_in_seconds);
|
|
}
|
|
|
|
bool wait_confirmed_config(int timeout = 30)
|
|
{
|
|
if (!m_mgmd_client.is_connected())
|
|
{
|
|
g_err << "wait_confirmed_config: not connected!" << endl;
|
|
return false;
|
|
}
|
|
|
|
int retries = 0;
|
|
Config conf;
|
|
while (!m_mgmd_client.get_config(conf))
|
|
{
|
|
retries++;
|
|
|
|
if (retries == timeout * 10)
|
|
{
|
|
g_err << "wait_confirmed_config: Failed to get config within "
|
|
<< timeout << " seconds" << endl;
|
|
return false;
|
|
}
|
|
|
|
g_err << "Failed to get config, sleeping" << endl;
|
|
NdbSleep_MilliSleep(100);
|
|
|
|
}
|
|
g_info << "wait_confirmed_config: ok" << endl;
|
|
return true;
|
|
|
|
}
|
|
|
|
NdbMgmHandle handle() { return m_mgmd_client.handle(); }
|
|
|
|
private:
|
|
|
|
bool get_section_string(const Properties& config,
|
|
const char* section_name,
|
|
const char* key,
|
|
const char** value) const
|
|
{
|
|
const Properties* section;
|
|
if (!config.get(section_name, §ion))
|
|
return false;
|
|
|
|
if (!section->get(key, value))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool get_section_uint32(const Properties& config,
|
|
const char* section_name,
|
|
const char* key,
|
|
Uint32* value) const
|
|
{
|
|
const Properties* section;
|
|
if (!config.get(section_name, §ion))
|
|
return false;
|
|
|
|
if (!section->get(key, value))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
};
|
|
|
|
class MgmdProcessList : public Vector<Mgmd*>
|
|
{
|
|
public:
|
|
|
|
~MgmdProcessList()
|
|
{
|
|
// Delete and thus stop the mgmd(s)
|
|
for (unsigned i = 0; i < size(); i++)
|
|
{
|
|
Mgmd* mgmd = this->operator[](i);
|
|
delete mgmd;
|
|
}
|
|
// delete this->[i];
|
|
clear();
|
|
}
|
|
};
|
|
|
|
|
|
#define CHECK(x) \
|
|
if (!(x)) { \
|
|
fprintf(stderr, "CHECK(" #x ") failed at line: %d\n", \
|
|
__LINE__); \
|
|
return NDBT_FAILED; \
|
|
}
|
|
|
|
int runTestBasic2Mgm(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
// Create config.ini
|
|
Properties config = ConfigFactory::create(2);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
// Start ndb_mgmd(s)
|
|
MgmdProcessList mgmds;
|
|
for (int i = 1; i <= 2; i++)
|
|
{
|
|
Mgmd* mgmd = new Mgmd(i);
|
|
mgmds.push_back(mgmd);
|
|
CHECK(mgmd->start_from_config_ini(wd.path()));
|
|
}
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->connect(config));
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// Check binary config files created
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
// Stop the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->stop());
|
|
|
|
// Start up the mgmd(s) again from config.bin
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path()));
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->connect(config));
|
|
|
|
// check ndb_X_config.bin.1 still exists but not ndb_X_config.bin.2
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
CHECK(!file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.2",
|
|
NULL).c_str()));
|
|
CHECK(!file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.2",
|
|
NULL).c_str()));
|
|
|
|
return NDBT_OK;
|
|
|
|
}
|
|
|
|
int runTestBug45495(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
g_err << "** Create config.ini" << endl;
|
|
Properties config = ConfigFactory::create(2);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
// Start ndb_mgmd(s)
|
|
MgmdProcessList mgmds;
|
|
for (int i = 1; i <= 2; i++)
|
|
{
|
|
Mgmd* mgmd = new Mgmd(i);
|
|
mgmds.push_back(mgmd);
|
|
CHECK(mgmd->start_from_config_ini(wd.path()));
|
|
}
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->connect(config));
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// Check binary config files created
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
g_err << "** Restart one ndb_mgmd at a time --reload + --initial" << endl;
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->stop());
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path(),
|
|
"--reload", "--initial", NULL));
|
|
CHECK(mgmds[i]->connect(config));
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// check ndb_X_config.bin.1 still exists but not ndb_X_config.bin.2
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
CHECK(!file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.2",
|
|
NULL).c_str()));
|
|
CHECK(!file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.2",
|
|
NULL).c_str()));
|
|
}
|
|
|
|
g_err << "** Restart one ndb_mgmd at a time --initial" << endl;
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->stop());
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path(),
|
|
"--initial", NULL));
|
|
CHECK(mgmds[i]->connect(config));
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// check ndb_X_config.bin.1 still exists but not ndb_X_config.bin.2
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
CHECK(!file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.2",
|
|
NULL).c_str()));
|
|
CHECK(!file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.2",
|
|
NULL).c_str()));
|
|
}
|
|
|
|
g_err << "** Create config2.ini" << endl;
|
|
CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config2.ini",
|
|
NULL).c_str()));
|
|
|
|
g_err << "** Restart one ndb_mgmd at a time --initial should not work" << endl;
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->stop());
|
|
// Start from config2.ini
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path(),
|
|
"-f config2.ini",
|
|
"--initial", NULL));
|
|
|
|
// Wait for mgmd to exit and check return status
|
|
int ret;
|
|
CHECK(mgmds[i]->wait(ret));
|
|
CHECK(ret == 1);
|
|
|
|
// check config files exist only for the still running mgmd(s)
|
|
for (unsigned j = 0; j < mgmds.size(); j++)
|
|
{
|
|
BaseString tmp;
|
|
tmp.assfmt("ndb_%d_config.bin.1", j+1);
|
|
CHECK(file_exists(path(wd.path(),
|
|
tmp.c_str(),
|
|
NULL).c_str()) == (j != i));
|
|
}
|
|
|
|
// Start from config.ini again
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path(),
|
|
"--initial",
|
|
"--reload",
|
|
NULL));
|
|
CHECK(mgmds[i]->connect(config));
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
}
|
|
|
|
g_err << "** Reload from config2.ini" << endl;
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->stop());
|
|
// Start from config2.ini
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path(),
|
|
"-f config2.ini",
|
|
"--reload", NULL));
|
|
CHECK(mgmds[i]->connect(config));
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
}
|
|
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
Uint32 timeout = 30;
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.2",
|
|
NULL).c_str(), timeout));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.2",
|
|
NULL).c_str(), timeout));
|
|
|
|
g_err << "** Reload mgmd initial(from generation=2)" << endl;
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->stop());
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path(),
|
|
"-f config2.ini",
|
|
"--reload", "--initial", NULL));
|
|
|
|
CHECK(mgmds[i]->connect(config));
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// check config files exist
|
|
for (unsigned j = 0; j < mgmds.size(); j++)
|
|
{
|
|
BaseString tmp;
|
|
tmp.assfmt("ndb_%d_config.bin.1", j+1);
|
|
CHECK(file_exists(path(wd.path(),
|
|
tmp.c_str(),
|
|
NULL).c_str()) == (i < j));
|
|
|
|
tmp.assfmt("ndb_%d_config.bin.2", j+1);
|
|
CHECK(file_exists(path(wd.path(),
|
|
tmp.c_str(),
|
|
NULL).c_str(),
|
|
timeout));
|
|
}
|
|
}
|
|
|
|
return NDBT_OK;
|
|
}
|
|
|
|
|
|
|
|
int runTestBug42015(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
g_err << "** Create config.ini" << endl;
|
|
Properties config = ConfigFactory::create(2);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
MgmdProcessList mgmds;
|
|
// Start ndb_mgmd 1 from config.ini
|
|
Mgmd* mgmd = new Mgmd(1);
|
|
mgmds.push_back(mgmd);
|
|
CHECK(mgmd->start_from_config_ini(wd.path()));
|
|
|
|
// Start ndb_mgmd 2 by fetching from first
|
|
Mgmd* mgmd2 = new Mgmd(2);
|
|
mgmds.push_back(mgmd2);
|
|
CHECK(mgmd2->start(wd.path(),
|
|
"--ndb-connectstring",
|
|
mgmd->connectstring(config).c_str(),
|
|
NULL));
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->connect(config));
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// Check binary config files created
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
return NDBT_OK;
|
|
|
|
}
|
|
|
|
/* Test for bug 53008: --skip-config-cache */
|
|
int runTestNoConfigCache(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
g_err << "** Create config.ini" << endl;
|
|
Properties config = ConfigFactory::create();
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
// Start ndb_mgmd from config.ini
|
|
Mgmd* mgmd = new Mgmd(1);
|
|
CHECK(mgmd->start_from_config_ini(wd.path(), "--skip-config-cache", NULL));
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
CHECK(mgmd->connect(config));
|
|
|
|
// wait for confirmed config
|
|
CHECK(mgmd->wait_confirmed_config());
|
|
|
|
// Check binary config files *not* created
|
|
bool bin_conf_file = file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str());
|
|
CHECK(bin_conf_file == false);
|
|
|
|
mgmd->stop();
|
|
return NDBT_OK;
|
|
}
|
|
|
|
|
|
/* Test for BUG#13428853 */
|
|
int runTestNoConfigCache_DontCreateConfigDir(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
g_err << "** Create config.ini" << endl;
|
|
Properties config = ConfigFactory::create();
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
g_err << "Test no configdir is created with --skip-config-cache" << endl;
|
|
Mgmd* mgmd = new Mgmd(1);
|
|
CHECK(mgmd->start_from_config_ini(wd.path(),
|
|
"--skip-config-cache",
|
|
"--config-dir=dir37",
|
|
NULL));
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
CHECK(mgmd->connect(config));
|
|
|
|
// wait for confirmed config
|
|
CHECK(mgmd->wait_confirmed_config());
|
|
|
|
// Check configdir not created
|
|
CHECK(!file_exists(path(wd.path(), "dir37", NULL).c_str()));
|
|
|
|
mgmd->stop();
|
|
|
|
g_err << "Also test --initial --skip-config-cache" << endl;
|
|
// Also test starting ndb_mgmd --initial --skip-config-cache
|
|
CHECK(mgmd->start_from_config_ini(wd.path(),
|
|
"--skip-config-cache",
|
|
"--initial",
|
|
"--config-dir=dir37",
|
|
NULL));
|
|
// Connect the ndb_mgmd(s)
|
|
CHECK(mgmd->connect(config));
|
|
|
|
// wait for confirmed config
|
|
CHECK(mgmd->wait_confirmed_config());
|
|
|
|
// Check configdir not created
|
|
CHECK(!file_exists(path(wd.path(), "dir37", NULL).c_str()));
|
|
|
|
mgmd->stop();
|
|
return NDBT_OK;
|
|
}
|
|
|
|
|
|
int runTestNoConfigCache_Fetch(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
Properties config = ConfigFactory::create(2);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
MgmdProcessList mgmds;
|
|
// Start ndb_mgmd 1 from config.ini without config cache
|
|
Mgmd* mgmd = new Mgmd(1);
|
|
mgmds.push_back(mgmd);
|
|
CHECK(mgmd->start_from_config_ini(wd.path(),
|
|
"--skip-config-cache",
|
|
NULL));
|
|
|
|
// Start ndb_mgmd 2 without config cache and by fetching from first
|
|
Mgmd* mgmd2 = new Mgmd(2);
|
|
mgmds.push_back(mgmd2);
|
|
CHECK(mgmd2->start(wd.path(),
|
|
"--ndb-connectstring",
|
|
mgmd->connectstring(config).c_str(),
|
|
"--skip-config-cache",
|
|
NULL));
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->connect(config));
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
return NDBT_OK;
|
|
|
|
}
|
|
|
|
|
|
int runTestNowaitNodes(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
MgmdProcessList mgmds;
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
// Create config.ini
|
|
unsigned nodeids[] = { 1, 2 };
|
|
Properties config = ConfigFactory::create(2, 1, 1, nodeids);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
|
|
BaseString binfile[2];
|
|
binfile[0].assfmt("ndb_%u_config.bin.1", nodeids[0]);
|
|
binfile[1].assfmt("ndb_%u_config.bin.1", nodeids[1]);
|
|
|
|
// Start first ndb_mgmd
|
|
Mgmd* mgmd1 = new Mgmd(nodeids[0]);
|
|
{
|
|
mgmds.push_back(mgmd1);
|
|
BaseString arg;
|
|
arg.assfmt("--nowait-nodes=%u", nodeids[1]);
|
|
CHECK(mgmd1->start_from_config_ini(wd.path(),
|
|
"--initial",
|
|
arg.c_str(),
|
|
NULL));
|
|
|
|
// Connect the ndb_mgmd
|
|
CHECK(mgmd1->connect(config));
|
|
|
|
// wait for confirmed config
|
|
CHECK(mgmd1->wait_confirmed_config());
|
|
|
|
// Check binary config file created
|
|
CHECK(file_exists(path(wd.path(),
|
|
binfile[0].c_str(),
|
|
NULL).c_str()));
|
|
}
|
|
|
|
// Start second ndb_mgmd
|
|
{
|
|
Mgmd* mgmd2 = new Mgmd(nodeids[1]);
|
|
mgmds.push_back(mgmd2);
|
|
CHECK(mgmd2->start_from_config_ini(wd.path(),
|
|
"--initial",
|
|
NULL));
|
|
|
|
// Connect the ndb_mgmd
|
|
CHECK(mgmd2->connect(config));
|
|
|
|
// wait for confirmed config
|
|
CHECK(mgmd2->wait_confirmed_config());
|
|
|
|
// Check binary config file created
|
|
CHECK(file_exists(path(wd.path(),
|
|
binfile[1].c_str(),
|
|
NULL).c_str()));
|
|
|
|
}
|
|
|
|
// Create new config.ini
|
|
g_err << "** Create config2.ini" << endl;
|
|
CHECK(ConfigFactory::put(config, "ndb_mgmd", nodeids[0], "ArbitrationDelay", 100));
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config2.ini",
|
|
NULL).c_str()));
|
|
|
|
g_err << "** Reload second mgmd from config2.ini" << endl;
|
|
{
|
|
Mgmd* mgmd2 = mgmds[1];
|
|
CHECK(mgmd2->stop());
|
|
// Start from config2.ini
|
|
CHECK(mgmd2->start_from_config_ini(wd.path(),
|
|
"-f config2.ini",
|
|
"--reload", NULL));
|
|
CHECK(mgmd2->connect(config));
|
|
CHECK(mgmd1->wait_confirmed_config());
|
|
CHECK(mgmd2->wait_confirmed_config());
|
|
|
|
CHECK(file_exists(path(wd.path(),
|
|
binfile[0].c_str(),
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
binfile[1].c_str(),
|
|
NULL).c_str()));
|
|
|
|
// Both ndb_mgmd(s) should have reloaded and new binary config exist
|
|
binfile[0].assfmt("ndb_%u_config.bin.2", nodeids[0]);
|
|
binfile[1].assfmt("ndb_%u_config.bin.2", nodeids[1]);
|
|
CHECK(file_exists(path(wd.path(),
|
|
binfile[0].c_str(),
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
binfile[1].c_str(),
|
|
NULL).c_str()));
|
|
}
|
|
|
|
// Stop the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->stop());
|
|
|
|
return NDBT_OK;
|
|
}
|
|
|
|
|
|
int runTestNowaitNodes2(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
int ret;
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
// Create config.ini
|
|
Properties config = ConfigFactory::create(2);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
g_err << "** Start mgmd1 from config.ini" << endl;
|
|
MgmdProcessList mgmds;
|
|
Mgmd* mgmd1 = new Mgmd(1);
|
|
mgmds.push_back(mgmd1);
|
|
CHECK(mgmd1->start_from_config_ini(wd.path(),
|
|
"--initial",
|
|
"--nowait-nodes=1-255",
|
|
NULL));
|
|
CHECK(mgmd1->connect(config));
|
|
CHECK(mgmd1->wait_confirmed_config());
|
|
|
|
// check config files exist
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
g_err << "** Create config2.ini" << endl;
|
|
CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config2.ini",
|
|
NULL).c_str()));
|
|
|
|
g_err << "** Start mgmd2 from config2.ini" << endl;
|
|
Mgmd* mgmd2 = new Mgmd(2);
|
|
mgmds.push_back(mgmd2);
|
|
CHECK(mgmd2->start_from_config_ini(wd.path(),
|
|
"-f config2.ini",
|
|
"--initial",
|
|
"--nowait-nodes=1-255",
|
|
NULL));
|
|
CHECK(mgmd2->wait(ret));
|
|
CHECK(ret == 1);
|
|
|
|
CHECK(mgmd1->stop());
|
|
|
|
g_err << "** Start mgmd2 again from config2.ini" << endl;
|
|
CHECK(mgmd2->start_from_config_ini(wd.path(),
|
|
"-f config2.ini",
|
|
"--initial",
|
|
"--nowait-nodes=1-255",
|
|
NULL));
|
|
|
|
|
|
CHECK(mgmd2->connect(config));
|
|
CHECK(mgmd2->wait_confirmed_config());
|
|
|
|
// check config files exist
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
g_err << "** Start mgmd1 from config.ini, mgmd2 should shutdown" << endl;
|
|
CHECK(mgmd1->start_from_config_ini(wd.path(),
|
|
"--initial",
|
|
"--nowait-nodes=1-255",
|
|
NULL));
|
|
CHECK(mgmd2->wait(ret));
|
|
CHECK(ret == 1);
|
|
|
|
CHECK(mgmd1->stop());
|
|
|
|
return NDBT_OK;
|
|
}
|
|
|
|
int
|
|
runBug56844(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
g_err << "** Create config.ini" << endl;
|
|
Properties config = ConfigFactory::create(2);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
// Start ndb_mgmd(s)
|
|
MgmdProcessList mgmds;
|
|
for (int i = 1; i <= 2; i++)
|
|
{
|
|
Mgmd* mgmd = new Mgmd(i);
|
|
mgmds.push_back(mgmd);
|
|
CHECK(mgmd->start_from_config_ini(wd.path()));
|
|
}
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->connect(config));
|
|
}
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
}
|
|
|
|
// stop them
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->stop());
|
|
}
|
|
|
|
// Check binary config files created
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_2_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config2.ini",
|
|
NULL).c_str()));
|
|
Uint32 no = 2;
|
|
int loops = ctx->getNumLoops();
|
|
for (int l = 0; l < loops; l++, no++)
|
|
{
|
|
g_err << l << ": *** Reload from config.ini" << endl;
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
// Start from config2.ini
|
|
CHECK(mgmds[i]->start_from_config_ini(wd.path(),
|
|
(l & 1) == 1 ?
|
|
"-f config.ini" :
|
|
"-f config2.ini",
|
|
"--reload", NULL));
|
|
}
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->connect(config));
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
}
|
|
|
|
/**
|
|
* Since it will first be confirmed...
|
|
* and then once connected to other ndb_nmgmd start a config
|
|
* change, it can take a bit until new config exists...
|
|
* allow 30s
|
|
*/
|
|
Uint32 timeout = 30;
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
BaseString p = path(wd.path(), "", NULL);
|
|
p.appfmt("ndb_%u_config.bin.%u", i+1, no);
|
|
g_err << "CHECK(" << p.c_str() << ")" << endl;
|
|
CHECK(file_exists(p.c_str(), timeout));
|
|
}
|
|
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->stop());
|
|
}
|
|
}
|
|
return NDBT_OK;
|
|
}
|
|
|
|
static bool
|
|
get_status(const char* connectstring,
|
|
Properties& status)
|
|
{
|
|
NdbMgmd ndbmgmd;
|
|
if (!ndbmgmd.connect(connectstring))
|
|
return false;
|
|
|
|
Properties args;
|
|
if (!ndbmgmd.call("get status", args,
|
|
"node status", status, NULL, true))
|
|
{
|
|
g_err << "fetch_mgmd_status: mgmd.call failed" << endl;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
value_equal(Properties& status,
|
|
int nodeid, const char* name,
|
|
const char* expected_value)
|
|
{
|
|
const char* value;
|
|
BaseString key;
|
|
key.assfmt("node.%d.%s", nodeid, name);
|
|
if (!status.get(key.c_str(), &value))
|
|
{
|
|
g_err << "value_equal: no value found for '" << name
|
|
<< "." << nodeid << "'" << endl;
|
|
return false;
|
|
}
|
|
|
|
if (strcmp(value, expected_value))
|
|
{
|
|
g_err << "value_equal: found unexpected value: '" << value
|
|
<< "', expected: '" << expected_value << "'" <<endl;
|
|
return false;
|
|
}
|
|
g_info << "'" << value << "'=='" << expected_value << "'" << endl;
|
|
return true;
|
|
}
|
|
|
|
#include <ndb_version.h>
|
|
|
|
int runTestBug12352191(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
BaseString version;
|
|
version.assfmt("%u", NDB_VERSION_D);
|
|
BaseString mysql_version;
|
|
mysql_version.assfmt("%u", NDB_MYSQL_VERSION_D);
|
|
BaseString address("127.0.0.1");
|
|
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
g_err << "** Create config.ini" << endl;
|
|
Properties config = ConfigFactory::create(2);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
MgmdProcessList mgmds;
|
|
const int nodeid1 = 1;
|
|
Mgmd* mgmd1 = new Mgmd(nodeid1);
|
|
mgmds.push_back(mgmd1);
|
|
|
|
const int nodeid2 = 2;
|
|
Mgmd* mgmd2 = new Mgmd(nodeid2);
|
|
mgmds.push_back(mgmd2);
|
|
|
|
// Start first mgmd
|
|
CHECK(mgmd1->start_from_config_ini(wd.path()));
|
|
CHECK(mgmd1->connect(config));
|
|
|
|
Properties status1;
|
|
CHECK(get_status(mgmd1->connectstring(config).c_str(), status1));
|
|
//status1.print();
|
|
// Check status for own mgm node, always CONNECTED
|
|
CHECK(value_equal(status1, nodeid1, "type", "MGM"));
|
|
CHECK(value_equal(status1, nodeid1, "status", "CONNECTED"));
|
|
CHECK(value_equal(status1, nodeid1, "version", version.c_str()));
|
|
CHECK(value_equal(status1, nodeid1, "mysql_version", mysql_version.c_str()));
|
|
CHECK(value_equal(status1, nodeid1, "address", address.c_str()));
|
|
CHECK(value_equal(status1, nodeid1, "startphase", "0"));
|
|
CHECK(value_equal(status1, nodeid1, "dynamic_id", "0"));
|
|
CHECK(value_equal(status1, nodeid1, "node_group", "0"));
|
|
CHECK(value_equal(status1, nodeid1, "connect_count", "0"));
|
|
|
|
// Check status for other mgm node
|
|
// not started yet -> NO_CONTACT, no address, no versions
|
|
CHECK(value_equal(status1, nodeid2, "type", "MGM"));
|
|
CHECK(value_equal(status1, nodeid2, "status", "NO_CONTACT"));
|
|
CHECK(value_equal(status1, nodeid2, "version", "0"));
|
|
CHECK(value_equal(status1, nodeid2, "mysql_version", "0"));
|
|
CHECK(value_equal(status1, nodeid2, "address", ""));
|
|
CHECK(value_equal(status1, nodeid2, "startphase", "0"));
|
|
CHECK(value_equal(status1, nodeid2, "dynamic_id", "0"));
|
|
CHECK(value_equal(status1, nodeid2, "node_group", "0"));
|
|
CHECK(value_equal(status1, nodeid2, "connect_count", "0"));
|
|
|
|
// Start second mgmd
|
|
CHECK(mgmd2->start_from_config_ini(wd.path()));
|
|
CHECK(mgmd2->connect(config));
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
Properties status2;
|
|
CHECK(get_status(mgmd2->connectstring(config).c_str(), status2));
|
|
//status2.print();
|
|
// Check status for own mgm node, always CONNECTED
|
|
CHECK(value_equal(status2, nodeid2, "type", "MGM"));
|
|
CHECK(value_equal(status2, nodeid2, "status", "CONNECTED"));
|
|
CHECK(value_equal(status2, nodeid2, "version", version.c_str()));
|
|
CHECK(value_equal(status2, nodeid2, "mysql_version", mysql_version.c_str()));
|
|
CHECK(value_equal(status2, nodeid2, "address", address.c_str()));
|
|
CHECK(value_equal(status2, nodeid2, "startphase", "0"));
|
|
CHECK(value_equal(status2, nodeid2, "dynamic_id", "0"));
|
|
CHECK(value_equal(status2, nodeid2, "node_group", "0"));
|
|
CHECK(value_equal(status2, nodeid2, "connect_count", "0"));
|
|
|
|
// Check status for other mgm node
|
|
// both started now -> CONNECTED, address and versions filled in
|
|
CHECK(value_equal(status2, nodeid1, "type", "MGM"));
|
|
CHECK(value_equal(status2, nodeid1, "status", "CONNECTED"));
|
|
CHECK(value_equal(status2, nodeid1, "version", version.c_str()));
|
|
CHECK(value_equal(status2, nodeid1, "mysql_version", mysql_version.c_str()));
|
|
CHECK(value_equal(status2, nodeid1, "address", address.c_str()));
|
|
CHECK(value_equal(status2, nodeid1, "startphase", "0"));
|
|
CHECK(value_equal(status2, nodeid1, "dynamic_id", "0"));
|
|
CHECK(value_equal(status2, nodeid1, "node_group", "0"));
|
|
CHECK(value_equal(status2, nodeid1, "connect_count", "0"));
|
|
|
|
Properties status3;
|
|
CHECK(get_status(mgmd1->connectstring(config).c_str(), status3));
|
|
//status3.print();
|
|
// Check status for own mgm node, always CONNECTED
|
|
CHECK(value_equal(status3, nodeid1, "type", "MGM"));
|
|
CHECK(value_equal(status3, nodeid1, "status", "CONNECTED"));
|
|
CHECK(value_equal(status3, nodeid1, "version", version.c_str()));
|
|
CHECK(value_equal(status3, nodeid1, "mysql_version", mysql_version.c_str()));
|
|
CHECK(value_equal(status3, nodeid1, "address", address.c_str()));
|
|
CHECK(value_equal(status3, nodeid1, "startphase", "0"));
|
|
CHECK(value_equal(status3, nodeid1, "dynamic_id", "0"));
|
|
CHECK(value_equal(status3, nodeid1, "node_group", "0"));
|
|
CHECK(value_equal(status3, nodeid1, "connect_count", "0"));
|
|
|
|
// Check status for other mgm node
|
|
// both started now -> CONNECTED, address and versions filled in
|
|
CHECK(value_equal(status3, nodeid2, "type", "MGM"));
|
|
CHECK(value_equal(status3, nodeid2, "status", "CONNECTED"));
|
|
CHECK(value_equal(status3, nodeid2, "version", version.c_str()));
|
|
CHECK(value_equal(status3, nodeid2, "mysql_version", mysql_version.c_str()));
|
|
CHECK(value_equal(status3, nodeid2, "address", address.c_str()));
|
|
CHECK(value_equal(status3, nodeid2, "startphase", "0"));
|
|
CHECK(value_equal(status3, nodeid2, "dynamic_id", "0"));
|
|
CHECK(value_equal(status3, nodeid2, "node_group", "0"));
|
|
CHECK(value_equal(status3, nodeid2, "connect_count", "0"));
|
|
|
|
return NDBT_OK;
|
|
|
|
}
|
|
|
|
int
|
|
runBug61607(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
// Create config.ini
|
|
const int cnt_mgmd = 1;
|
|
Properties config = ConfigFactory::create(cnt_mgmd);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
// Start ndb_mgmd(s)
|
|
MgmdProcessList mgmds;
|
|
for (int i = 1; i <= cnt_mgmd; i++)
|
|
{
|
|
Mgmd* mgmd = new Mgmd(i);
|
|
mgmds.push_back(mgmd);
|
|
CHECK(mgmd->start_from_config_ini(wd.path()));
|
|
}
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->connect(config));
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// Check binary config files created
|
|
CHECK(file_exists(path(wd.path(),
|
|
"ndb_1_config.bin.1",
|
|
NULL).c_str()));
|
|
|
|
int no_of_nodes = 0;
|
|
int * node_ids = 0;
|
|
int initialstart = 0;
|
|
int nostart = 0;
|
|
int abort = 0;
|
|
int force = 0;
|
|
int need_disconnect = 0;
|
|
int res = ndb_mgm_restart4(mgmds[0]->handle(), no_of_nodes, node_ids,
|
|
initialstart, nostart, abort, force,
|
|
&need_disconnect);
|
|
|
|
|
|
return res == 0 ? NDBT_OK : NDBT_FAILED;
|
|
}
|
|
|
|
int
|
|
runStopDuringStart(NDBT_Context* ctx, NDBT_Step* step)
|
|
{
|
|
MgmdProcessList mgmds;
|
|
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
|
|
|
|
// Create config.ini
|
|
unsigned nodeids[] = { 251, 252 };
|
|
Properties config = ConfigFactory::create(2, 1, 1, nodeids);
|
|
CHECK(ConfigFactory::write_config_ini(config,
|
|
path(wd.path(),
|
|
"config.ini",
|
|
NULL).c_str()));
|
|
|
|
for (unsigned i = 0; i < NDB_ARRAY_SIZE(nodeids); i++)
|
|
{
|
|
Mgmd* mgmd = new Mgmd(nodeids[i]);
|
|
mgmds.push_back(mgmd);
|
|
CHECK(mgmd->start_from_config_ini(wd.path()));
|
|
}
|
|
|
|
// Connect the ndb_mgmd(s)
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->connect(config));
|
|
|
|
// wait for confirmed config
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
// Check binary config files created
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
BaseString file;
|
|
file.assfmt("ndb_%u_config.bin.1", nodeids[i]);
|
|
CHECK(file_exists(path(wd.path(),
|
|
file.c_str(),
|
|
NULL).c_str()));
|
|
}
|
|
|
|
// stop them
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
{
|
|
mgmds[i]->stop();
|
|
int exitCode;
|
|
mgmds[i]->wait(exitCode);
|
|
}
|
|
|
|
// restart one with error-insert 100
|
|
// => it shall exit during start...
|
|
mgmds[0]->start(wd.path(), "--error-insert=100", NULL);
|
|
|
|
// restart rest normally
|
|
for (unsigned i = 1; i < mgmds.size(); i++)
|
|
{
|
|
mgmds[i]->start(wd.path());
|
|
}
|
|
|
|
// wait first one to terminate
|
|
int exitCode;
|
|
mgmds[0]->wait(exitCode);
|
|
NdbSleep_MilliSleep(3000);
|
|
|
|
// check other OK
|
|
for (unsigned i = 1; i < mgmds.size(); i++)
|
|
{
|
|
CHECK(mgmds[i]->connect(config));
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
}
|
|
|
|
// now restart without error insert
|
|
mgmds[0]->start(wd.path());
|
|
|
|
// connect
|
|
CHECK(mgmds[0]->connect(config));
|
|
|
|
// all should be ok
|
|
for (unsigned i = 0; i < mgmds.size(); i++)
|
|
CHECK(mgmds[i]->wait_confirmed_config());
|
|
|
|
return NDBT_OK;
|
|
}
|
|
|
|
NDBT_TESTSUITE(testMgmd);
|
|
DRIVER(DummyDriver); /* turn off use of NdbApi */
|
|
|
|
TESTCASE("Basic2Mgm",
|
|
"Basic test with two mgmd")
|
|
{
|
|
INITIALIZER(runTestBasic2Mgm);
|
|
}
|
|
|
|
TESTCASE("Bug42015",
|
|
"Test that mgmd can fetch configuration from another mgmd")
|
|
{
|
|
INITIALIZER(runTestBug42015);
|
|
}
|
|
TESTCASE("NowaitNodes",
|
|
"Test that one mgmd(of 2) can start alone with usage "
|
|
"of --nowait-nodes, then start the second mgmd and it should join")
|
|
{
|
|
INITIALIZER(runTestNowaitNodes);
|
|
}
|
|
TESTCASE("NowaitNodes2",
|
|
"Test that one mgmd(of 2) can start alone with usage "
|
|
"of --nowait-nodes, then start the second mgmd from different "
|
|
"configuration and the one with lowest nodeid should shutdown")
|
|
{
|
|
INITIALIZER(runTestNowaitNodes2);
|
|
}
|
|
|
|
TESTCASE("NoCfgCache",
|
|
"Test that when an mgmd is started with --skip-config-cache, "
|
|
"no ndb_xx_config.xx.bin file is created, but you can "
|
|
"connect to the mgm node and retrieve the config.")
|
|
{
|
|
INITIALIZER(runTestNoConfigCache);
|
|
}
|
|
TESTCASE("NoCfgCacheOrConfigDir",
|
|
"Test that when an mgmd is started with --skip-config-cache, "
|
|
"no ndb_xx_config.xx.bin file is created, but you can "
|
|
"connect to the mgm node and retrieve the config.")
|
|
{
|
|
INITIALIZER(runTestNoConfigCache_DontCreateConfigDir);
|
|
}
|
|
TESTCASE("NoCfgCacheFetch",
|
|
"Test that when an mgmd is started with --skip-config-cache, "
|
|
"it can still fetch config from another ndb_mgmd.")
|
|
{
|
|
INITIALIZER(runTestNoConfigCache_Fetch);
|
|
}
|
|
TESTCASE("Bug45495",
|
|
"Test that mgmd can be restarted in any order")
|
|
{
|
|
INITIALIZER(runTestBug45495);
|
|
}
|
|
|
|
TESTCASE("Bug56844",
|
|
"Test that mgmd can be reloaded in parallel")
|
|
{
|
|
INITIALIZER(runBug56844);
|
|
}
|
|
TESTCASE("Bug12352191",
|
|
"Test mgmd status for other mgmd")
|
|
{
|
|
INITIALIZER(runTestBug12352191);
|
|
}
|
|
TESTCASE("Bug61607",
|
|
"ndb_mgmd incorrectly reports failure when there are no ndbds to stop")
|
|
{
|
|
INITIALIZER(runBug61607);
|
|
}
|
|
TESTCASE("StopDuringStart", "")
|
|
{
|
|
INITIALIZER(runStopDuringStart);
|
|
}
|
|
|
|
NDBT_TESTSUITE_END(testMgmd)
|
|
|
|
int main(int argc, const char** argv)
|
|
{
|
|
ndb_init();
|
|
NDBT_TESTSUITE_INSTANCE(testMgmd);
|
|
testMgmd.setCreateTable(false);
|
|
testMgmd.setRunAllTables(true);
|
|
testMgmd.setConnectCluster(false);
|
|
|
|
#ifdef NDB_USE_GET_ENV
|
|
char buf1[255], buf2[255];
|
|
if (NdbEnv_GetEnv("NDB_MGMD_VALGRIND_EXE", buf1, sizeof(buf1))) {
|
|
exe_valgrind = buf1;
|
|
}
|
|
|
|
if (NdbEnv_GetEnv("NDB_MGMD_VALGRIND_ARG", buf2, sizeof(buf2))) {
|
|
arg_valgrind = buf2;
|
|
}
|
|
#endif
|
|
|
|
return testMgmd.execute(argc, argv);
|
|
}
|
|
|
|
template class Vector<Mgmd*>;
|
|
|