#At file:///Users/mz/mysql/ndb-7.1-opt64/ based on revid:martin.zaun@stripped
3866 Martin Zaun 2010-10-19
crund - aligned c++ design and log+console output with java version.
added:
storage/ndb/test/crund/tws/tws_cpp/Driver.cpp
storage/ndb/test/crund/tws/tws_cpp/Driver.hpp
storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.cpp
storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.hpp
storage/ndb/test/crund/tws/tws_cpp/TwsDriver.hpp
modified:
storage/ndb/test/crund/tws/tws_cpp/TwsDriver.cpp
=== added file 'storage/ndb/test/crund/tws/tws_cpp/Driver.cpp'
--- a/storage/ndb/test/crund/tws/tws_cpp/Driver.cpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/crund/tws/tws_cpp/Driver.cpp 2010-10-19 22:52:04 +0000
@@ -0,0 +1,268 @@
+/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
+ *
+ * Copyright (C) 2010 MySQL
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "Driver.hpp"
+
+#include <cassert>
+
+#include "helpers.hpp"
+#include "string_helpers.hpp"
+
+using std::cout;
+using std::flush;
+using std::endl;
+using std::ios_base;
+using std::string;
+using std::vector;
+
+using utils::Properties;
+using utils::toBool;
+using utils::toInt;
+using utils::toString;
+
+// ---------------------------------------------------------------------------
+// Helper Macros & Functions
+// ---------------------------------------------------------------------------
+
+#define ABORT_GETTIMEOFDAY_ERROR() \
+ do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \
+ << ", gettimeofday() returned an error code." << endl; \
+ exit(-1); \
+ } while (0)
+
+// ---------------------------------------------------------------------------
+// Driver Implementation
+// ---------------------------------------------------------------------------
+
+vector< string > Driver::propFileNames;
+string Driver::logFileName;
+
+void
+Driver::exitUsage()
+{
+ cout << "usage: [options]" << endl
+ << " [-p <file name>]... properties file name" << endl
+ << " [-l <file name>] log file name for data output" << endl
+ << " [-h|--help] print usage message and exit" << endl
+ << endl;
+ exit(1); // return an error code
+}
+
+void
+Driver::parseArguments(int argc, const char* argv[])
+{
+ for (int i = 1; i < argc; i++) {
+ const string arg = argv[i];
+ if (arg.compare("-p") == 0) {
+ if (i >= argc) {
+ exitUsage();
+ }
+ propFileNames.push_back(argv[++i]);
+ } else if (arg.compare("-l") == 0) {
+ if (i >= argc) {
+ exitUsage();
+ }
+ logFileName = argv[++i];
+ } else if (arg.compare("-h") == 0 || arg.compare("--help") == 0) {
+ exitUsage();
+ } else {
+ cout << "unknown option: " << arg << endl;
+ exitUsage();
+ }
+ }
+
+ if (propFileNames.size() == 0) {
+ propFileNames.push_back("run.properties");
+ }
+
+ if (logFileName.empty()) {
+ logFileName = "log_";
+
+ // format, destination strings (static size)
+ const char format[] = "%Y%m%d_%H%M%S";
+ const int size = sizeof("yyyymmdd_HHMMSS");
+ char dest[size];
+
+ // get time, convert to timeinfo (statically allocated) then to string
+ const time_t now = time(0);
+ const int nchars = strftime(dest, size, format, localtime(&now));
+ assert(nchars == size-1);
+ (void)nchars;
+
+ logFileName += dest;
+ logFileName += ".txt";
+ }
+ //cout << "logFileName='" << logFileName << "'" << endl;
+}
+
+// ----------------------------------------------------------------------
+
+void
+Driver::run() {
+ init();
+
+ if (warmupRuns > 0) {
+ cout << endl
+ << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
+ << "warmup runs ..." << endl
+ << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
+
+ for (int i = 0; i < warmupRuns; i++) {
+ runTests();
+ }
+
+ // truncate log file, reset log buffers
+ closeLogFile();
+ openLogFile();
+ clearLogBuffers();
+ }
+
+ cout << endl
+ << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
+ << "hot runs ..." << endl
+ << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
+ runTests();
+
+ cout << endl
+ << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
+ close();
+}
+
+void
+Driver::init() {
+ loadProperties();
+ initProperties();
+ printProperties();
+ openLogFile();
+ clearLogBuffers();
+}
+
+void
+Driver::close() {
+ clearLogBuffers();
+ closeLogFile();
+}
+
+void
+Driver::loadProperties() {
+ cout << endl;
+ for (vector<string>::const_iterator i = propFileNames.begin();
+ i != propFileNames.end(); ++i) {
+ cout << "reading properties file: " << *i << endl;
+ props.load(i->c_str());
+ //cout << "props = {" << endl << props << "}" << endl;
+ }
+}
+
+void
+Driver::initProperties() {
+ cout << "setting driver properties ..." << flush;
+
+ ostringstream msg;
+
+ warmupRuns = toInt(props[L"warmupRuns"], 0, -1);
+ if (warmupRuns < 0) {
+ msg << "[ignored] warmupRuns: '"
+ << toString(props[L"warmupRuns"]) << "'" << endl;
+ warmupRuns = 0;
+ }
+
+ //if (msg.tellp() == 0) // netbeans reports amibuities
+ if (msg.str().empty()) {
+ cout << " [ok]" << endl;
+ } else {
+ cout << endl << msg.str() << endl;
+ }
+}
+
+void
+Driver::printProperties() {
+ const ios_base::fmtflags f = cout.flags();
+ // no effect calling manipulator function, not sure why
+ //cout << ios_base::boolalpha;
+ cout.flags(ios_base::boolalpha);
+
+ cout << endl << "driver settings ..." << endl;
+ cout << "warmupRuns: " << warmupRuns << endl;
+
+ cout.flags(f);
+}
+
+void
+Driver::openLogFile() {
+ cout << endl
+ << "opening results file:" << flush;
+ log.open(logFileName.c_str(), ios_base::out | ios_base::trunc);
+ assert(log.good());
+ cout << " [ok: " << logFileName << "]" << endl;
+}
+
+void
+Driver::closeLogFile() {
+ cout << endl
+ << "closing results file:" << flush;
+ log.close();
+ cout << " [ok: " << logFileName << "]" << endl;
+}
+
+// ---------------------------------------------------------------------------
+
+void
+Driver::clearLogBuffers() {
+ logHeader = true;
+ header.rdbuf()->str("");
+ rtimes.rdbuf()->str("");
+}
+
+void
+Driver::writeLogBuffers() {
+ log << descr << ", rtime[ms]"
+ << header.rdbuf()->str() << endl
+ << rtimes.rdbuf()->str() << endl;
+}
+
+void
+Driver::begin(const string& name) {
+ cout << endl;
+ cout << name << endl;
+
+ if (gettimeofday(&t0, NULL) != 0)
+ ABORT_GETTIMEOFDAY_ERROR();
+}
+
+void
+Driver::finish(const string& name) {
+ if (gettimeofday(&t1, NULL) != 0)
+ ABORT_GETTIMEOFDAY_ERROR();
+
+ const long r_usec = (((t1.tv_sec - t0.tv_sec) * 1000000)
+ + (t1.tv_usec - t0.tv_usec));
+ const long r_msec = r_usec / 1000;
+
+ cout << "tx real time: " << r_msec
+ << "\tms" << endl;
+ rtimes << "\t" << r_msec;
+ rta += r_msec;
+
+ if (logHeader)
+ header << "\t" << name;
+}
+
+//---------------------------------------------------------------------------
=== added file 'storage/ndb/test/crund/tws/tws_cpp/Driver.hpp'
--- a/storage/ndb/test/crund/tws/tws_cpp/Driver.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/crund/tws/tws_cpp/Driver.hpp 2010-10-19 22:52:04 +0000
@@ -0,0 +1,102 @@
+/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
+ *
+ * Copyright (C) 2010 MySQL
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef Driver_hpp
+#define Driver_hpp
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <sys/time.h>
+
+#include "Properties.hpp"
+
+using std::string;
+using std::vector;
+using std::ofstream;
+using std::ostringstream;
+
+using utils::Properties;
+
+class Driver {
+public:
+
+ /**
+ * Parses the benchmark's command-line arguments.
+ */
+ static void parseArguments(int argc, const char* argv[]);
+
+ /**
+ * Creates an instance.
+ */
+ Driver() {}
+
+ /**
+ * Deletes an instance.
+ */
+ virtual ~Driver() {}
+
+ /**
+ * Runs the benchmark.
+ */
+ void run();
+
+protected:
+
+ // command-line arguments
+ static vector< string > propFileNames;
+ static string logFileName;
+
+ static void exitUsage();
+
+ // driver settings
+ Properties props;
+ int warmupRuns;
+
+ // driver resources
+ ofstream log;
+ string descr;
+ bool logHeader;
+ ostringstream header;
+ ostringstream rtimes;
+ struct timeval t0, t1;
+ long rta;
+
+ // driver intializers/finalizers
+ virtual void init();
+ virtual void close();
+ virtual void loadProperties();
+ virtual void initProperties();
+ virtual void printProperties();
+ virtual void openLogFile();
+ virtual void closeLogFile();
+
+ // benchmark operations
+ virtual void runTests() = 0;
+ virtual void clearLogBuffers();
+ virtual void writeLogBuffers();
+ virtual void begin(const string& name);
+ virtual void finish(const string& name);
+};
+
+#endif // Driver_hpp
=== added file 'storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.cpp'
--- a/storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.cpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.cpp 2010-10-19 22:52:04 +0000
@@ -0,0 +1,941 @@
+/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
+ *
+ * Copyright (C) 2010 MySQL
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "NdbApiTwsDriver.hpp"
+
+#include <iostream>
+#include <string>
+#include <cassert>
+
+#include "helpers.hpp"
+#include "string_helpers.hpp"
+#include "Properties.hpp"
+
+using std::cout;
+using std::flush;
+using std::endl;
+using std::ios_base;
+using std::string;
+
+using utils::Properties;
+using utils::toBool;
+using utils::toInt;
+using utils::toString;
+
+// ---------------------------------------------------------------------------
+// Helper Macros & Functions
+// ---------------------------------------------------------------------------
+
+// This benchmark's error handling of NDBAPI calls is rigorous but crude:
+// - all calls' return value is checked for errors
+// - all errors are reported and then followed by a process exit
+#define ABORT_NDB_ERROR(error) \
+ do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \
+ << ", code: " << (int)(error).code \
+ << ", msg: " << (error).message << "." << endl; \
+ exit(-1); \
+ } while (0)
+
+// ---------------------------------------------------------------------------
+// NDB API Model Implementation
+// ---------------------------------------------------------------------------
+
+NdbApiTwsModel::NdbApiTwsModel(Ndb* ndb) {
+ const NdbDictionary::Dictionary* dict = ndb->getDictionary();
+
+ // get table T0
+ if ((table_t0 = dict->getTable("mytable")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+
+ // get columns of table T0
+ if ((column_c0 = table_t0->getColumn("c0")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c1 = table_t0->getColumn("c1")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c2 = table_t0->getColumn("c2")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c3 = table_t0->getColumn("c3")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c4 = table_t0->getColumn("c4")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c5 = table_t0->getColumn("c5")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c6 = table_t0->getColumn("c6")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c7 = table_t0->getColumn("c7")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c8 = table_t0->getColumn("c8")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c9 = table_t0->getColumn("c9")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c10 = table_t0->getColumn("c10")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c11 = table_t0->getColumn("c11")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c12 = table_t0->getColumn("c12")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c13 = table_t0->getColumn("c13")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+ if ((column_c14 = table_t0->getColumn("c14")) == NULL)
+ ABORT_NDB_ERROR(dict->getNdbError());
+
+ // get attribute ids for columns of table T0
+ attr_c0 = column_c0->getAttrId();
+ attr_c1 = column_c1->getAttrId();
+ attr_c2 = column_c2->getAttrId();
+ attr_c3 = column_c3->getAttrId();
+ attr_c4 = column_c4->getAttrId();
+ attr_c5 = column_c5->getAttrId();
+ attr_c6 = column_c6->getAttrId();
+ attr_c7 = column_c7->getAttrId();
+ attr_c8 = column_c8->getAttrId();
+ attr_c9 = column_c9->getAttrId();
+ attr_c10 = column_c10->getAttrId();
+ attr_c11 = column_c11->getAttrId();
+ attr_c12 = column_c12->getAttrId();
+ attr_c13 = column_c13->getAttrId();
+ attr_c14 = column_c14->getAttrId();
+
+ width_c0 = columnWidth(column_c0);
+ width_c1 = columnWidth(column_c1);
+ width_c2 = columnWidth(column_c2);
+ width_c3 = columnWidth(column_c3);
+ width_c4 = columnWidth(column_c4);
+ width_c5 = columnWidth(column_c5);
+ width_c6 = columnWidth(column_c6);
+ width_c7 = columnWidth(column_c7);
+ width_c8 = columnWidth(column_c8);
+ width_c9 = columnWidth(column_c9);
+ width_c10 = columnWidth(column_c10);
+ width_c11 = columnWidth(column_c11);
+ width_c12 = columnWidth(column_c12);
+ width_c13 = columnWidth(column_c13);
+ width_c14 = columnWidth(column_c14);
+
+ width_row = (
+ + width_c0
+ + width_c1
+ + width_c2
+ + width_c3
+ + width_c4
+ + width_c5
+ + width_c6
+ + width_c7
+ + width_c8
+ + width_c9
+ + width_c10
+ + width_c11
+ + width_c12
+ + width_c13
+ + width_c14);
+}
+
+// ---------------------------------------------------------------------------
+// NdbApiTwsDriver Implementation
+// ---------------------------------------------------------------------------
+
+void
+NdbApiTwsDriver::init() {
+ TwsDriver::init();
+
+ // ndb_init must be called first
+ cout << endl
+ << "initializing NDBAPI ..." << flush;
+ int stat = ndb_init();
+ if (stat != 0)
+ ABORT_ERROR("ndb_init() returned: " << stat);
+ cout << " [ok]" << endl;
+
+ initConnection();
+}
+
+void
+NdbApiTwsDriver::close() {
+ closeConnection();
+
+ // ndb_close must be called last
+ cout << "closing NDBAPI ... " << flush;
+ ndb_end(0);
+ cout << " [ok]" << endl;
+
+ TwsDriver::close();
+}
+
+void
+NdbApiTwsDriver::initProperties() {
+ TwsDriver::initProperties();
+
+ cout << "setting ndb properties ..." << flush;
+
+ ostringstream msg;
+
+ mgmdConnect = toString(props[L"ndb.mgmdConnect"]);
+ if (mgmdConnect.empty()) {
+ mgmdConnect = string("localhost");
+ }
+
+ catalog = toString(props[L"ndb.catalog"]);
+ if (catalog.empty()) {
+ catalog = string("testdb");
+ }
+
+ schema = toString(props[L"ndb.schema"]);
+ if (schema.empty()) {
+ schema = string("def");
+ }
+
+ //if (msg.tellp() == 0) {
+ if (msg.str().empty()) {
+ cout << " [ok]" << endl;
+ } else {
+ cout << endl << msg.str() << endl;
+ }
+
+ descr = "ndbapi(" + mgmdConnect + ")";
+}
+
+void
+NdbApiTwsDriver::printProperties() {
+ TwsDriver::printProperties();
+
+ const ios_base::fmtflags f = cout.flags();
+ // no effect calling manipulator function, not sure why
+ //cout << ios_base::boolalpha;
+ cout.flags(ios_base::boolalpha);
+
+ cout << endl << "ndb settings ..." << endl;
+ cout << "ndb.mgmdConnect: \"" << mgmdConnect << "\"" << endl;
+ cout << "ndb.catalog: \"" << catalog << "\"" << endl;
+ cout << "ndb.schema: \"" << schema << "\"" << endl;
+
+ cout.flags(f);
+}
+
+void
+NdbApiTwsDriver::initNdbapiBuffers() {
+ assert(model->column_c0 != NULL);
+ assert(bb == NULL);
+ assert(ra == NULL);
+
+ cout << "allocating ndbapi buffers ..." << flush;
+ bb = new char[model->width_row * nRows];
+ ra = new NdbRecAttr*[model->nCols * nRows];
+ cout << " [ok]" << endl;
+}
+
+void
+NdbApiTwsDriver::closeNdbapiBuffers() {
+ assert(bb != NULL);
+ assert(ra != NULL);
+
+ cout << "releasing ndbapi buffers ..." << flush;
+ delete[] ra;
+ ra = NULL;
+ delete[] bb;
+ bb = NULL;
+ cout << " [ok]" << endl;
+}
+
+// ---------------------------------------------------------------------------
+
+void
+NdbApiTwsDriver::runLoadOperations() {
+ cout << endl
+ << "running NDB API operations ..." << " [nRows=" << nRows << "]"
+ << endl;
+
+ if (doSingle) {
+ if (doInsert) runNdbapiInsert(SINGLE);
+ if (doLookup) runNdbapiLookup(SINGLE);
+ if (doUpdate) runNdbapiUpdate(SINGLE);
+ if (doDelete) runNdbapiDelete(SINGLE);
+ }
+ if (doBulk) {
+ if (doInsert) runNdbapiInsert(BULK);
+ if (doLookup) runNdbapiLookup(BULK);
+ if (doUpdate) runNdbapiUpdate(BULK);
+ if (doDelete) runNdbapiDelete(BULK);
+ }
+ if (doBatch) {
+ if (doInsert) runNdbapiInsert(BATCH);
+ if (doLookup) runNdbapiLookup(BATCH);
+ if (doUpdate) runNdbapiUpdate(BATCH);
+ if (doDelete) runNdbapiDelete(BATCH);
+ }
+}
+
+// Alternative Implementation:
+// The recurring pattern of runNdbapiXXX(XMode mode) can be parametrized
+// over the operation, for instance, by a member function template:
+//
+// template< XMode M, void (NdbApiTwsDriver::*OP)(int) >
+// void runOp(string name);
+//
+// which tests the template parameter XMode and calls the operation
+// ...
+// if (M == SINGLE) {
+// ... (this->*OP)(i); ...
+// }
+// ...
+// while the caller selects the mode and function to be invoked
+// ...
+// switch (mode) {
+// case SINGLE:
+// runOp< SINGLE, &NdbApiTwsDriver::ndbapiInsert >(name);
+// }...
+// Alas, it turns out not worth it in terms of readability and lines of code.
+
+void
+NdbApiTwsDriver::runNdbapiInsert(XMode mode) {
+ const string name = string("insert_") + toStr(mode);
+ begin(name);
+
+ if (mode == SINGLE) {
+ for(int i = 0; i < nRows; i++) {
+ ndbapiBeginTransaction();
+ ndbapiInsert(i);
+ ndbapiCommitTransaction();
+ ndbapiCloseTransaction();
+ }
+ } else {
+ ndbapiBeginTransaction();
+ for(int i = 0; i < nRows; i++) {
+ ndbapiInsert(i);
+ if (mode == BULK)
+ ndbapiExecuteTransaction();
+ }
+ ndbapiCommitTransaction();
+ ndbapiCloseTransaction();
+ }
+
+ finish(name);
+}
+
+void
+NdbApiTwsDriver::ndbapiInsert(int c0) {
+ // get an insert operation for the table
+ NdbOperation* op = tx->getNdbOperation(model->table_t0);
+ if (op == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ if (op->insertTuple() != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+
+ // values
+ Uint32 i = c0;
+ const int maxlen = 256;
+ char str[maxlen];
+ snprintf(str, maxlen, "%d", i);
+
+ // set values; key attribute needs to be set first
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
+ if (op->equal(model->attr_c0, bb_pos) != 0) // key
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c0;
+
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c1);
+ if (op->setValue(model->attr_c1, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c1;
+
+ if (op->setValue(model->attr_c2, i) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c2;
+
+ if (op->setValue(model->attr_c3, i) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c3;
+
+ if (op->setValue(model->attr_c4, (char*)NULL) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c4;
+
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c5);
+ if (op->setValue(model->attr_c5, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c5;
+
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c6);
+ if (op->setValue(model->attr_c6, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c6;
+
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c7);
+ if (op->setValue(model->attr_c7, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c7;
+
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c8);
+ if (op->setValue(model->attr_c8, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c8;
+
+ if (op->setValue(model->attr_c9, (char*)NULL) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c9;
+
+ if (op->setValue(model->attr_c10, (char*)NULL) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c10;
+
+ if (op->setValue(model->attr_c11, (char*)NULL) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c11;
+
+ if (op->setValue(model->attr_c12, (char*)NULL) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c12;
+
+ if (op->setValue(model->attr_c13, (char*)NULL) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c13;
+
+ if (op->setValue(model->attr_c14, (char*)NULL) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c14;
+}
+
+void
+NdbApiTwsDriver::runNdbapiLookup(XMode mode) {
+ const string name = string("lookup_") + toStr(mode);
+ begin(name);
+
+ if (mode == SINGLE) {
+ for(int i = 0; i < nRows; i++) {
+ ndbapiBeginTransaction();
+ ndbapiLookup(i);
+ ndbapiCommitTransaction();
+ ndbapiRead(i);
+ ndbapiCloseTransaction();
+ }
+ } else {
+ ndbapiBeginTransaction();
+ for(int i = 0; i < nRows; i++) {
+ ndbapiLookup(i);
+
+ if (mode == BULK)
+ ndbapiExecuteTransaction();
+ }
+ ndbapiCommitTransaction();
+ for(int i = 0; i < nRows; i++) {
+ ndbapiRead(i);
+ }
+ ndbapiCloseTransaction();
+ }
+
+ finish(name);
+}
+
+void
+NdbApiTwsDriver::ndbapiLookup(int c0) {
+ // get a lookup operation for the table
+ NdbOperation* op = tx->getNdbOperation(model->table_t0);
+ if (op == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ if (op->readTuple(ndbOpLockMode) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+
+ // values
+ Uint32 i = c0;
+ const int maxlen = 256;
+ char str[maxlen];
+ snprintf(str, maxlen, "%d", i);
+
+ // set values; key attribute needs to be set first
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
+ if (op->equal(model->attr_c0, bb_pos) != 0) // key
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c0;
+
+ // get attributes (not readable until after commit)
+ if ((*ra_pos = op->getValue(model->attr_c1, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c1;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c2, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c2;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c3, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c3;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c4, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c4;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c5, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c5;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c6, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c6;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c7, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c7;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c8, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c8;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c9, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c9;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c10, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c10;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c11, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c11;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c12, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c12;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c13, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c13;
+ ra_pos++;
+
+ if ((*ra_pos = op->getValue(model->attr_c14, bb_pos)) == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c14;
+ ra_pos++;
+}
+
+void
+NdbApiTwsDriver::ndbapiRead(int c0) {
+ // values
+ const int maxlen = 256;
+ char str0[maxlen];
+ snprintf(str0, maxlen, "%d", c0);
+ Int32 i1;
+ char str1[maxlen];
+
+ // no need to read key column
+ bb_pos += model->width_c0;
+
+ ndbapiToString1blp(str1, bb_pos, model->width_c1);
+ verify(str0, str1);
+ bb_pos += model->width_c1;
+ ra_pos++;
+
+ memcpy(&i1, bb_pos, model->width_c2);
+ verify(c0, i1);
+ bb_pos += model->width_c2;
+ ra_pos++;
+
+ memcpy(&i1, bb_pos, model->width_c3);
+ verify(c0, i1);
+ bb_pos += model->width_c3;
+ ra_pos++;
+
+ // null expected
+ verify(1, (*ra_pos)->isNULL());
+ bb_pos += model->width_c4;
+ ra_pos++;
+
+ ndbapiToString1blp(str1, bb_pos, model->width_c5);
+ verify(str0, str1);
+ bb_pos += model->width_c5;
+ ra_pos++;
+
+ ndbapiToString1blp(str1, bb_pos, model->width_c6);
+ verify(str0, str1);
+ bb_pos += model->width_c6;
+ ra_pos++;
+
+ ndbapiToString1blp(str1, bb_pos, model->width_c7);
+ verify(str0, str1);
+ bb_pos += model->width_c7;
+ ra_pos++;
+
+ ndbapiToString1blp(str1, bb_pos, model->width_c8);
+ verify(str0, str1);
+ bb_pos += model->width_c8;
+ ra_pos++;
+
+ // null expected
+ verify(1, (*ra_pos)->isNULL());
+ bb_pos += model->width_c9;
+ ra_pos++;
+
+ // null expected
+ verify(1, (*ra_pos)->isNULL());
+ bb_pos += model->width_c10;
+ ra_pos++;
+
+ // null expected
+ verify(1, (*ra_pos)->isNULL());
+ bb_pos += model->width_c11;
+ ra_pos++;
+
+ // null expected
+ verify(1, (*ra_pos)->isNULL());
+ bb_pos += model->width_c12;
+ ra_pos++;
+
+ // null expected
+ verify(1, (*ra_pos)->isNULL());
+ bb_pos += model->width_c13;
+ ra_pos++;
+
+ // null expected
+ verify(1, (*ra_pos)->isNULL());
+ bb_pos += model->width_c14;
+ ra_pos++;
+}
+
+void
+NdbApiTwsDriver::runNdbapiUpdate(XMode mode) {
+ const string name = string("update_") + toStr(mode);
+ begin(name);
+
+ if (mode == SINGLE) {
+ for(int i = 0; i < nRows; i++) {
+ ndbapiBeginTransaction();
+ ndbapiUpdate(i);
+ ndbapiCommitTransaction();
+ ndbapiCloseTransaction();
+ }
+ } else {
+ ndbapiBeginTransaction();
+ for(int i = 0; i < nRows; i++) {
+ ndbapiUpdate(i);
+ if (mode == BULK)
+ ndbapiExecuteTransaction();
+ }
+ ndbapiCommitTransaction();
+ ndbapiCloseTransaction();
+ }
+
+ finish(name);
+}
+
+void
+NdbApiTwsDriver::ndbapiUpdate(int c0) {
+ // get an update operation for the table
+ NdbOperation* op = tx->getNdbOperation(model->table_t0);
+ if (op == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ if (op->updateTuple() != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+
+ // values
+ const int maxlen = 256;
+ char str0[maxlen];
+ snprintf(str0, maxlen, "%d", c0);
+ int i = -c0;
+ char str1[maxlen];
+ snprintf(str1, maxlen, "%d", i);
+
+ // set values; key attribute needs to be set first
+ ndbapiToBuffer1blp(bb_pos, str0, model->width_c0);
+ if (op->equal(model->attr_c0, bb_pos) != 0) // key
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c0;
+
+ ndbapiToBuffer1blp(bb_pos, str1, model->width_c1);
+ if (op->setValue(model->attr_c1, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c1;
+
+ if (op->setValue(model->attr_c2, i) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c2;
+
+ if (op->setValue(model->attr_c3, i) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c3;
+
+ ndbapiToBuffer1blp(bb_pos, str1, model->width_c5);
+ if (op->setValue(model->attr_c5, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c5;
+
+ ndbapiToBuffer1blp(bb_pos, str1, model->width_c6);
+ if (op->setValue(model->attr_c6, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c6;
+
+ ndbapiToBuffer1blp(bb_pos, str1, model->width_c7);
+ if (op->setValue(model->attr_c7, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c7;
+
+ ndbapiToBuffer1blp(bb_pos, str1, model->width_c8);
+ if (op->setValue(model->attr_c8, bb_pos) != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c8;
+}
+
+void
+NdbApiTwsDriver::runNdbapiDelete(XMode mode) {
+ const string name = string("delete_") + toStr(mode);
+ begin(name);
+
+ if (mode == SINGLE) {
+ for(int i = 0; i < nRows; i++) {
+ ndbapiBeginTransaction();
+ ndbapiDelete(i);
+ ndbapiCommitTransaction();
+ ndbapiCloseTransaction();
+ }
+ } else {
+ ndbapiBeginTransaction();
+ for(int i = 0; i < nRows; i++) {
+ ndbapiDelete(i);
+ if (mode == BULK)
+ ndbapiExecuteTransaction();
+ }
+ ndbapiCommitTransaction();
+ ndbapiCloseTransaction();
+ }
+
+ finish(name);
+}
+
+void
+NdbApiTwsDriver::ndbapiDelete(int c0) {
+ // get a delete operation for the table
+ NdbOperation* op = tx->getNdbOperation(model->table_t0);
+ if (op == NULL)
+ ABORT_NDB_ERROR(tx->getNdbError());
+ if (op->deleteTuple() != 0)
+ ABORT_NDB_ERROR(tx->getNdbError());
+
+ // values
+ Uint32 i = c0;
+ const int maxlen = 256;
+ char str[maxlen];
+ snprintf(str, maxlen, "%d", i);
+
+ // set values; key attribute needs to be set first
+ ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
+ if (op->equal(model->attr_c0, bb_pos) != 0) // key
+ ABORT_NDB_ERROR(tx->getNdbError());
+ bb_pos += model->width_c0;
+}
+
+// ----------------------------------------------------------------------
+
+void
+NdbApiTwsDriver::ndbapiBeginTransaction() {
+ assert(tx == NULL);
+
+ // prepare buffer for writing
+ bb_pos = bb; // clear
+ ra_pos = ra;
+
+ // start a transaction
+ // must be closed with Ndb::closeTransaction or NdbTransaction::close
+ if ((tx = ndb->startTransaction()) == NULL)
+ ABORT_NDB_ERROR(ndb->getNdbError());
+}
+
+void
+NdbApiTwsDriver::ndbapiExecuteTransaction() {
+ assert(tx != NULL);
+
+ // execute but don't commit the current transaction
+ if (tx->execute(NdbTransaction::NoCommit) != 0
+ || tx->getNdbError().status != NdbError::Success)
+ ABORT_NDB_ERROR(tx->getNdbError());
+}
+
+void
+NdbApiTwsDriver::ndbapiCommitTransaction() {
+ assert(tx != NULL);
+
+ // commit the current transaction
+ if (tx->execute(NdbTransaction::Commit) != 0
+ || tx->getNdbError().status != NdbError::Success)
+ ABORT_NDB_ERROR(tx->getNdbError());
+
+ // prepare buffer for reading
+ bb_pos = bb; // rewind
+ ra_pos = ra;
+}
+
+void
+NdbApiTwsDriver::ndbapiCloseTransaction() {
+ assert(tx != NULL);
+
+ // close the current transaction
+ // to be called irrespectively of success or failure
+ ndb->closeTransaction(tx);
+ tx = NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+void
+NdbApiTwsDriver::initConnection() {
+ assert(mgmd == NULL);
+ assert(ndb == NULL);
+ assert(tx == NULL);
+ assert(model == NULL);
+
+ cout << endl;
+
+ // instantiate NDB cluster singleton
+ cout << "creating cluster connection ..." << flush;
+ assert(!mgmdConnect.empty());
+ mgmd = new Ndb_cluster_connection(mgmdConnect.c_str());
+ cout << " [ok]" << endl; // no useful mgmd->string conversion
+
+ // connect to cluster management node (ndb_mgmd)
+ cout << "connecting to mgmd ..." << flush;
+ const int retries = 0; // number of retries (< 0 = indefinitely)
+ const int delay = 0; // seconds to wait after retry
+ const int verbose = 1; // print report of progess
+ // returns: 0 = success, 1 = recoverable error, -1 = non-recoverable error
+ if (mgmd->connect(retries, delay, verbose) != 0)
+ ABORT_ERROR("mgmd@" << mgmdConnect << " was not ready within "
+ << (retries * delay) << "s.");
+ cout << " [ok: " << mgmdConnect << "]" << endl;
+
+ // optionally, connect and wait for reaching the data nodes (ndbds)
+ cout << "waiting for data nodes ..." << flush;
+ const int initial_wait = 10; // seconds to wait until first node detected
+ const int final_wait = 0; // seconds to wait after first node detected
+ // returns: 0 all nodes live, > 0 at least one node live, < 0 error
+ if (mgmd->wait_until_ready(initial_wait, final_wait) < 0)
+ ABORT_ERROR("data nodes were not ready within "
+ << (initial_wait + final_wait) << "s.");
+ cout << " [ok]" << endl;
+
+ // connect to database
+ cout << "connecting to database ..." << flush;
+ ndb = new Ndb(mgmd, catalog.c_str(), schema.c_str());
+ const int max_no_tx = 10; // maximum number of parallel tx (<=1024)
+ // note each scan or index scan operation uses one extra transaction
+ //if (ndb->init() != 0)
+ if (ndb->init(max_no_tx) != 0)
+ ABORT_NDB_ERROR(ndb->getNdbError());
+ cout << " [ok: " << catalog << "." << schema << "]" << endl;
+
+ cout << "caching metadata ..." << flush;
+ model = new NdbApiTwsModel(ndb);
+ cout << " [ok]" << endl;
+
+ initNdbapiBuffers();
+
+ cout << "using lock mode for reads ..." << flush;
+ string lm;
+ switch (lockMode) {
+ case READ_COMMITTED:
+ ndbOpLockMode = NdbOperation::LM_CommittedRead;
+ lm = "LM_CommittedRead";
+ break;
+ case SHARED:
+ ndbOpLockMode = NdbOperation::LM_Read;
+ lm = "LM_Read";
+ break;
+ case EXCLUSIVE:
+ ndbOpLockMode = NdbOperation::LM_Exclusive;
+ lm = "LM_Exclusive";
+ break;
+ default:
+ ndbOpLockMode = NdbOperation::LM_CommittedRead;
+ lm = "LM_CommittedRead";
+ assert(false);
+ }
+ cout << " [ok: " + lm + "]" << endl;
+}
+
+void
+NdbApiTwsDriver::closeConnection() {
+ assert(mgmd != NULL);
+ assert(ndb != NULL);
+ assert(tx == NULL);
+ assert(model != NULL);
+
+ cout << endl;
+
+ closeNdbapiBuffers();
+
+ cout << "clearing metadata cache ..." << flush;
+ delete model;
+ model = NULL;
+ cout << " [ok]" << endl;
+
+ cout << "closing database connection ..." << flush;
+ // no ndb->close();
+ delete ndb;
+ ndb = NULL;
+ cout << " [ok]" << endl;
+
+ cout << "closing cluster connection ..." << flush;
+ delete mgmd;
+ mgmd = NULL;
+ cout << " [ok]" << endl;
+}
+
+//---------------------------------------------------------------------------
+
+void
+NdbApiTwsDriver::ndbapiToBuffer1blp(void* to, const char* from, size_t width) {
+ char* t = (char*)to;
+ size_t n = strlen(from);
+ assert(0 <= n && n < width && width < 256); // width <= 256 ?
+
+ memcpy(t + 1, from, n);
+ *t = n;
+}
+
+void
+NdbApiTwsDriver::ndbapiToString1blp(char* to, const void* from, size_t width) {
+ const char* s = (const char*)from;
+ size_t n = *s;
+ assert(0 <= n && n < width && width < 256); // width <= 256 ?
+
+ memcpy(to, s + 1, n);
+ to[n] = '\0';
+}
+
+// ---------------------------------------------------------------------------
+
+int
+main(int argc, const char* argv[])
+{
+ NdbApiTwsDriver::parseArguments(argc, argv);
+ NdbApiTwsDriver d;
+ d.run();
+
+ return 0;
+}
+
+//---------------------------------------------------------------------------
=== added file 'storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.hpp'
--- a/storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/crund/tws/tws_cpp/NdbApiTwsDriver.hpp 2010-10-19 22:52:04 +0000
@@ -0,0 +1,172 @@
+/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
+ *
+ * Copyright (C) 2010 MySQL
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef NdbApiTwsDriver_hpp
+#define NdbApiTwsDriver_hpp
+
+#include "TwsDriver.hpp"
+
+#include <NdbApi.hpp>
+#include <NdbError.hpp>
+
+using std::string;
+
+struct NdbApiTwsModel {
+ const NdbDictionary::Table* table_t0;
+ const NdbDictionary::Column* column_c0;
+ const NdbDictionary::Column* column_c1;
+ const NdbDictionary::Column* column_c2;
+ const NdbDictionary::Column* column_c3;
+ const NdbDictionary::Column* column_c4;
+ const NdbDictionary::Column* column_c5;
+ const NdbDictionary::Column* column_c6;
+ const NdbDictionary::Column* column_c7;
+ const NdbDictionary::Column* column_c8;
+ const NdbDictionary::Column* column_c9;
+ const NdbDictionary::Column* column_c10;
+ const NdbDictionary::Column* column_c11;
+ const NdbDictionary::Column* column_c12;
+ const NdbDictionary::Column* column_c13;
+ const NdbDictionary::Column* column_c14;
+
+ int attr_c0;
+ int attr_c1;
+ int attr_c2;
+ int attr_c3;
+ int attr_c4;
+ int attr_c5;
+ int attr_c6;
+ int attr_c7;
+ int attr_c8;
+ int attr_c9;
+ int attr_c10;
+ int attr_c11;
+ int attr_c12;
+ int attr_c13;
+ int attr_c14;
+
+ int width_c0;
+ int width_c1;
+ int width_c2;
+ int width_c3;
+ int width_c4;
+ int width_c5;
+ int width_c6;
+ int width_c7;
+ int width_c8;
+ int width_c9;
+ int width_c10;
+ int width_c11;
+ int width_c12;
+ int width_c13;
+ int width_c14;
+ int width_row; // sum of {width_c0 .. width_c14}
+ static const int nCols = 15;
+
+ NdbApiTwsModel(Ndb* ndb);
+
+ ~NdbApiTwsModel() {}
+
+ static int columnWidth(const NdbDictionary::Column* c) {
+ int s = c->getSize(); // size of type or of base type
+ int al = c->getLength(); // length or max length, 1 for scalars
+ int at = c->getArrayType(); // size of length prefix, practically
+ return (s * al) + at;
+ }
+
+private:
+
+ NdbApiTwsModel(const NdbApiTwsModel&);
+ NdbApiTwsModel& operator=(const NdbApiTwsModel&);
+};
+
+class NdbApiTwsDriver : public TwsDriver {
+public:
+
+ NdbApiTwsDriver()
+ : mgmd(NULL), ndb(NULL), tx(NULL), model(NULL), bb(NULL), ra(NULL) {
+ }
+
+ virtual ~NdbApiTwsDriver() {
+ assert(mgmd == NULL); assert(ndb == NULL); assert(tx == NULL);
+ assert(model == NULL); assert(bb == NULL); assert(ra == NULL);
+ }
+
+private:
+
+ NdbApiTwsDriver(const NdbApiTwsDriver&);
+ NdbApiTwsDriver& operator=(const NdbApiTwsDriver&);
+
+protected:
+
+ // NDB API settings
+ string mgmdConnect;
+ string catalog;
+ string schema;
+
+ // NDB API resources
+ Ndb_cluster_connection* mgmd;
+ Ndb* ndb;
+ NdbTransaction* tx;
+ NdbOperation::LockMode ndbOpLockMode;
+
+ // NDB Api metadata resources
+ NdbApiTwsModel* model;
+
+ // NDB Api data resources
+ char* bb;
+ char* bb_pos;
+ NdbRecAttr** ra;
+ NdbRecAttr** ra_pos;
+
+ // NDB API intializers/finalizers
+ virtual void init();
+ virtual void close();
+ virtual void initProperties();
+ virtual void printProperties();
+ void initNdbapiBuffers();
+ void closeNdbapiBuffers();
+
+ // NDB API operations
+ virtual void runLoadOperations();
+ void runNdbapiInsert(XMode mode);
+ void ndbapiInsert(int c0);
+ void runNdbapiLookup(XMode mode);
+ void ndbapiLookup(int c0);
+ void ndbapiRead(int c0);
+ void runNdbapiUpdate(XMode mode);
+ void ndbapiUpdate(int c0);
+ void runNdbapiDelete(XMode mode);
+ void ndbapiDelete(int c0);
+ void ndbapiBeginTransaction();
+ void ndbapiExecuteTransaction();
+ void ndbapiCommitTransaction();
+ void ndbapiCloseTransaction();
+ static void ndbapiToBuffer1blp(void* to, const char* from, size_t width);
+ static void ndbapiToString1blp(char* to, const void* from, size_t width);
+
+ // NDB API datastore operations
+ virtual void initConnection();
+ virtual void closeConnection();
+ //virtual void clearPersistenceContext(); // not used
+ //virtual void clearData(); // not used
+};
+
+#endif // NdbApiTwsDriver_hpp
=== modified file 'storage/ndb/test/crund/tws/tws_cpp/TwsDriver.cpp'
--- a/storage/ndb/test/crund/tws/tws_cpp/TwsDriver.cpp 2010-10-08 11:14:56 +0000
+++ b/storage/ndb/test/crund/tws/tws_cpp/TwsDriver.cpp 2010-10-19 22:52:04 +0000
@@ -18,20 +18,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <cstdlib>
+#include "TwsDriver.hpp"
+
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
-#include <vector>
#include <cassert>
-#include <algorithm>
-#include <cctype>
-
-#include <sys/time.h>
-
-#include <NdbApi.hpp>
-#include <NdbError.hpp>
#include "helpers.hpp"
#include "string_helpers.hpp"
@@ -42,9 +35,6 @@ using std::flush;
using std::endl;
using std::ios_base;
using std::string;
-using std::wstring;
-using std::vector;
-using std::ofstream;
using std::ostringstream;
using utils::Properties;
@@ -53,270 +43,9 @@ using utils::toInt;
using utils::toString;
// ---------------------------------------------------------------------------
-
-class Driver {
-public:
-
- /**
- * Parses the benchmark's command-line arguments.
- */
- static void parseArguments(int argc, const char* argv[]);
-
- /**
- * Creates an instance.
- */
- Driver() {}
-
- /**
- * Deletes an instance.
- */
- virtual ~Driver() {}
-
- /**
- * Runs the benchmark.
- */
- void run();
-
-protected:
-
- // command-line arguments
- static vector< string > propFileNames;
- static string logFileName;
-
- static void exitUsage();
-
- // driver settings
- Properties props;
- bool renewConnection;
- int warmupRuns;
- int hotRuns;
-
- // driver resources
- ofstream log;
- string descr;
- bool logHeader;
- ostringstream header;
- ostringstream rtimes;
- struct timeval t0, t1;
- long rta;
-
- // driver intializers/finalizers
- virtual void init();
- virtual void close();
- virtual void loadProperties();
- virtual void initProperties();
- virtual void printProperties();
- virtual void openLogFile();
- virtual void closeLogFile();
-
- // benchmark operations
- virtual void runTests() = 0;
- virtual void begin(const string& name);
- virtual void commit(const string& name);
-
- // datastore operations
- virtual void initConnection() = 0;
- virtual void closeConnection() = 0;
- //virtual void clearPersistenceContext() = 0; // not used
- //virtual void clearData() = 0; // not used
-};
-
-// ---------------------------------------------------------------------------
-
-class TwsDriver : public Driver {
-protected:
-
- // benchmark settings
- enum LockMode { READ_COMMITTED, SHARED, EXCLUSIVE };
- static const char* toStr(LockMode mode);
- enum XMode { SINGLE, BULK, BATCH };
- static const char* toStr(XMode mode);
- bool doInsert;
- bool doLookup;
- bool doUpdate;
- bool doDelete;
- bool doSingle;
- bool doBulk;
- bool doBatch;
- bool doVerify;
- LockMode lockMode;
- int nRows;
-
- // benchmark intializers/finalizers
- virtual void initProperties();
- virtual void printProperties();
-
- // benchmark operations
- virtual void runTests();
- virtual void runLoads();
- virtual void runOperations() = 0;
- void verify(Int32 exp, Int32 act);
- void verify(const char* exp, const char* act);
-};
-
-// ---------------------------------------------------------------------------
-
-struct NdbApiTwsModel {
- const NdbDictionary::Table* table_t0;
- const NdbDictionary::Column* column_c0;
- const NdbDictionary::Column* column_c1;
- const NdbDictionary::Column* column_c2;
- const NdbDictionary::Column* column_c3;
- const NdbDictionary::Column* column_c4;
- const NdbDictionary::Column* column_c5;
- const NdbDictionary::Column* column_c6;
- const NdbDictionary::Column* column_c7;
- const NdbDictionary::Column* column_c8;
- const NdbDictionary::Column* column_c9;
- const NdbDictionary::Column* column_c10;
- const NdbDictionary::Column* column_c11;
- const NdbDictionary::Column* column_c12;
- const NdbDictionary::Column* column_c13;
- const NdbDictionary::Column* column_c14;
-
- int attr_c0;
- int attr_c1;
- int attr_c2;
- int attr_c3;
- int attr_c4;
- int attr_c5;
- int attr_c6;
- int attr_c7;
- int attr_c8;
- int attr_c9;
- int attr_c10;
- int attr_c11;
- int attr_c12;
- int attr_c13;
- int attr_c14;
-
- int width_c0;
- int width_c1;
- int width_c2;
- int width_c3;
- int width_c4;
- int width_c5;
- int width_c6;
- int width_c7;
- int width_c8;
- int width_c9;
- int width_c10;
- int width_c11;
- int width_c12;
- int width_c13;
- int width_c14;
- int width_row; // sum of {width_c0 .. width_c14}
- static const int nCols = 15;
-
- NdbApiTwsModel(Ndb* ndb);
-
- ~NdbApiTwsModel() {}
-
- static int columnWidth(const NdbDictionary::Column* c) {
- int s = c->getSize(); // size of type or of base type
- int al = c->getLength(); // length or max length, 1 for scalars
- int at = c->getArrayType(); // size of length prefix, practically
- return (s * al) + at;
- }
-
-private:
-
- NdbApiTwsModel(const NdbApiTwsModel&);
- NdbApiTwsModel& operator=(const NdbApiTwsModel&);
-};
-
-class NdbApiTwsDriver : public TwsDriver {
-public:
-
- NdbApiTwsDriver()
- : mgmd(NULL), ndb(NULL), tx(NULL), model(NULL), bb(NULL), ra(NULL) {
- }
-
- virtual ~NdbApiTwsDriver() {
- assert(mgmd == NULL); assert(ndb == NULL); assert(tx == NULL);
- assert(model == NULL); assert(bb == NULL); assert(ra == NULL);
- }
-
-private:
-
- NdbApiTwsDriver(const NdbApiTwsDriver&);
- NdbApiTwsDriver& operator=(const NdbApiTwsDriver&);
-
-protected:
-
- // NDB API settings
- string mgmdConnect;
- string catalog;
- string schema;
-
- // NDB API resources
- Ndb_cluster_connection* mgmd;
- Ndb* ndb;
- NdbTransaction* tx;
- NdbOperation::LockMode ndbOpLockMode;
-
- // NDB Api metadata resources
- NdbApiTwsModel* model;
-
- // NDB Api data resources
- char* bb;
- char* bb_pos;
- NdbRecAttr** ra;
- NdbRecAttr** ra_pos;
-
- // NDB API intializers/finalizers
- virtual void initProperties();
- virtual void printProperties();
- virtual void init();
- virtual void close();
- void initNdbapiBuffers();
- void closeNdbapiBuffers();
-
- // NDB API operations
- virtual void runOperations();
- void runNdbapiInsert(XMode mode);
- void ndbapiInsert(int c0);
- void runNdbapiLookup(XMode mode);
- void ndbapiLookup(int c0);
- void ndbapiRead(int c0);
- void runNdbapiUpdate(XMode mode);
- void ndbapiUpdate(int c0);
- void runNdbapiDelete(XMode mode);
- void ndbapiDelete(int c0);
- void ndbapiBeginTransaction();
- void ndbapiExecuteTransaction();
- void ndbapiCommitTransaction();
- void ndbapiCloseTransaction();
- static void ndbapiToBuffer1blp(void* to, const char* from, size_t width);
- static void ndbapiToString1blp(char* to, const void* from, size_t width);
-
- // NDB API datastore operations
- virtual void initConnection();
- virtual void closeConnection();
- //virtual void clearPersistenceContext(); // not used
- //virtual void clearData(); // not used
-};
-
-// ---------------------------------------------------------------------------
// Helper Macros & Functions
// ---------------------------------------------------------------------------
-// This benchmark's error handling of NDBAPI calls is rigorous but crude:
-// - all calls' return value is checked for errors
-// - all errors are reported and then followed by a process exit
-#define ABORT_NDB_ERROR(error) \
- do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \
- << ", code: " << (int)(error).code \
- << ", msg: " << (error).message << "." << endl; \
- exit(-1); \
- } while (0)
-
-#define ABORT_GETTIMEOFDAY_ERROR() \
- do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \
- << ", gettimeofday() returned an error code." << endl; \
- exit(-1); \
- } while (0)
-
#define ABORT_VERIFICATION_ERROR() \
do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \
<< ", failed data verification." << endl; \
@@ -324,241 +53,19 @@ protected:
} while (0)
// ---------------------------------------------------------------------------
-// Driver Implementation
-// ---------------------------------------------------------------------------
-
-vector< string > Driver::propFileNames;
-string Driver::logFileName;
-
-void
-Driver::exitUsage()
-{
- cout << "usage: [options]" << endl
- << " [-p <file name>]... properties file name" << endl
- << " [-l <file name>] log file name for data output" << endl
- << " [-h|--help] print usage message and exit" << endl
- << endl;
- exit(1); // return an error code
-}
-
-void
-Driver::parseArguments(int argc, const char* argv[])
-{
- for (int i = 1; i < argc; i++) {
- const string arg = argv[i];
- if (arg.compare("-p") == 0) {
- if (i >= argc) {
- exitUsage();
- }
- propFileNames.push_back(argv[++i]);
- } else if (arg.compare("-l") == 0) {
- if (i >= argc) {
- exitUsage();
- }
- logFileName = argv[++i];
- } else if (arg.compare("-h") == 0 || arg.compare("--help") == 0) {
- exitUsage();
- } else {
- cout << "unknown option: " << arg << endl;
- exitUsage();
- }
- }
-
- if (propFileNames.size() == 0) {
- propFileNames.push_back("run.properties");
- }
-
- if (logFileName.empty()) {
- logFileName = "log_";
-
- // format, destination strings (static size)
- const char format[] = "%Y%m%d_%H%M%S";
- const int size = sizeof("yyyymmdd_HHMMSS");
- char dest[size];
-
- // get time, convert to timeinfo (statically allocated) then to string
- const time_t now = time(0);
- const int nchars = strftime(dest, size, format, localtime(&now));
- assert(nchars == size-1);
- (void)nchars;
-
- logFileName += dest;
- logFileName += ".txt";
- }
- //cout << "logFileName='" << logFileName << "'" << endl;
-}
-
-// ----------------------------------------------------------------------
-
-void
-Driver::run() {
- init();
-
- if (warmupRuns > 0) {
- cout << endl
- << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
- << "warmup runs ..." << endl
- << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
-
- for (int i = 0; i < warmupRuns; i++) {
- runTests();
- }
-
- // truncate log file, reset log buffers
- closeLogFile();
- openLogFile();
- header.rdbuf()->str("");
- rtimes.rdbuf()->str("");
- logHeader = true;
- }
-
- if (hotRuns > 0) {
- cout << endl
- << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
- << "hot runs ..." << endl
- << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
-
- for (int i = 0; i < hotRuns; i++) {
- runTests();
- }
-
- // write log buffers
- log << descr << ", rtime[ms]"
- << header.rdbuf()->str() << endl
- << rtimes.rdbuf()->str() << endl << endl << endl;
- }
-
- close();
-}
-
-void
-Driver::init() {
- loadProperties();
- initProperties();
- printProperties();
- openLogFile();
-
- // clear log buffers
- logHeader = true;
- header.rdbuf()->str("");
- rtimes.rdbuf()->str("");
-}
-
-void
-Driver::close() {
- // clear log buffers
- header.rdbuf()->str("");
- rtimes.rdbuf()->str("");
-
- closeLogFile();
-}
-
-void
-Driver::loadProperties() {
- cout << endl;
- for (vector<string>::const_iterator i = propFileNames.begin();
- i != propFileNames.end(); ++i) {
- cout << "reading properties file: " << *i << endl;
- props.load(i->c_str());
- //cout << "props = {" << endl << props << "}" << endl;
- }
-}
-
-void
-Driver::initProperties() {
- cout << "setting driver properties ..." << flush;
-
- ostringstream msg;
-
- renewConnection = toBool(props[L"renewConnection"], false);
-
- warmupRuns = toInt(props[L"warmupRuns"], 0, -1);
- if (warmupRuns < 0) {
- msg << "[ignored] warmupRuns: '"
- << toString(props[L"warmupRuns"]) << "'" << endl;
- warmupRuns = 0;
- }
-
- hotRuns = toInt(props[L"hotRuns"], 1, -1);
- if (hotRuns < 0) {
- msg << "[ignored] hotRuns: '"
- << toString(props[L"hotRuns"]) << "'" << endl;
- hotRuns = 1;
- }
-
- //if (msg.tellp() == 0) // netbeans reports amibuities
- if (msg.str().empty()) {
- cout << " [ok]" << endl;
- } else {
- cout << endl << msg.str() << endl;
- }
-}
-
-void
-Driver::printProperties() {
- const ios_base::fmtflags f = cout.flags();
- // no effect calling manipulator function, not sure why
- //cout << ios_base::boolalpha;
- cout.flags(ios_base::boolalpha);
-
- cout << endl << "driver settings ..." << endl;
- cout << "renewConnection: " << renewConnection << endl;
- cout << "warmupRuns: " << warmupRuns << endl;
- cout << "hotRuns: " << hotRuns << endl;
-
- cout.flags(f);
-}
-
-void
-Driver::openLogFile() {
- cout << endl
- << "opening results file:" << flush;
- log.open(logFileName.c_str(), ios_base::out | ios_base::trunc);
- assert(log.good());
- cout << " [ok: " << logFileName << "]" << endl;
-}
-
-void
-Driver::closeLogFile() {
- cout << endl
- << "closing results file:" << flush;
- log.close();
- cout << " [ok: " << logFileName << "]" << endl;
-}
-
+// TwsDriver Implementation
// ---------------------------------------------------------------------------
void
-Driver::begin(const string& name) {
- cout << endl;
- cout << name << endl;
-
- if (gettimeofday(&t0, NULL) != 0)
- ABORT_GETTIMEOFDAY_ERROR();
+TwsDriver::init() {
+ Driver::init();
}
void
-Driver::commit(const string& name) {
- if (gettimeofday(&t1, NULL) != 0)
- ABORT_GETTIMEOFDAY_ERROR();
-
- const long r_usec = (((t1.tv_sec - t0.tv_sec) * 1000000)
- + (t1.tv_usec - t0.tv_usec));
- const long r_msec = r_usec / 1000;
-
- cout << "tx real time: " << r_msec
- << "\tms" << endl;
- rtimes << "\t" << r_msec;
- rta += r_msec;
-
- if (logHeader)
- header << "\t" << name;
+TwsDriver::close() {
+ Driver::close();
}
-// ---------------------------------------------------------------------------
-// TwsDriver Implementation
-// ---------------------------------------------------------------------------
-
void
TwsDriver::initProperties() {
Driver::initProperties();
@@ -567,6 +74,7 @@ TwsDriver::initProperties() {
ostringstream msg;
+ renewConnection = toBool(props[L"renewConnection"], false);
doInsert = toBool(props[L"doInsert"], true);
doLookup = toBool(props[L"doLookup"], true);
doUpdate = toBool(props[L"doUpdate"], true);
@@ -597,6 +105,13 @@ TwsDriver::initProperties() {
nRows = 256;
}
+ nRuns = toInt(props[L"nRuns"], 1, -1);
+ if (nRuns < 0) {
+ msg << "[ignored] nRuns: '"
+ << toString(props[L"nRuns"]) << "'" << endl;
+ nRuns = 1;
+ }
+
//if (msg.tellp() == 0) // netbeans reports amibuities
if (msg.str().empty()) {
cout << " [ok]" << endl;
@@ -615,6 +130,7 @@ TwsDriver::printProperties() {
cout.flags(ios_base::boolalpha);
cout << endl << "tws settings..." << endl;
+ cout << "renewConnection: " << renewConnection << endl;
cout << "doInsert: " << doInsert << endl;
cout << "doLookup: " << doLookup << endl;
cout << "doUpdate: " << doUpdate << endl;
@@ -625,6 +141,7 @@ TwsDriver::printProperties() {
cout << "doVerify: " << doVerify << endl;
cout << "lockMode: " << toStr(lockMode) << endl;
cout << "nRows: " << nRows << endl;
+ cout << "nRuns: " << nRuns << endl;
cout.flags(f);
}
@@ -644,6 +161,31 @@ TwsDriver::runTests() {
void
TwsDriver::runLoads() {
+ // anticipating multiple loads to be run here
+ runSeries();
+}
+
+void
+TwsDriver::runSeries() {
+ if (nRuns == 0)
+ return; // nothing to do
+
+ cout << endl
+ << "------------------------------------------------------------" << endl;
+ cout << "running " << nRuns << " iterations on load: " << descr;
+
+ for (int i = 0; i < nRuns; i++) {
+ cout << endl
+ << "------------------------------------------------------------" << endl;
+ runOperations();
+ }
+
+ writeLogBuffers();
+ clearLogBuffers();
+}
+
+void
+TwsDriver::runOperations() {
// log buffers
rtimes << "nRows=" << nRows;
rta = 0L;
@@ -655,7 +197,7 @@ TwsDriver::runLoads() {
}
//clearData(); // not used
- runOperations();
+ runLoadOperations();
cout << endl
<< "total" << endl;
@@ -668,13 +210,30 @@ TwsDriver::runLoads() {
logHeader = false;
}
rtimes << "\t" << rta << endl;
+}
- cout << endl
- << "------------------------------------------------------------" << endl;
+void
+TwsDriver::verify(int exp, int act) {
+ if (doVerify) {
+ //cout << "XXX exp=" << exp << ", act=" << act << endl;
+ if (exp != act) {
+ ABORT_VERIFICATION_ERROR();
+ }
+ }
}
void
-TwsDriver::verify(Int32 exp, Int32 act) {
+TwsDriver::verify(long exp, long act) {
+ if (doVerify) {
+ //cout << "XXX exp=" << exp << ", act=" << act << endl;
+ if (exp != act) {
+ ABORT_VERIFICATION_ERROR();
+ }
+ }
+}
+
+void
+TwsDriver::verify(long long exp, long long act) {
if (doVerify) {
//cout << "XXX exp=" << exp << ", act=" << act << endl;
if (exp != act) {
@@ -723,889 +282,4 @@ TwsDriver::toStr(LockMode mode) {
};
}
-// ---------------------------------------------------------------------------
-// NDB API Model Implementation
-// ---------------------------------------------------------------------------
-
-NdbApiTwsModel::NdbApiTwsModel(Ndb* ndb) {
- const NdbDictionary::Dictionary* dict = ndb->getDictionary();
-
- // get table T0
- if ((table_t0 = dict->getTable("mytable")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
-
- // get columns of table T0
- if ((column_c0 = table_t0->getColumn("c0")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c1 = table_t0->getColumn("c1")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c2 = table_t0->getColumn("c2")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c3 = table_t0->getColumn("c3")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c4 = table_t0->getColumn("c4")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c5 = table_t0->getColumn("c5")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c6 = table_t0->getColumn("c6")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c7 = table_t0->getColumn("c7")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c8 = table_t0->getColumn("c8")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c9 = table_t0->getColumn("c9")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c10 = table_t0->getColumn("c10")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c11 = table_t0->getColumn("c11")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c12 = table_t0->getColumn("c12")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c13 = table_t0->getColumn("c13")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
- if ((column_c14 = table_t0->getColumn("c14")) == NULL)
- ABORT_NDB_ERROR(dict->getNdbError());
-
- // get attribute ids for columns of table T0
- attr_c0 = column_c0->getAttrId();
- attr_c1 = column_c1->getAttrId();
- attr_c2 = column_c2->getAttrId();
- attr_c3 = column_c3->getAttrId();
- attr_c4 = column_c4->getAttrId();
- attr_c5 = column_c5->getAttrId();
- attr_c6 = column_c6->getAttrId();
- attr_c7 = column_c7->getAttrId();
- attr_c8 = column_c8->getAttrId();
- attr_c9 = column_c9->getAttrId();
- attr_c10 = column_c10->getAttrId();
- attr_c11 = column_c11->getAttrId();
- attr_c12 = column_c12->getAttrId();
- attr_c13 = column_c13->getAttrId();
- attr_c14 = column_c14->getAttrId();
-
- width_c0 = columnWidth(column_c0);
- width_c1 = columnWidth(column_c1);
- width_c2 = columnWidth(column_c2);
- width_c3 = columnWidth(column_c3);
- width_c4 = columnWidth(column_c4);
- width_c5 = columnWidth(column_c5);
- width_c6 = columnWidth(column_c6);
- width_c7 = columnWidth(column_c7);
- width_c8 = columnWidth(column_c8);
- width_c9 = columnWidth(column_c9);
- width_c10 = columnWidth(column_c10);
- width_c11 = columnWidth(column_c11);
- width_c12 = columnWidth(column_c12);
- width_c13 = columnWidth(column_c13);
- width_c14 = columnWidth(column_c14);
-
- width_row = (
- + width_c0
- + width_c1
- + width_c2
- + width_c3
- + width_c4
- + width_c5
- + width_c6
- + width_c7
- + width_c8
- + width_c9
- + width_c10
- + width_c11
- + width_c12
- + width_c13
- + width_c14);
-}
-
-// ---------------------------------------------------------------------------
-// NdbApiTwsDriver Implementation
-// ---------------------------------------------------------------------------
-
-void
-NdbApiTwsDriver::init() {
- TwsDriver::init();
-
- // ndb_init must be called first
- cout << endl
- << "initializing NDBAPI ..." << flush;
- int stat = ndb_init();
- if (stat != 0)
- ABORT_ERROR("ndb_init() returned: " << stat);
- cout << " [ok]" << endl;
-
- initConnection();
-}
-
-void
-NdbApiTwsDriver::close() {
- closeConnection();
-
- // ndb_close must be called last
- cout << "closing NDBAPI ... " << flush;
- ndb_end(0);
- cout << " [ok]" << endl;
-
- TwsDriver::close();
-}
-
-void
-NdbApiTwsDriver::initProperties() {
- TwsDriver::initProperties();
-
- cout << "setting ndb properties ..." << flush;
-
- ostringstream msg;
-
- mgmdConnect = toString(props[L"ndb.mgmdConnect"]);
- if (mgmdConnect.empty()) {
- mgmdConnect = string("localhost");
- }
-
- catalog = toString(props[L"ndb.catalog"]);
- if (catalog.empty()) {
- catalog = string("testdb");
- }
-
- schema = toString(props[L"ndb.schema"]);
- if (schema.empty()) {
- schema = string("def");
- }
-
- //if (msg.tellp() == 0) {
- if (msg.str().empty()) {
- cout << " [ok]" << endl;
- } else {
- cout << endl << msg.str() << endl;
- }
-
- descr = "ndbapi(" + mgmdConnect + ")";
-}
-
-void
-NdbApiTwsDriver::printProperties() {
- TwsDriver::printProperties();
-
- const ios_base::fmtflags f = cout.flags();
- // no effect calling manipulator function, not sure why
- //cout << ios_base::boolalpha;
- cout.flags(ios_base::boolalpha);
-
- cout << endl << "ndb settings ..." << endl;
- cout << "ndb.mgmdConnect: \"" << mgmdConnect << "\"" << endl;
- cout << "ndb.catalog: \"" << catalog << "\"" << endl;
- cout << "ndb.schema: \"" << schema << "\"" << endl;
-
- cout.flags(f);
-}
-
-void
-NdbApiTwsDriver::initNdbapiBuffers() {
- assert(model->column_c0 != NULL);
- assert(bb == NULL);
- assert(ra == NULL);
-
- cout << "allocating ndbapi buffers ..." << flush;
- bb = new char[model->width_row * nRows];
- ra = new NdbRecAttr*[model->nCols * nRows];
- cout << " [ok]" << endl;
-}
-
-void
-NdbApiTwsDriver::closeNdbapiBuffers() {
- assert(bb != NULL);
- assert(ra != NULL);
-
- cout << "releasing ndbapi buffers ..." << flush;
- delete[] ra;
- ra = NULL;
- delete[] bb;
- bb = NULL;
- cout << " [ok]" << endl;
-}
-
-// ---------------------------------------------------------------------------
-
-void
-NdbApiTwsDriver::runOperations() {
- cout << endl
- << "running NDB API operations ..." << " [nRows=" << nRows << "]"
- << endl;
-
- if (doSingle) {
- if (doInsert) runNdbapiInsert(SINGLE);
- if (doLookup) runNdbapiLookup(SINGLE);
- if (doUpdate) runNdbapiUpdate(SINGLE);
- if (doDelete) runNdbapiDelete(SINGLE);
- }
- if (doBulk) {
- if (doInsert) runNdbapiInsert(BULK);
- if (doLookup) runNdbapiLookup(BULK);
- if (doUpdate) runNdbapiUpdate(BULK);
- if (doDelete) runNdbapiDelete(BULK);
- }
- if (doBatch) {
- if (doInsert) runNdbapiInsert(BATCH);
- if (doLookup) runNdbapiLookup(BATCH);
- if (doUpdate) runNdbapiUpdate(BATCH);
- if (doDelete) runNdbapiDelete(BATCH);
- }
-}
-
-// Alternative Implementation:
-// The recurring pattern of runNdbapiXXX(XMode mode) can be parametrized
-// over the operation, for instance, by a member function template:
-//
-// template< XMode M, void (NdbApiTwsDriver::*OP)(int) >
-// void runOp(string name);
-//
-// which tests the template parameter XMode and calls the operation
-// ...
-// if (M == SINGLE) {
-// ... (this->*OP)(i); ...
-// }
-// ...
-// while the caller selects the mode and function to be invoked
-// ...
-// switch (mode) {
-// case SINGLE:
-// runOp< SINGLE, &NdbApiTwsDriver::ndbapiInsert >(name);
-// }...
-// Alas, it turns out not worth it in terms of readability and lines of code.
-
-void
-NdbApiTwsDriver::runNdbapiInsert(XMode mode) {
- const string name = string("insert_") + toStr(mode);
- begin(name);
-
- if (mode == SINGLE) {
- for(int i = 0; i < nRows; i++) {
- ndbapiBeginTransaction();
- ndbapiInsert(i);
- ndbapiCommitTransaction();
- ndbapiCloseTransaction();
- }
- } else {
- ndbapiBeginTransaction();
- for(int i = 0; i < nRows; i++) {
- ndbapiInsert(i);
- if (mode == BULK)
- ndbapiExecuteTransaction();
- }
- ndbapiCommitTransaction();
- ndbapiCloseTransaction();
- }
-
- commit(name);
-}
-
-void
-NdbApiTwsDriver::ndbapiInsert(int c0) {
- // get an insert operation for the table
- NdbOperation* op = tx->getNdbOperation(model->table_t0);
- if (op == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- if (op->insertTuple() != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
-
- // values
- Uint32 i = c0;
- const int maxlen = 256;
- char str[maxlen];
- snprintf(str, maxlen, "%d", i);
-
- // set values; key attribute needs to be set first
- ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
- if (op->equal(model->attr_c0, bb_pos) != 0) // key
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c0;
-
- ndbapiToBuffer1blp(bb_pos, str, model->width_c1);
- if (op->setValue(model->attr_c1, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c1;
-
- if (op->setValue(model->attr_c2, i) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c2;
-
- if (op->setValue(model->attr_c3, i) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c3;
-
- if (op->setValue(model->attr_c4, (char*)NULL) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c4;
-
- ndbapiToBuffer1blp(bb_pos, str, model->width_c5);
- if (op->setValue(model->attr_c5, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c5;
-
- ndbapiToBuffer1blp(bb_pos, str, model->width_c6);
- if (op->setValue(model->attr_c6, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c6;
-
- ndbapiToBuffer1blp(bb_pos, str, model->width_c7);
- if (op->setValue(model->attr_c7, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c7;
-
- ndbapiToBuffer1blp(bb_pos, str, model->width_c8);
- if (op->setValue(model->attr_c8, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c8;
-
- if (op->setValue(model->attr_c9, (char*)NULL) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c9;
-
- if (op->setValue(model->attr_c10, (char*)NULL) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c10;
-
- if (op->setValue(model->attr_c11, (char*)NULL) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c11;
-
- if (op->setValue(model->attr_c12, (char*)NULL) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c12;
-
- if (op->setValue(model->attr_c13, (char*)NULL) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c13;
-
- if (op->setValue(model->attr_c14, (char*)NULL) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c14;
-}
-
-void
-NdbApiTwsDriver::runNdbapiLookup(XMode mode) {
- const string name = string("lookup_") + toStr(mode);
- begin(name);
-
- if (mode == SINGLE) {
- for(int i = 0; i < nRows; i++) {
- ndbapiBeginTransaction();
- ndbapiLookup(i);
- ndbapiCommitTransaction();
- ndbapiRead(i);
- ndbapiCloseTransaction();
- }
- } else {
- ndbapiBeginTransaction();
- for(int i = 0; i < nRows; i++) {
- ndbapiLookup(i);
-
- if (mode == BULK)
- ndbapiExecuteTransaction();
- }
- ndbapiCommitTransaction();
- for(int i = 0; i < nRows; i++) {
- ndbapiRead(i);
- }
- ndbapiCloseTransaction();
- }
-
- commit(name);
-}
-
-void
-NdbApiTwsDriver::ndbapiLookup(int c0) {
- // get a lookup operation for the table
- NdbOperation* op = tx->getNdbOperation(model->table_t0);
- if (op == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- if (op->readTuple(ndbOpLockMode) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
-
- // values
- Uint32 i = c0;
- const int maxlen = 256;
- char str[maxlen];
- snprintf(str, maxlen, "%d", i);
-
- // set values; key attribute needs to be set first
- ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
- if (op->equal(model->attr_c0, bb_pos) != 0) // key
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c0;
-
- // get attributes (not readable until after commit)
- if ((*ra_pos = op->getValue(model->attr_c1, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c1;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c2, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c2;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c3, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c3;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c4, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c4;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c5, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c5;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c6, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c6;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c7, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c7;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c8, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c8;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c9, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c9;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c10, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c10;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c11, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c11;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c12, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c12;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c13, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c13;
- ra_pos++;
-
- if ((*ra_pos = op->getValue(model->attr_c14, bb_pos)) == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c14;
- ra_pos++;
-}
-
-void
-NdbApiTwsDriver::ndbapiRead(int c0) {
- // values
- const int maxlen = 256;
- char str0[maxlen];
- snprintf(str0, maxlen, "%d", c0);
- Int32 i1;
- char str1[maxlen];
-
- // no need to read key column
- bb_pos += model->width_c0;
-
- ndbapiToString1blp(str1, bb_pos, model->width_c1);
- verify(str0, str1);
- bb_pos += model->width_c1;
- ra_pos++;
-
- memcpy(&i1, bb_pos, model->width_c2);
- verify(c0, i1);
- bb_pos += model->width_c2;
- ra_pos++;
-
- memcpy(&i1, bb_pos, model->width_c3);
- verify(c0, i1);
- bb_pos += model->width_c3;
- ra_pos++;
-
- // null expected
- verify(1, (*ra_pos)->isNULL());
- bb_pos += model->width_c4;
- ra_pos++;
-
- ndbapiToString1blp(str1, bb_pos, model->width_c5);
- verify(str0, str1);
- bb_pos += model->width_c5;
- ra_pos++;
-
- ndbapiToString1blp(str1, bb_pos, model->width_c6);
- verify(str0, str1);
- bb_pos += model->width_c6;
- ra_pos++;
-
- ndbapiToString1blp(str1, bb_pos, model->width_c7);
- verify(str0, str1);
- bb_pos += model->width_c7;
- ra_pos++;
-
- ndbapiToString1blp(str1, bb_pos, model->width_c8);
- verify(str0, str1);
- bb_pos += model->width_c8;
- ra_pos++;
-
- // null expected
- verify(1, (*ra_pos)->isNULL());
- bb_pos += model->width_c9;
- ra_pos++;
-
- // null expected
- verify(1, (*ra_pos)->isNULL());
- bb_pos += model->width_c10;
- ra_pos++;
-
- // null expected
- verify(1, (*ra_pos)->isNULL());
- bb_pos += model->width_c11;
- ra_pos++;
-
- // null expected
- verify(1, (*ra_pos)->isNULL());
- bb_pos += model->width_c12;
- ra_pos++;
-
- // null expected
- verify(1, (*ra_pos)->isNULL());
- bb_pos += model->width_c13;
- ra_pos++;
-
- // null expected
- verify(1, (*ra_pos)->isNULL());
- bb_pos += model->width_c14;
- ra_pos++;
-}
-
-void
-NdbApiTwsDriver::runNdbapiUpdate(XMode mode) {
- const string name = string("update_") + toStr(mode);
- begin(name);
-
- if (mode == SINGLE) {
- for(int i = 0; i < nRows; i++) {
- ndbapiBeginTransaction();
- ndbapiUpdate(i);
- ndbapiCommitTransaction();
- ndbapiCloseTransaction();
- }
- } else {
- ndbapiBeginTransaction();
- for(int i = 0; i < nRows; i++) {
- ndbapiUpdate(i);
- if (mode == BULK)
- ndbapiExecuteTransaction();
- }
- ndbapiCommitTransaction();
- ndbapiCloseTransaction();
- }
-
- commit(name);
-}
-
-void
-NdbApiTwsDriver::ndbapiUpdate(int c0) {
- // get an update operation for the table
- NdbOperation* op = tx->getNdbOperation(model->table_t0);
- if (op == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- if (op->updateTuple() != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
-
- // values
- const int maxlen = 256;
- char str0[maxlen];
- snprintf(str0, maxlen, "%d", c0);
- int i = -c0;
- char str1[maxlen];
- snprintf(str1, maxlen, "%d", i);
-
- // set values; key attribute needs to be set first
- ndbapiToBuffer1blp(bb_pos, str0, model->width_c0);
- if (op->equal(model->attr_c0, bb_pos) != 0) // key
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c0;
-
- ndbapiToBuffer1blp(bb_pos, str1, model->width_c1);
- if (op->setValue(model->attr_c1, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c1;
-
- if (op->setValue(model->attr_c2, i) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c2;
-
- if (op->setValue(model->attr_c3, i) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c3;
-
- ndbapiToBuffer1blp(bb_pos, str1, model->width_c5);
- if (op->setValue(model->attr_c5, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c5;
-
- ndbapiToBuffer1blp(bb_pos, str1, model->width_c6);
- if (op->setValue(model->attr_c6, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c6;
-
- ndbapiToBuffer1blp(bb_pos, str1, model->width_c7);
- if (op->setValue(model->attr_c7, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c7;
-
- ndbapiToBuffer1blp(bb_pos, str1, model->width_c8);
- if (op->setValue(model->attr_c8, bb_pos) != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c8;
-}
-
-void
-NdbApiTwsDriver::runNdbapiDelete(XMode mode) {
- const string name = string("delete_") + toStr(mode);
- begin(name);
-
- if (mode == SINGLE) {
- for(int i = 0; i < nRows; i++) {
- ndbapiBeginTransaction();
- ndbapiDelete(i);
- ndbapiCommitTransaction();
- ndbapiCloseTransaction();
- }
- } else {
- ndbapiBeginTransaction();
- for(int i = 0; i < nRows; i++) {
- ndbapiDelete(i);
- if (mode == BULK)
- ndbapiExecuteTransaction();
- }
- ndbapiCommitTransaction();
- ndbapiCloseTransaction();
- }
-
- commit(name);
-}
-
-void
-NdbApiTwsDriver::ndbapiDelete(int c0) {
- // get a delete operation for the table
- NdbOperation* op = tx->getNdbOperation(model->table_t0);
- if (op == NULL)
- ABORT_NDB_ERROR(tx->getNdbError());
- if (op->deleteTuple() != 0)
- ABORT_NDB_ERROR(tx->getNdbError());
-
- // values
- Uint32 i = c0;
- const int maxlen = 256;
- char str[maxlen];
- snprintf(str, maxlen, "%d", i);
-
- // set values; key attribute needs to be set first
- ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
- if (op->equal(model->attr_c0, bb_pos) != 0) // key
- ABORT_NDB_ERROR(tx->getNdbError());
- bb_pos += model->width_c0;
-}
-
-// ----------------------------------------------------------------------
-
-void
-NdbApiTwsDriver::ndbapiBeginTransaction() {
- assert(tx == NULL);
-
- // prepare buffer for writing
- bb_pos = bb; // clear
- ra_pos = ra;
-
- // start a transaction
- // must be closed with Ndb::closeTransaction or NdbTransaction::close
- if ((tx = ndb->startTransaction()) == NULL)
- ABORT_NDB_ERROR(ndb->getNdbError());
-}
-
-void
-NdbApiTwsDriver::ndbapiExecuteTransaction() {
- assert(tx != NULL);
-
- // execute but don't commit the current transaction
- if (tx->execute(NdbTransaction::NoCommit) != 0
- || tx->getNdbError().status != NdbError::Success)
- ABORT_NDB_ERROR(tx->getNdbError());
-}
-
-void
-NdbApiTwsDriver::ndbapiCommitTransaction() {
- assert(tx != NULL);
-
- // commit the current transaction
- if (tx->execute(NdbTransaction::Commit) != 0
- || tx->getNdbError().status != NdbError::Success)
- ABORT_NDB_ERROR(tx->getNdbError());
-
- // prepare buffer for reading
- bb_pos = bb; // rewind
- ra_pos = ra;
-}
-
-void
-NdbApiTwsDriver::ndbapiCloseTransaction() {
- assert(tx != NULL);
-
- // close the current transaction
- // to be called irrespectively of success or failure
- ndb->closeTransaction(tx);
- tx = NULL;
-}
-
-// ---------------------------------------------------------------------------
-
-void
-NdbApiTwsDriver::initConnection() {
- assert(mgmd == NULL);
- assert(ndb == NULL);
- assert(tx == NULL);
- assert(model == NULL);
-
- cout << endl;
-
- // instantiate NDB cluster singleton
- cout << "creating cluster connection ..." << flush;
- assert(!mgmdConnect.empty());
- mgmd = new Ndb_cluster_connection(mgmdConnect.c_str());
- cout << " [ok]" << endl; // no useful mgmd->string conversion
-
- // connect to cluster management node (ndb_mgmd)
- cout << "connecting to mgmd ..." << flush;
- const int retries = 0; // number of retries (< 0 = indefinitely)
- const int delay = 0; // seconds to wait after retry
- const int verbose = 1; // print report of progess
- // returns: 0 = success, 1 = recoverable error, -1 = non-recoverable error
- if (mgmd->connect(retries, delay, verbose) != 0)
- ABORT_ERROR("mgmd@" << mgmdConnect << " was not ready within "
- << (retries * delay) << "s.");
- cout << " [ok: " << mgmdConnect << "]" << endl;
-
- // optionally, connect and wait for reaching the data nodes (ndbds)
- cout << "waiting for data nodes ..." << flush;
- const int initial_wait = 10; // seconds to wait until first node detected
- const int final_wait = 0; // seconds to wait after first node detected
- // returns: 0 all nodes live, > 0 at least one node live, < 0 error
- if (mgmd->wait_until_ready(initial_wait, final_wait) < 0)
- ABORT_ERROR("data nodes were not ready within "
- << (initial_wait + final_wait) << "s.");
- cout << " [ok]" << endl;
-
- // connect to database
- cout << "connecting to database ..." << flush;
- ndb = new Ndb(mgmd, catalog.c_str(), schema.c_str());
- const int max_no_tx = 10; // maximum number of parallel tx (<=1024)
- // note each scan or index scan operation uses one extra transaction
- //if (ndb->init() != 0)
- if (ndb->init(max_no_tx) != 0)
- ABORT_NDB_ERROR(ndb->getNdbError());
- cout << " [ok: " << catalog << "." << schema << "]" << endl;
-
- cout << "caching metadata ..." << flush;
- model = new NdbApiTwsModel(ndb);
- cout << " [ok]" << endl;
-
- initNdbapiBuffers();
-
- cout << "using lock mode for reads ..." << flush;
- string lm;
- switch (lockMode) {
- case READ_COMMITTED:
- ndbOpLockMode = NdbOperation::LM_CommittedRead;
- lm = "LM_CommittedRead";
- break;
- case SHARED:
- ndbOpLockMode = NdbOperation::LM_Read;
- lm = "LM_Read";
- break;
- case EXCLUSIVE:
- ndbOpLockMode = NdbOperation::LM_Exclusive;
- lm = "LM_Exclusive";
- break;
- default:
- ndbOpLockMode = NdbOperation::LM_CommittedRead;
- lm = "LM_CommittedRead";
- assert(false);
- }
- cout << " [ok: " + lm + "]" << endl;
-}
-
-void
-NdbApiTwsDriver::closeConnection() {
- assert(mgmd != NULL);
- assert(ndb != NULL);
- assert(tx == NULL);
- assert(model != NULL);
-
- cout << endl;
-
- closeNdbapiBuffers();
-
- cout << "clearing metadata cache ..." << flush;
- delete model;
- model = NULL;
- cout << " [ok]" << endl;
-
- cout << "closing database connection ..." << flush;
- // no ndb->close();
- delete ndb;
- ndb = NULL;
- cout << " [ok]" << endl;
-
- cout << "closing cluster connection ..." << flush;
- delete mgmd;
- mgmd = NULL;
- cout << " [ok]" << endl;
-}
-
-//---------------------------------------------------------------------------
-
-void
-NdbApiTwsDriver::ndbapiToBuffer1blp(void* to, const char* from, size_t width) {
- char* t = (char*)to;
- size_t n = strlen(from);
- assert(0 <= n && n < width && width < 256); // width <= 256 ?
-
- memcpy(t + 1, from, n);
- *t = n;
-}
-
-void
-NdbApiTwsDriver::ndbapiToString1blp(char* to, const void* from, size_t width) {
- const char* s = (const char*)from;
- size_t n = *s;
- assert(0 <= n && n < width && width < 256); // width <= 256 ?
-
- memcpy(to, s + 1, n);
- to[n] = '\0';
-}
-
-// ---------------------------------------------------------------------------
-
-int
-main(int argc, const char* argv[])
-{
- NdbApiTwsDriver::parseArguments(argc, argv);
- NdbApiTwsDriver d;
- d.run();
-
- return 0;
-}
-
//---------------------------------------------------------------------------
=== added file 'storage/ndb/test/crund/tws/tws_cpp/TwsDriver.hpp'
--- a/storage/ndb/test/crund/tws/tws_cpp/TwsDriver.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/crund/tws/tws_cpp/TwsDriver.hpp 2010-10-19 22:52:04 +0000
@@ -0,0 +1,71 @@
+/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
+ *
+ * Copyright (C) 2010 MySQL
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef TwsDriver_hpp
+#define TwsDriver_hpp
+
+#include "Driver.hpp"
+
+class TwsDriver : public Driver {
+protected:
+
+ // benchmark settings
+ enum LockMode { READ_COMMITTED, SHARED, EXCLUSIVE };
+ static const char* toStr(LockMode mode);
+ enum XMode { SINGLE, BULK, BATCH };
+ static const char* toStr(XMode mode);
+ bool renewConnection;
+ bool doInsert;
+ bool doLookup;
+ bool doUpdate;
+ bool doDelete;
+ bool doSingle;
+ bool doBulk;
+ bool doBatch;
+ bool doVerify;
+ LockMode lockMode;
+ int nRows;
+ int nRuns;
+
+ // benchmark intializers/finalizers
+ virtual void init();
+ virtual void close();
+ virtual void initProperties();
+ virtual void printProperties();
+
+ // benchmark operations
+ virtual void runTests();
+ virtual void runLoads();
+ virtual void runSeries();
+ virtual void runOperations();
+ virtual void runLoadOperations() = 0;
+ void verify(int exp, int act);
+ void verify(long exp, long act);
+ void verify(long long exp, long long act);
+ void verify(const char* exp, const char* act);
+
+ // datastore operations
+ virtual void initConnection() = 0;
+ virtual void closeConnection() = 0;
+ //virtual void clearPersistenceContext() = 0; // not used
+ //virtual void clearData() = 0; // not used
+};
+
+#endif // TwsDriver_hpp
Attachment: [text/bzr-bundle] bzr/martin.zaun@oracle.com-20101019225204-7iwdlfcb35akpf97.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.1 branch (martin.zaun:3866) | Martin Zaun | 20 Oct |