summaryrefslogtreecommitdiff
path: root/ndb/test/tools
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/test/tools')
-rw-r--r--ndb/test/tools/Makefile.am31
-rw-r--r--ndb/test/tools/Makefile_old (renamed from ndb/test/tools/Makefile)0
-rw-r--r--ndb/test/tools/copy_tab.cpp99
-rw-r--r--ndb/test/tools/cpcc.cpp349
-rw-r--r--ndb/test/tools/create_index.cpp95
-rw-r--r--ndb/test/tools/hugoCalculator.cpp (renamed from ndb/test/tools/hugoCalculator/hugoCalculator.cpp)0
-rw-r--r--ndb/test/tools/hugoFill.cpp (renamed from ndb/test/tools/hugoFill/hugoFill.cpp)0
-rw-r--r--ndb/test/tools/hugoLoad.cpp (renamed from ndb/test/tools/hugoLoad/hugoLoad.cpp)0
-rw-r--r--ndb/test/tools/hugoLockRecords.cpp (renamed from ndb/test/tools/hugoLockRecords/hugoLockRecords.cpp)0
-rw-r--r--ndb/test/tools/hugoPkDelete.cpp (renamed from ndb/test/tools/hugoPkDelete/hugoPkDel.cpp)0
-rw-r--r--ndb/test/tools/hugoPkRead.cpp (renamed from ndb/test/tools/hugoPkRead/hugoPkRead.cpp)0
-rw-r--r--ndb/test/tools/hugoPkReadRecord.cpp (renamed from ndb/test/tools/hugoPkReadRecord/hugoPkReadRecord.cpp)0
-rw-r--r--ndb/test/tools/hugoPkUpdate.cpp (renamed from ndb/test/tools/hugoPkUpdate/hugoPkUpd.cpp)0
-rw-r--r--ndb/test/tools/hugoScanRead.cpp (renamed from ndb/test/tools/hugoScanRead/hugoScanRead.cpp)0
-rw-r--r--ndb/test/tools/hugoScanUpdate.cpp (renamed from ndb/test/tools/hugoScanUpdate/hugoScanUpd.cpp)0
-rw-r--r--ndb/test/tools/old_dirs/hugoCalculator/Makefile (renamed from ndb/test/tools/hugoCalculator/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoFill/Makefile (renamed from ndb/test/tools/hugoFill/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoLoad/Makefile (renamed from ndb/test/tools/hugoLoad/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoLockRecords/Makefile (renamed from ndb/test/tools/hugoLockRecords/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkDelete/Makefile (renamed from ndb/test/tools/hugoPkDelete/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkRead/Makefile (renamed from ndb/test/tools/hugoPkRead/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkReadRecord/Makefile (renamed from ndb/test/tools/hugoPkReadRecord/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoPkUpdate/Makefile (renamed from ndb/test/tools/hugoPkUpdate/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoScanRead/Makefile (renamed from ndb/test/tools/hugoScanRead/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/hugoScanUpdate/Makefile (renamed from ndb/test/tools/hugoScanUpdate/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/restart/Makefile (renamed from ndb/test/tools/restart/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/transproxy/Makefile29
-rw-r--r--ndb/test/tools/old_dirs/verify_index/Makefile9
-rw-r--r--ndb/test/tools/old_dirs/waiter/Makefile_old (renamed from ndb/test/tools/waiter/Makefile)0
-rw-r--r--ndb/test/tools/old_dirs/waiter/waiter.cpp (renamed from ndb/test/tools/waiter/waiter.cpp)0
-rw-r--r--ndb/test/tools/restart.cpp (renamed from ndb/test/tools/restart/restart.cpp)0
-rw-r--r--ndb/test/tools/transproxy.cpp362
-rw-r--r--ndb/test/tools/verify_index.cpp85
33 files changed, 1059 insertions, 0 deletions
diff --git a/ndb/test/tools/Makefile.am b/ndb/test/tools/Makefile.am
new file mode 100644
index 00000000000..8d94c21b721
--- /dev/null
+++ b/ndb/test/tools/Makefile.am
@@ -0,0 +1,31 @@
+
+ndbtest_PROGRAMS = hugoCalculator hugoLoad hugoFill hugoLockRecords hugoPkDelete hugoPkRead hugoPkReadRecord hugoPkUpdate hugoScanRead hugoScanUpdate restart verify_index copy_tab create_index ndb_cpcc
+
+# transproxy
+
+hugoCalculator_SOURCES = hugoCalculator.cpp
+hugoFill_SOURCES = hugoFill.cpp
+hugoLoad_SOURCES = hugoLoad.cpp
+hugoLockRecords_SOURCES = hugoLockRecords.cpp
+hugoPkDelete_SOURCES = hugoPkDelete.cpp
+hugoPkRead_SOURCES = hugoPkRead.cpp
+hugoPkReadRecord_SOURCES = hugoPkReadRecord.cpp
+hugoPkUpdate_SOURCES = hugoPkUpdate.cpp
+hugoScanRead_SOURCES = hugoScanRead.cpp
+hugoScanUpdate_SOURCES = hugoScanUpdate.cpp
+restart_SOURCES = restart.cpp
+# transproxy_SOURCES = transproxy.cpp
+verify_index_SOURCES = verify_index.cpp
+copy_tab_SOURCES = copy_tab.cpp
+create_index_SOURCES = create_index.cpp
+ndb_cpcc_SOURCES = cpcc.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient
+
+include $(top_srcdir)/ndb/config/common.mk.am
+include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
+
+ndb_cpcc_LDADD = $(LDADD) $(top_builddir)/ndb/src/mgmclient/CpcClient.o
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/test/tools/Makefile b/ndb/test/tools/Makefile_old
index b8e90ae207f..b8e90ae207f 100644
--- a/ndb/test/tools/Makefile
+++ b/ndb/test/tools/Makefile_old
diff --git a/ndb/test/tools/copy_tab.cpp b/ndb/test/tools/copy_tab.cpp
new file mode 100644
index 00000000000..33ce8e01d9a
--- /dev/null
+++ b/ndb/test/tools/copy_tab.cpp
@@ -0,0 +1,99 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+#include <NdbApi.hpp>
+#include <NDBT.hpp>
+#include "UtilTransactions.hpp"
+
+#include <getarg.h>
+
+int main(int argc, const char** argv){
+
+ const char* _tabname = NULL;
+ const char* _to_tabname = NULL;
+ const char* _dbname = "TEST_DB";
+ const char* _connectstr = NULL;
+ int _copy_data = true;
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "database", 'd', arg_string, &_dbname, "dbname",
+ "Name of database table is in"},
+ { "connstr", 'c', arg_string, &_connectstr, "connect string",
+ "How to connect to NDB"},
+ { "copy-data", '\0', arg_negative_flag, &_copy_data, "Don't copy data to new table",
+ "How to connect to NDB"},
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "srctab desttab\n"\
+ "This program will copy one table in Ndb\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) ||
+ argv[optind] == NULL || argv[optind + 1] == NULL || _help){
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ _tabname = argv[optind];
+ _to_tabname = argv[optind+1];
+
+ if (_connectstr)
+ Ndb::setConnectString(_connectstr);
+ Ndb MyNdb(_dbname);
+ if(MyNdb.init() != 0){
+ ERR(MyNdb.getNdbError());
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ while(MyNdb.waitUntilReady() != 0)
+ ndbout << "Waiting for ndb to become ready..." << endl;
+
+ ndbout << "Copying table " << _tabname << " to " << _to_tabname << "...";
+ const NdbDictionary::Table* ptab = MyNdb.getDictionary()->getTable(_tabname);
+ if (ptab){
+ NdbDictionary::Table tab2(*ptab);
+ tab2.setName(_to_tabname);
+ if (MyNdb.getDictionary()->createTable(tab2) != 0){
+ ndbout << endl << MyNdb.getDictionary()->getNdbError() << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ } else {
+ ndbout << endl << MyNdb.getDictionary()->getNdbError() << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ ndbout << "OK" << endl;
+ if (_copy_data){
+ ndbout << "Copying data..."<<endl;
+ const NdbDictionary::Table * tab3 =
+ NDBT_Table::discoverTableFromDb(&MyNdb,
+ _tabname);
+ // if (!tab3)
+
+ UtilTransactions util(*tab3);
+
+ if(util.copyTableData(&MyNdb,
+ _to_tabname) != NDBT_OK){
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ ndbout << "OK" << endl;
+ }
+ return NDBT_ProgramExit(NDBT_OK);
+}
diff --git a/ndb/test/tools/cpcc.cpp b/ndb/test/tools/cpcc.cpp
new file mode 100644
index 00000000000..e768d707bbc
--- /dev/null
+++ b/ndb/test/tools/cpcc.cpp
@@ -0,0 +1,349 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <getarg.h>
+#include "CpcClient.hpp"
+#include <NdbEnv.h>
+
+#define DEFAULT_PORT 1234
+#define ENV_HOSTS "NDB_CPCC_HOSTS"
+
+struct settings {
+ int m_longl;
+ short m_port;
+} g_settings = { 0 , DEFAULT_PORT };
+
+Vector<SimpleCpcClient*> g_hosts;
+int connect(Vector<SimpleCpcClient*>&);
+
+class Expression {
+public:
+ virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process &)= 0;
+};
+
+int for_each(Vector<SimpleCpcClient*>& list, Expression &);
+int start_stop(const char * cmd, Vector<SimpleCpcClient*>& list,
+ Vector<Vector<Uint32> >& procs);
+
+class True : public Expression {
+public:
+ virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
+ return true;
+ }
+};
+
+class FieldEQ : public Expression {
+ BaseString m_field;
+ BaseString m_value;
+public:
+ FieldEQ(const BaseString & field, const BaseString & value){
+ m_field = field;
+ m_value = value;
+ }
+ virtual ~FieldEQ(){}
+
+ virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
+ BaseString v;
+ if(m_field == "name") v = p.m_name;
+
+ if(m_field == "type") v = p.m_type;
+ if(m_field == "status") v = p.m_status;
+ if(m_field == "owner") v = p.m_owner;
+ if(m_field == "group") v = p.m_group;
+ if(m_field == "path") v = p.m_path;
+ if(m_field == "args") v = p.m_args;
+ if(m_field == "env") v = p.m_env;
+ if(m_field == "cwd") v = p.m_cwd;
+
+ if(m_field == "stdin") v = p.m_stdin;
+ if(m_field == "stdout") v = p.m_stdout;
+ if(m_field == "stderr") v = p.m_stderr;
+
+ return v == m_value;
+ }
+};
+
+class Match : public Expression {
+ Expression & m_cond;
+ Expression & m_apply;
+public:
+ Match(Expression& condition, Expression & rule)
+ : m_cond(condition), m_apply(rule) {
+ }
+ virtual ~Match(){}
+
+ virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
+ if(m_cond.evaluate(c, p))
+ return m_apply.evaluate(c, p);
+ return false;
+ }
+};
+
+class Operate : public Expression {
+ const char * cmd;
+ SimpleCpcClient * host;
+ settings & sets;
+public:
+ Operate(const char * c, settings & s) : sets(s) {
+ cmd = c;
+ host = 0;
+ }
+
+ virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p);
+};
+
+class ProcEQ : public Expression {
+ SimpleCpcClient * host;
+ Uint32 id;
+public:
+ ProcEQ(SimpleCpcClient* h, Uint32 i){
+ host = h; id = i;
+ }
+
+ virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
+ return p.m_id == (int)id && c == host;
+ }
+};
+
+class OrExpr : public Expression {
+ Expression * m_rule;
+ Vector<Expression *> m_cond;
+ bool on_empty;
+public:
+ OrExpr(Expression * rule, bool onEmp = true){
+ m_rule = rule;
+ on_empty = onEmp;
+ }
+
+ virtual ~OrExpr(){}
+
+ virtual bool evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & p){
+ bool run = on_empty;
+ for(size_t i = 0; i<m_cond.size(); i++){
+ if(m_cond[i]->evaluate(c, p)){
+ run = true;
+ break;
+ }
+ }
+ if(run)
+ return m_rule->evaluate(c, p);
+ return false;
+ }
+
+ void push_back(Expression * expr){
+ m_cond.push_back(expr);
+ }
+};
+
+void
+add_host(Vector<SimpleCpcClient*> & hosts, BaseString tmp){
+ Vector<BaseString> split;
+ tmp.split(split, ":");
+
+ short port = g_settings.m_port;
+ if(split.size() > 1)
+ port = atoi(split[1].c_str());
+
+ hosts.push_back(new SimpleCpcClient(split[0].c_str(), port));
+}
+
+void
+add_hosts(Vector<SimpleCpcClient*> & hosts, BaseString list){
+ Vector<BaseString> split;
+ list.split(split);
+ for(size_t i = 0; i<split.size(); i++){
+ add_host(hosts, split[i]);
+ }
+}
+
+int
+main(int argc, const char** argv){
+ int help = 0;
+ const char *cmd=0, *name=0, *group=0, *owner=0;
+ int list = 0, start = 0, stop = 0, rm = 0;
+ struct getargs args[] = {
+ { "cmd", 'c', arg_string, &cmd, "command", "command to run (default ls)" }
+ ,{ "name", 'n', arg_string, &name,
+ "apply command for all processes with name" }
+ ,{ "group", 'g', arg_string, &group,
+ "apply command for all processes in group" }
+ ,{ "owner", 'g', arg_string, &owner,
+ "apply command for all processes with owner" }
+ ,{ "long", 'l', arg_flag, &g_settings.m_longl, "long", "long listing"}
+ ,{ "usage", '?', arg_flag, &help, "Print help", "" }
+ ,{ "ls", 0, arg_flag, &list, "-c list", "list process(es)" }
+ ,{ "start", 0, arg_flag, &start, "-c start", "start process(es)" }
+ ,{ "stop", 0, arg_flag, &stop, "-c stop", "stop process(es)" }
+ ,{ "rm", 0, arg_flag, &rm, "-c rm", "undefine process(es)" }
+ };
+ const int num_args = 10;
+
+ int optind = 0;
+ char desc[] = "[host:[port]]\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return 1;
+ }
+
+ if(list + start + stop + rm > 1){
+ ndbout_c("Can only specify one command");
+ arg_printusage(args, num_args, argv[0], desc);
+ return 1;
+ }
+
+ if(list) cmd = "list";
+ if(start) cmd = "start";
+ if(stop) cmd = "stop";
+ if(rm) cmd = "rm";
+ if(!cmd) cmd = "list";
+
+ Expression * m_expr = 0;
+
+ for(int i = optind; i<argc; i++){
+ add_host(g_hosts, argv[i]);
+ }
+
+ OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true);
+ m_expr = orE;
+ for(int i = optind; i<argc; i++){
+ BaseString tmp(argv[i]);
+ Vector<BaseString> split;
+ tmp.split(split, ":");
+
+ if(split.size() > 2){
+ Uint32 id = atoi(split[2].c_str());
+ orE->push_back(new ProcEQ(g_hosts[i-optind], id));
+ }
+ }
+
+ if(g_hosts.size() == 0){
+ char buf[1024];
+ if(NdbEnv_GetEnv(ENV_HOSTS, buf, sizeof(buf))){
+ add_hosts(g_hosts, BaseString(buf));
+ }
+ }
+
+ if(g_hosts.size() == 0){
+ g_hosts.push_back(new SimpleCpcClient("localhost", g_settings.m_port));
+ }
+
+ if(group != 0){
+ Expression * tmp = new FieldEQ("group", group);
+ m_expr = new Match(* tmp, * m_expr);
+ }
+
+ if(name != 0){
+ Expression * tmp = new FieldEQ("name", name);
+ m_expr = new Match(* tmp, * m_expr);
+ }
+
+ if(owner != 0){
+ Expression * tmp = new FieldEQ("owner", owner);
+ m_expr = new Match(* tmp, * m_expr);
+ }
+
+ connect(g_hosts);
+ for_each(g_hosts, * m_expr);
+
+ return 0;
+}
+
+int
+connect(Vector<SimpleCpcClient*>& list){
+ for(size_t i = 0; i<list.size(); i++){
+ if(list[i]->connect() != 0){
+ ndbout_c("Failed to connect to %s:%d",
+ list[i]->getHost(), list[i]->getPort());
+ delete list[i]; list[i] = 0;
+ }
+ }
+ return 0;
+}
+
+int
+for_each(Vector<SimpleCpcClient*>& list, Expression & expr){
+ for(size_t i = 0; i<list.size(); i++){
+ if(list[i] == 0)
+ continue;
+ Properties p;
+ Vector<SimpleCpcClient::Process> procs;
+ if(list[i]->list_processes(procs, p) != 0){
+ ndbout << "Failed to list processes on "
+ << list[i]->getHost() << ":" << list[i]->getPort() << endl;
+ }
+ for(size_t j = 0; j<procs.size(); j++)
+ expr.evaluate(list[i], procs[j]);
+ }
+ return 0;
+}
+
+bool
+Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){
+ Uint32 id = pp.m_id;
+ Properties p;
+ int res;
+
+ if(strcasecmp(cmd, "start") == 0)
+ res = c->start_process(id, p);
+ else if(strcasecmp(cmd, "stop") == 0)
+ res = c->stop_process(id, p);
+ else if(strcasecmp(cmd, "rm") == 0)
+ res = c->undefine_process(id, p);
+ else if(strcasecmp(cmd, "list") == 0){
+ if(!sets.m_longl){
+ if(host != c){
+ ndbout_c("--- %s:%d", c->getHost(), c->getPort());
+ host = c;
+ }
+ }
+
+ char s = 0;
+ const char * status = pp.m_status.c_str();
+ if(strcmp(status, "stopped") == 0) s = '-';
+ if(strcmp(status, "starting") == 0) s = 's';
+ if(strcmp(status, "running") == 0) s = 'r';
+ if(strcmp(status, "stopping") == 0) s = 'k';
+ if(s == 0) s = '?';
+
+ if(!sets.m_longl){
+ ndbout_c("%c%c\t%d\t%s\t%s\t%s(%s)",
+ s,
+ pp.m_type.c_str()[0], id, pp.m_owner.c_str(),
+ pp.m_group.c_str(), pp.m_name.c_str(), pp.m_path.c_str());
+ } else {
+ ndbout_c("%c%c %s:%d:%d %s %s %s(%s)",
+ s, pp.m_type.c_str()[0], c->getHost(), c->getPort(),
+ id, pp.m_owner.c_str(), pp.m_group.c_str(),
+ pp.m_name.c_str(), pp.m_path.c_str());
+ }
+ return true;
+ }
+
+ if(res != 0){
+ BaseString msg;
+ p.get("errormessage", msg);
+ ndbout_c("Failed to %s %d on %s:%d - %s",
+ cmd, id,
+ c->getHost(), c->getPort(), msg.c_str());
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/ndb/test/tools/create_index.cpp b/ndb/test/tools/create_index.cpp
new file mode 100644
index 00000000000..dc9e6c606d6
--- /dev/null
+++ b/ndb/test/tools/create_index.cpp
@@ -0,0 +1,95 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+#include <NdbApi.hpp>
+#include <NDBT.hpp>
+
+#include <getarg.h>
+
+
+
+int
+main(int argc, const char** argv){
+
+ const char* _dbname = "TEST_DB";
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "database", 'd', arg_string, &_dbname, "dbname",
+ "Name of database table is in"},
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "<tabname>+\n"\
+ "This program will create one unique hash index named ind_<tabname> "
+ " for each table. The index will contain all columns in the table";
+
+ if(getarg(args, num_args, argc, argv, &optind) || _help ||
+ argv[optind] == NULL){
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+
+ Ndb MyNdb(_dbname);
+ if(MyNdb.init() != 0){
+ ERR(MyNdb.getNdbError());
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ while(MyNdb.waitUntilReady() != 0)
+ ndbout << "Waiting for ndb to become ready..." << endl;
+
+ NdbDictionary::Dictionary * dict = MyNdb.getDictionary();
+
+ for(int i = optind; i<argc; i++){
+ const NdbDictionary::Table * tab = dict->getTable(argv[i]);
+ if(tab == 0){
+ g_err << "Unknown table: " << argv[i] << endl;
+ continue;
+ }
+
+ if(tab->getNoOfColumns() > 16){
+ g_err << "Table " << argv[i] << " has more than 16 columns" << endl;
+ }
+
+ NdbDictionary::Index ind;
+ char buf[512];
+ sprintf(buf, "IND_%s", argv[i]);
+ ind.setName(buf);
+ ind.setTable(argv[i]);
+ ind.setType(NdbDictionary::Index::UniqueHashIndex);
+ for(int c = 0; c<tab->getNoOfColumns(); c++)
+ ind.addIndexColumn(tab->getColumn(c)->getName());
+
+ ndbout << "creating index " << buf << " on table " << argv[i] << "...";
+ const int res = dict->createIndex(ind);
+ if(res != 0)
+ ndbout << endl << dict->getNdbError() << endl;
+ else
+ ndbout << "OK" << endl;
+ }
+
+ return NDBT_ProgramExit(NDBT_OK);
+}
+
+
diff --git a/ndb/test/tools/hugoCalculator/hugoCalculator.cpp b/ndb/test/tools/hugoCalculator.cpp
index 7f2751be2ba..7f2751be2ba 100644
--- a/ndb/test/tools/hugoCalculator/hugoCalculator.cpp
+++ b/ndb/test/tools/hugoCalculator.cpp
diff --git a/ndb/test/tools/hugoFill/hugoFill.cpp b/ndb/test/tools/hugoFill.cpp
index dee6ce2e6c8..dee6ce2e6c8 100644
--- a/ndb/test/tools/hugoFill/hugoFill.cpp
+++ b/ndb/test/tools/hugoFill.cpp
diff --git a/ndb/test/tools/hugoLoad/hugoLoad.cpp b/ndb/test/tools/hugoLoad.cpp
index be7f878d106..be7f878d106 100644
--- a/ndb/test/tools/hugoLoad/hugoLoad.cpp
+++ b/ndb/test/tools/hugoLoad.cpp
diff --git a/ndb/test/tools/hugoLockRecords/hugoLockRecords.cpp b/ndb/test/tools/hugoLockRecords.cpp
index e2c2cd13f00..e2c2cd13f00 100644
--- a/ndb/test/tools/hugoLockRecords/hugoLockRecords.cpp
+++ b/ndb/test/tools/hugoLockRecords.cpp
diff --git a/ndb/test/tools/hugoPkDelete/hugoPkDel.cpp b/ndb/test/tools/hugoPkDelete.cpp
index 1855f19796f..1855f19796f 100644
--- a/ndb/test/tools/hugoPkDelete/hugoPkDel.cpp
+++ b/ndb/test/tools/hugoPkDelete.cpp
diff --git a/ndb/test/tools/hugoPkRead/hugoPkRead.cpp b/ndb/test/tools/hugoPkRead.cpp
index 50351f08195..50351f08195 100644
--- a/ndb/test/tools/hugoPkRead/hugoPkRead.cpp
+++ b/ndb/test/tools/hugoPkRead.cpp
diff --git a/ndb/test/tools/hugoPkReadRecord/hugoPkReadRecord.cpp b/ndb/test/tools/hugoPkReadRecord.cpp
index ac17ffffee8..ac17ffffee8 100644
--- a/ndb/test/tools/hugoPkReadRecord/hugoPkReadRecord.cpp
+++ b/ndb/test/tools/hugoPkReadRecord.cpp
diff --git a/ndb/test/tools/hugoPkUpdate/hugoPkUpd.cpp b/ndb/test/tools/hugoPkUpdate.cpp
index e7edc3a991d..e7edc3a991d 100644
--- a/ndb/test/tools/hugoPkUpdate/hugoPkUpd.cpp
+++ b/ndb/test/tools/hugoPkUpdate.cpp
diff --git a/ndb/test/tools/hugoScanRead/hugoScanRead.cpp b/ndb/test/tools/hugoScanRead.cpp
index 47ea8f4a8a7..47ea8f4a8a7 100644
--- a/ndb/test/tools/hugoScanRead/hugoScanRead.cpp
+++ b/ndb/test/tools/hugoScanRead.cpp
diff --git a/ndb/test/tools/hugoScanUpdate/hugoScanUpd.cpp b/ndb/test/tools/hugoScanUpdate.cpp
index 3e2255ca0f3..3e2255ca0f3 100644
--- a/ndb/test/tools/hugoScanUpdate/hugoScanUpd.cpp
+++ b/ndb/test/tools/hugoScanUpdate.cpp
diff --git a/ndb/test/tools/hugoCalculator/Makefile b/ndb/test/tools/old_dirs/hugoCalculator/Makefile
index a29deeaacd3..a29deeaacd3 100644
--- a/ndb/test/tools/hugoCalculator/Makefile
+++ b/ndb/test/tools/old_dirs/hugoCalculator/Makefile
diff --git a/ndb/test/tools/hugoFill/Makefile b/ndb/test/tools/old_dirs/hugoFill/Makefile
index 3da745810b6..3da745810b6 100644
--- a/ndb/test/tools/hugoFill/Makefile
+++ b/ndb/test/tools/old_dirs/hugoFill/Makefile
diff --git a/ndb/test/tools/hugoLoad/Makefile b/ndb/test/tools/old_dirs/hugoLoad/Makefile
index 7c5756d0d41..7c5756d0d41 100644
--- a/ndb/test/tools/hugoLoad/Makefile
+++ b/ndb/test/tools/old_dirs/hugoLoad/Makefile
diff --git a/ndb/test/tools/hugoLockRecords/Makefile b/ndb/test/tools/old_dirs/hugoLockRecords/Makefile
index 3235750cbf8..3235750cbf8 100644
--- a/ndb/test/tools/hugoLockRecords/Makefile
+++ b/ndb/test/tools/old_dirs/hugoLockRecords/Makefile
diff --git a/ndb/test/tools/hugoPkDelete/Makefile b/ndb/test/tools/old_dirs/hugoPkDelete/Makefile
index e6d53611c54..e6d53611c54 100644
--- a/ndb/test/tools/hugoPkDelete/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkDelete/Makefile
diff --git a/ndb/test/tools/hugoPkRead/Makefile b/ndb/test/tools/old_dirs/hugoPkRead/Makefile
index 03580dc0d18..03580dc0d18 100644
--- a/ndb/test/tools/hugoPkRead/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkRead/Makefile
diff --git a/ndb/test/tools/hugoPkReadRecord/Makefile b/ndb/test/tools/old_dirs/hugoPkReadRecord/Makefile
index 158a79a5666..158a79a5666 100644
--- a/ndb/test/tools/hugoPkReadRecord/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkReadRecord/Makefile
diff --git a/ndb/test/tools/hugoPkUpdate/Makefile b/ndb/test/tools/old_dirs/hugoPkUpdate/Makefile
index 48795b62206..48795b62206 100644
--- a/ndb/test/tools/hugoPkUpdate/Makefile
+++ b/ndb/test/tools/old_dirs/hugoPkUpdate/Makefile
diff --git a/ndb/test/tools/hugoScanRead/Makefile b/ndb/test/tools/old_dirs/hugoScanRead/Makefile
index b88377c299e..b88377c299e 100644
--- a/ndb/test/tools/hugoScanRead/Makefile
+++ b/ndb/test/tools/old_dirs/hugoScanRead/Makefile
diff --git a/ndb/test/tools/hugoScanUpdate/Makefile b/ndb/test/tools/old_dirs/hugoScanUpdate/Makefile
index ec0e07bfd84..ec0e07bfd84 100644
--- a/ndb/test/tools/hugoScanUpdate/Makefile
+++ b/ndb/test/tools/old_dirs/hugoScanUpdate/Makefile
diff --git a/ndb/test/tools/restart/Makefile b/ndb/test/tools/old_dirs/restart/Makefile
index 05d9e98c5bc..05d9e98c5bc 100644
--- a/ndb/test/tools/restart/Makefile
+++ b/ndb/test/tools/old_dirs/restart/Makefile
diff --git a/ndb/test/tools/old_dirs/transproxy/Makefile b/ndb/test/tools/old_dirs/transproxy/Makefile
new file mode 100644
index 00000000000..d6a76ed2e3d
--- /dev/null
+++ b/ndb/test/tools/old_dirs/transproxy/Makefile
@@ -0,0 +1,29 @@
+include .defs.mk
+
+TYPE =
+
+BIN_TARGET = transproxy
+
+SOURCES = transproxy.cpp
+
+CCFLAGS_LOC +=\
+ -I$(NDB_TOP)/include/kernel \
+ -I$(NDB_TOP)/include/mgmcommon \
+ -I$(NDB_TOP)/src/common/mgmcommon \
+ -I$(NDB_TOP)/src/mgmsrv
+
+LIBS_LOC +=\
+ -L$(NDB_TOP)/lib
+
+LIBS_SPEC +=\
+ $(NDB_TOP)/src/mgmsrv/InitConfigFileParser.o \
+ $(NDB_TOP)/src/mgmsrv/Config.o \
+ $(NDB_TOP)/src/mgmsrv/Container.o \
+ $(NDB_TOP)/src/mgmsrv/Str.o \
+ $(NDB_TOP)/src/mgmsrv/convertStrToInt.o \
+ -lNDB_API \
+ -leventlogger \
+ -llogger \
+ -lportlib
+
+include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/tools/old_dirs/verify_index/Makefile b/ndb/test/tools/old_dirs/verify_index/Makefile
new file mode 100644
index 00000000000..f6b31e4dc8e
--- /dev/null
+++ b/ndb/test/tools/old_dirs/verify_index/Makefile
@@ -0,0 +1,9 @@
+include .defs.mk
+
+TYPE := ndbapitest
+
+BIN_TARGET := verify_index
+
+SOURCES := verify_index.cpp
+
+include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/tools/waiter/Makefile b/ndb/test/tools/old_dirs/waiter/Makefile_old
index da2c9daff00..da2c9daff00 100644
--- a/ndb/test/tools/waiter/Makefile
+++ b/ndb/test/tools/old_dirs/waiter/Makefile_old
diff --git a/ndb/test/tools/waiter/waiter.cpp b/ndb/test/tools/old_dirs/waiter/waiter.cpp
index d57daff3aea..d57daff3aea 100644
--- a/ndb/test/tools/waiter/waiter.cpp
+++ b/ndb/test/tools/old_dirs/waiter/waiter.cpp
diff --git a/ndb/test/tools/restart/restart.cpp b/ndb/test/tools/restart.cpp
index 88cfb231a72..88cfb231a72 100644
--- a/ndb/test/tools/restart/restart.cpp
+++ b/ndb/test/tools/restart.cpp
diff --git a/ndb/test/tools/transproxy.cpp b/ndb/test/tools/transproxy.cpp
new file mode 100644
index 00000000000..384a8a34f03
--- /dev/null
+++ b/ndb/test/tools/transproxy.cpp
@@ -0,0 +1,362 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbTCP.h>
+#include <NdbOut.hpp>
+#include <NdbThread.h>
+#include <NdbSleep.h>
+#include <Properties.hpp>
+#include <LocalConfig.hpp>
+#include <Config.hpp>
+#include <InitConfigFileParser.hpp>
+#include <IPCConfig.hpp>
+
+static void
+fatal(char const* fmt, ...)
+{
+ va_list ap;
+ char buf[200];
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ ndbout << "FATAL: " << buf << endl;
+ sleep(1);
+ exit(1);
+}
+
+static void
+debug(char const* fmt, ...)
+{
+ va_list ap;
+ char buf[200];
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ ndbout << buf << endl;
+}
+
+// node
+struct Node {
+ enum Type { MGM = 1, DB = 2, API = 3 };
+ Type type;
+ unsigned id; // node id
+ static Node* list;
+ static unsigned count;
+ static Node* find(unsigned n) {
+ for (unsigned i = 0; i < count; i++) {
+ if (list[i].id == n)
+ return &list[i];
+ }
+ return 0;
+ }
+};
+
+unsigned Node::count = 0;
+Node* Node::list = 0;
+
+struct Copy {
+ int rfd; // read from
+ int wfd; // write to
+ unsigned char* buf;
+ unsigned bufsiz;
+ NdbThread* thread;
+ void run();
+ char info[20];
+};
+
+// connection between nodes 0-server side 1-client side
+// we are client to 0 and server to 1
+struct Conn {
+ Node* node[2]; // the nodes
+ unsigned port; // server port
+ unsigned proxy; // proxy port
+ static unsigned count;
+ static unsigned proxycount;
+ static Conn* list;
+ NdbThread* thread; // thread handling this connection
+ void run(); // run the connection
+ int sockfd[2]; // socket 0-on server side 1-client side
+ void conn0(); // connect to side 0
+ void conn1(); // connect to side 0
+ char info[20];
+ Copy copy[2]; // 0-to-1 and 1-to-0
+};
+
+unsigned Conn::count = 0;
+unsigned Conn::proxycount = 0;
+Conn* Conn::list = 0;
+
+// global data
+static char* hostname = 0;
+static struct sockaddr_in hostaddr;
+static char* localcfgfile = 0;
+static char* initcfgfile = 0;
+static unsigned ownnodeid = 0;
+
+static void
+properr(const Properties* props, const char* name, int i = -1)
+{
+ if (i < 0) {
+ fatal("get %s failed: errno = %d", name, props->getPropertiesErrno());
+ } else {
+ fatal("get %s_%d failed: errno = %d", name, i, props->getPropertiesErrno());
+ }
+}
+
+// read config and load it into our structs
+static void
+getcfg()
+{
+ LocalConfig lcfg;
+ if (! lcfg.read(localcfgfile)) {
+ fatal("read %s failed", localcfgfile);
+ }
+ ownnodeid = lcfg._ownNodeId;
+ debug("ownnodeid = %d", ownnodeid);
+ InitConfigFileParser pars(initcfgfile);
+ Config icfg;
+ if (! pars.getConfig(icfg)) {
+ fatal("parse %s failed", initcfgfile);
+ }
+ Properties* ccfg = icfg.getConfig(ownnodeid);
+ if (ccfg == 0) {
+ const char* err = "unknown error";
+ fatal("getConfig: %s", err);
+ }
+ ccfg->put("NodeId", ownnodeid);
+ ccfg->put("NodeType", "MGM");
+ if (! ccfg->get("NoOfNodes", &Node::count)) {
+ properr(ccfg, "NoOfNodes", -1);
+ }
+ debug("Node::count = %d", Node::count);
+ Node::list = new Node[Node::count];
+ for (unsigned i = 0; i < Node::count; i++) {
+ Node& node = Node::list[i];
+ const Properties* nodecfg;
+ if (! ccfg->get("Node", 1+i, &nodecfg)) {
+ properr(ccfg, "Node", 1+i);
+ }
+ const char* type;
+ if (! nodecfg->get("Type", &type)) {
+ properr(nodecfg, "Type");
+ }
+ if (strcmp(type, "MGM") == 0) {
+ node.type = Node::MGM;
+ } else if (strcmp(type, "DB") == 0) {
+ node.type = Node::DB;
+ } else if (strcmp(type, "API") == 0) {
+ node.type = Node::API;
+ } else {
+ fatal("prop %s_%d bad Type = %s", "Node", 1+i, type);
+ }
+ if (! nodecfg->get("NodeId", &node.id)) {
+ properr(nodecfg, "NodeId");
+ }
+ debug("node id=%d type=%d", node.id, node.type);
+ }
+ IPCConfig ipccfg(ccfg);
+ if (ipccfg.init() != 0) {
+ fatal("ipccfg init failed");
+ }
+ if (! ccfg->get("NoOfConnections", &Conn::count)) {
+ properr(ccfg, "NoOfConnections");
+ }
+ debug("Conn::count = %d", Conn::count);
+ Conn::list = new Conn[Conn::count];
+ for (unsigned i = 0; i < Conn::count; i++) {
+ Conn& conn = Conn::list[i];
+ const Properties* conncfg;
+ if (! ccfg->get("Connection", i, &conncfg)) {
+ properr(ccfg, "Connection", i);
+ }
+ unsigned n;
+ if (! conncfg->get("NodeId1", &n)) {
+ properr(conncfg, "NodeId1");
+ }
+ if ((conn.node[0] = Node::find(n)) == 0) {
+ fatal("node %d not found", n);
+ }
+ if (! conncfg->get("NodeId2", &n)) {
+ properr(conncfg, "NodeId2");
+ }
+ if ((conn.node[1] = Node::find(n)) == 0) {
+ fatal("node %d not found", n);
+ }
+ if (! conncfg->get("PortNumber", &conn.port)) {
+ properr(conncfg, "PortNumber");
+ }
+ conn.proxy = 0;
+ const char* proxy;
+ if (conncfg->get("Proxy", &proxy)) {
+ conn.proxy = atoi(proxy);
+ if (conn.proxy > 0) {
+ Conn::proxycount++;
+ }
+ }
+ sprintf(conn.info, "conn %d-%d", conn.node[0]->id, conn.node[1]->id);
+ }
+}
+
+void
+Conn::conn0()
+{
+ int fd;
+ while (1) {
+ if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
+ fatal("%s: create client socket failed: %s", info, strerror(errno));
+ }
+ struct sockaddr_in servaddr;
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(port);
+ servaddr.sin_addr = hostaddr.sin_addr;
+#if 0 // coredump
+ if (Ndb_getInAddr(&servaddr.sin_addr, hostname) != 0) {
+ fatal("%s: hostname %s lookup failed", info, hostname);
+ }
+#endif
+ if (connect(fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == 0)
+ break;
+ if (errno != ECONNREFUSED) {
+ fatal("%s: connect failed: %s", info, strerror(errno));
+ }
+ close(fd);
+ NdbSleep_MilliSleep(100);
+ }
+ sockfd[0] = fd;
+ debug("%s: side 0 connected", info);
+}
+
+void
+Conn::conn1()
+{
+ int servfd;
+ if ((servfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
+ fatal("%s: create server socket failed: %s", info, strerror(errno));
+ }
+ struct sockaddr_in servaddr;
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ servaddr.sin_port = htons(proxy);
+ const int on = 1;
+ setsockopt(servfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
+ if (bind(servfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) == -1) {
+ fatal("%s: bind %d failed: %s", info, proxy, strerror(errno));
+ }
+ if (listen(servfd, 1) == -1) {
+ fatal("%s: listen %d failed: %s", info, proxy, strerror(errno));
+ }
+ int fd;
+ if ((fd = accept(servfd, 0, 0)) == -1) {
+ fatal("%s: accept failed: %s", info, strerror(errno));
+ }
+ sockfd[1] = fd;
+ close(servfd);
+ debug("%s: side 1 connected", info);
+}
+
+void
+Copy::run()
+{
+ debug("%s: start", info);
+ int n, m;
+ while (1) {
+ n = read(rfd, buf, sizeof(buf));
+ if (n < 0)
+ fatal("read error: %s", strerror(errno));
+ m = write(wfd, buf, n);
+ if (m != n)
+ fatal("write error: %s", strerror(errno));
+ }
+ debug("%s: stop", info);
+}
+
+extern "C" void*
+copyrun_C(void* copy)
+{
+ ((Copy*) copy)->run();
+ NdbThread_Exit(0);
+ return 0;
+}
+
+void
+Conn::run()
+{
+ debug("%s: start", info);
+ conn1();
+ conn0();
+ const unsigned siz = 32 * 1024;
+ for (int i = 0; i < 2; i++) {
+ Copy& copy = this->copy[i];
+ copy.rfd = sockfd[i];
+ copy.wfd = sockfd[1-i];
+ copy.buf = new unsigned char[siz];
+ copy.bufsiz = siz;
+ sprintf(copy.info, "copy %d-%d", this->node[i]->id, this->node[1-i]->id);
+ copy.thread = NdbThread_Create(copyrun_C, (void**)&copy,
+ 8192, "copyrun", NDB_THREAD_PRIO_LOW);
+ if (copy.thread == 0) {
+ fatal("%s: create thread %d failed errno=%d", i, errno);
+ }
+ }
+ debug("%s: stop", info);
+}
+
+extern "C" void*
+connrun_C(void* conn)
+{
+ ((Conn*) conn)->run();
+ NdbThread_Exit(0);
+ return 0;
+}
+
+static void
+start()
+{
+ NdbThread_SetConcurrencyLevel(3 * Conn::proxycount + 2);
+ for (unsigned i = 0; i < Conn::count; i++) {
+ Conn& conn = Conn::list[i];
+ if (! conn.proxy)
+ continue;
+ conn.thread = NdbThread_Create(connrun_C, (void**)&conn,
+ 8192, "connrun", NDB_THREAD_PRIO_LOW);
+ if (conn.thread == 0) {
+ fatal("create thread %d failed errno=%d", i, errno);
+ }
+ }
+ sleep(3600);
+}
+
+int
+main(int av, char** ac)
+{
+ debug("start");
+ hostname = "ndb-srv7";
+ if (Ndb_getInAddr(&hostaddr.sin_addr, hostname) != 0) {
+ fatal("hostname %s lookup failed", hostname);
+ }
+ localcfgfile = "Ndb.cfg";
+ initcfgfile = "config.txt";
+ getcfg();
+ start();
+ debug("done");
+ return 0;
+}
+
+// vim: set sw=4 noet:
diff --git a/ndb/test/tools/verify_index.cpp b/ndb/test/tools/verify_index.cpp
new file mode 100644
index 00000000000..1295b657e9b
--- /dev/null
+++ b/ndb/test/tools/verify_index.cpp
@@ -0,0 +1,85 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+
+#include <NdbApi.hpp>
+#include <NdbMain.h>
+#include <NDBT.hpp>
+#include <NdbSleep.h>
+#include <getarg.h>
+#include <UtilTransactions.hpp>
+
+
+int main(int argc, const char** argv){
+ int _parallelism = 240;
+ const char* _tabname = NULL;
+ const char* _indexname = NULL;
+ int _help = 0;
+
+ struct getargs args[] = {
+ { "parallelism", 's', arg_integer, &_parallelism, "parallelism", "parallelism" },
+ { "usage", '?', arg_flag, &_help, "Print help", "" }
+ };
+ int num_args = sizeof(args) / sizeof(args[0]);
+ int optind = 0;
+ char desc[] =
+ "tabname indexname\n"\
+ "This program will verify the index [indexname] and compare it to data\n"
+ "in table [tablename]\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) ||
+ argv[optind] == NULL || argv[optind+1] == NULL || _help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ _tabname = argv[optind];
+ _indexname = argv[optind+1];
+
+ // Connect to Ndb
+ Ndb MyNdb( "TEST_DB" );
+
+ if(MyNdb.init() != 0){
+ ERR(MyNdb.getNdbError());
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ // Connect to Ndb and wait for it to become ready
+ while(MyNdb.waitUntilReady() != 0)
+ ndbout << "Waiting for ndb to become ready..." << endl;
+
+ // Check if table exists in db
+ const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname);
+ if(pTab == NULL){
+ ndbout << " Table " << _tabname << " does not exist!" << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ int rows = 0;
+ UtilTransactions utilTrans(*pTab);
+ if (utilTrans.verifyIndex(&MyNdb,
+ _indexname,
+ _parallelism) != 0){
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ return NDBT_ProgramExit(NDBT_OK);
+}
+
+
+