From: Martin Zaun Date: October 8 2010 11:17am Subject: bzr commit into mysql-5.1-telco-7.1 branch (martin.zaun:3864) List-Archive: http://lists.mysql.com/commits/120360 Message-Id: <201010081117.o97KEMuL011852@acsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0581538626==" --===============0581538626== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/mz/mysql/ndb-7.1-opt64/ based on revid:martin.zaun@stripped 3864 Martin Zaun 2010-10-08 crund - fixes, improvements, cleanups flowing from new TWS code. modified: .bzrignore storage/ndb/test/crund/Makefile storage/ndb/test/crund/Makefile.defaults storage/ndb/test/crund/build.xml storage/ndb/test/crund/martins_little_helpers/src/utils/Properties.hpp storage/ndb/test/crund/scripts/load_shema.sh storage/ndb/test/crund/src/com/mysql/cluster/crund/CrundDriver.java storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbApiLoad.java storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbBase.java storage/ndb/test/crund/src/crundndb/CrundDriver.cpp storage/ndb/test/crund/src/crundndb/CrundDriver.hpp storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.cpp storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.hpp storage/ndb/test/crund/src/crundndb/Driver.cpp storage/ndb/test/crund/src/crundndb/Driver.hpp storage/ndb/test/crund/src/crundndb/NdbApiDriver.cpp storage/ndb/test/crund/src/crundndb/NdbApiDriver.hpp storage/ndb/test/crund/src/crundndb/com_mysql_cluster_crund_NdbApiLoad.cpp === modified file '.bzrignore' --- a/.bzrignore 2010-10-05 08:48:30 +0000 +++ b/.bzrignore 2010-10-08 11:17:35 +0000 @@ -3134,10 +3134,12 @@ storage/ndb/test/crund/scripts/ndblog storage/ndb/test/crund/scripts/results storage/ndb/test/crund/src/crundndb/NdbApiDriver storage/ndb/test/crund/src/crundndb/com_mysql_cluster_crund_NdbApiLoad.h -storage/ndb/test/crund/tws_benchmark/build/ -storage/ndb/test/crund/tws_benchmark/nbproject/configs/ -storage/ndb/test/crund/tws_benchmark/nbproject/private/ -storage/ndb/test/crund/tws_benchmark/run.properties +storage/ndb/test/crund/tws/tws_java/build/ +storage/ndb/test/crund/tws/tws_java/nbproject/configs/ +storage/ndb/test/crund/tws/tws_java/nbproject/private/ +storage/ndb/test/crund/tws/tws_java/run.properties +storage/ndb/test/crund/tws/*.properties +storage/ndb/test/crund/tws/tws_cpp/TwsDriver libmysqld/examples/mysqltest.cc libmysqld/debug_sync.cc === modified file 'storage/ndb/test/crund/Makefile' --- a/storage/ndb/test/crund/Makefile 2010-09-27 05:31:17 +0000 +++ b/storage/ndb/test/crund/Makefile 2010-10-08 11:17:35 +0000 @@ -2,7 +2,7 @@ SRC = ./src -.PHONY: all help dep dbg opt prf clean clobber distclean check +.PHONY: all help dep dbg opt prf clean mostlclean clobber distclean check all: dbg help: @@ -16,7 +16,7 @@ help: @echo "distclean -- delete also database and server log files" @echo "check -- perform self-tests (if any)" -dep dbg opt prf clean mostlyclean check: +dep dbg opt prf clean mostlyclean clobber check: ant $@ @cd $(SRC)/crundndb && $(MAKE) $(MFLAGS) $@ === modified file 'storage/ndb/test/crund/Makefile.defaults' --- a/storage/ndb/test/crund/Makefile.defaults 2010-09-29 10:02:15 +0000 +++ b/storage/ndb/test/crund/Makefile.defaults 2010-10-08 11:17:35 +0000 @@ -144,7 +144,9 @@ # Default Targets Section: -.PHONY: dep depend dbg opt prf clean mostlyclean distclean check +.PHONY: dep depend dbg opt prf clean mostlyclean clobber distclean check + +help: dep depend: @set -e; \ @@ -180,7 +182,7 @@ clean: # library-archiving removes .o files with empty .depend file, # so, better delete it only as part of mostlyclean -mostlyclean: clean +mostlyclean clobber: clean rm -rf $(MOSTLYCLEAN) .depend distclean: mostlyclean === modified file 'storage/ndb/test/crund/build.xml' --- a/storage/ndb/test/crund/build.xml 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/build.xml 2010-10-08 11:17:35 +0000 @@ -198,14 +198,15 @@ - + + - + === modified file 'storage/ndb/test/crund/martins_little_helpers/src/utils/Properties.hpp' --- a/storage/ndb/test/crund/martins_little_helpers/src/utils/Properties.hpp 2010-10-06 06:15:04 +0000 +++ b/storage/ndb/test/crund/martins_little_helpers/src/utils/Properties.hpp 2010-10-08 11:17:35 +0000 @@ -23,8 +23,11 @@ using std::map; using std::wstring; using std::ios_base; using std::istream; +//using std::wistream; using std::ostream; +//using std::wostream; using std::streambuf; +//using std::wstreambuf; /** * The Properties class is a specialized map container that stores @@ -66,22 +69,22 @@ class Properties : public map>(istream& s, Properties& p) return s; } +/* +// not implemented yet +inline wistream& +operator>>(wistream& s, Properties& p) +{ + p.load(s); + return s; +} +*/ + inline ostream& operator<<(ostream& s, const Properties& p) { @@ -153,6 +209,17 @@ operator<<(ostream& s, const Properties& return s; } +/* +// not implemented yet +inline wostream& +operator<<(wostream& s, const Properties& p) +{ + p.store(s); + return s; +} +*/ + + // --------------------------------------------------------------------------- // Properties Implementation // --------------------------------------------------------------------------- === modified file 'storage/ndb/test/crund/scripts/load_shema.sh' --- a/storage/ndb/test/crund/scripts/load_shema.sh 2010-09-27 05:31:17 +0000 +++ b/storage/ndb/test/crund/scripts/load_shema.sh 2010-10-08 11:17:35 +0000 @@ -51,7 +51,7 @@ for ((i=3; i>=0; i--)) ; do echo echo "load tws schema..." - "$MYSQL_BIN/mysql" -v < ../tws_benchmark/schema.sql + "$MYSQL_BIN/mysql" -v < ../tws/schema.sql s=$? echo "mysql exit status: $s" === modified file 'storage/ndb/test/crund/src/com/mysql/cluster/crund/CrundDriver.java' --- a/storage/ndb/test/crund/src/com/mysql/cluster/crund/CrundDriver.java 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/CrundDriver.java 2010-10-08 11:17:35 +0000 @@ -275,10 +275,6 @@ abstract public class CrundDriver extend } runOp(op, countA, countB); } - if (logHeader) { - if (logSumOfOps) - header.append("\ttotal"); - } if (logSumOfOps) { out.println(); @@ -295,7 +291,12 @@ abstract public class CrundDriver extend } // log buffers - logHeader = false; + if (logHeader) { + if (logSumOfOps) { + header.append("\ttotal"); + } + logHeader = false; + } if (logRealTime) { rtimes.append(endl); if (logSumOfOps) { === modified file 'storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbApiLoad.java' --- a/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbApiLoad.java 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbApiLoad.java 2010-10-08 11:17:35 +0000 @@ -332,9 +332,15 @@ public class NdbApiLoad extends NdbBase // NDB API datastore operations // ---------------------------------------------------------------------- - protected native void initConnection(String catalog, String schema); + protected native void initConnection(String catalog, + String schema, + int defaultLockMode); protected void initConnection() { - initConnection(catalog, schema); + // XXX add lockMode property to CrundDriver, switch then here + final int LM_Read = 0; + final int LM_Exclusive = 1; + final int LM_CommittedRead = 2; + initConnection(catalog, schema, LM_CommittedRead); } protected native void closeConnection(); protected native void clearData(); === modified file 'storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbBase.java' --- a/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbBase.java 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbBase.java 2010-10-08 11:17:35 +0000 @@ -47,11 +47,11 @@ abstract public class NdbBase extends Cr assert mgmdConnect != null; // the database - catalog = props.getProperty("ndb.catalog", ""); + catalog = props.getProperty("ndb.catalog", "crunddb"); assert catalog != null; // the schema - schema = props.getProperty("ndb.schema", ""); + schema = props.getProperty("ndb.schema", "def"); assert schema != null; if (msg.length() == 0) { === modified file 'storage/ndb/test/crund/src/crundndb/CrundDriver.cpp' --- a/storage/ndb/test/crund/src/crundndb/CrundDriver.cpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/CrundDriver.cpp 2010-10-08 11:17:35 +0000 @@ -45,14 +45,29 @@ using utils::toString; void CrundDriver::initProperties() { Driver::initProperties(); - + cout << "setting crund properties ..." << flush; ostringstream msg; renewOperations = toBool(props[L"renewOperations"], false); + + string lm = toString(props[L"lockMode"]); + if (lm.empty()) { + lockMode = READ_COMMITTED; + } else if (lm.compare("READ_COMMITTED") == 0) { + lockMode = READ_COMMITTED; + } else if (lm.compare("SHARED") == 0) { + lockMode = SHARED; + } else if (lm.compare("EXCLUSIVE") == 0) { + lockMode = EXCLUSIVE; + } else { + msg << "[ignored] lockMode: '" << lm << "'" << endl; + lockMode = READ_COMMITTED; + } + logSumOfOps = toBool(props[L"logSumOfOps"], true); - //logSumOfOps = toBool(props[L"allowExtendedPC"], false); // not used + //allowExtendedPC = toBool(props[L"allowExtendedPC"], false); // not used aStart = toInt(props[L"aStart"], 256, 0); if (aStart < 1) { @@ -150,7 +165,7 @@ CrundDriver::initProperties() { void CrundDriver::printProperties() { Driver::printProperties(); - + const ios_base::fmtflags f = cout.flags(); // no effect calling manipulator function, not sure why //cout << ios_base::boolalpha; @@ -158,6 +173,7 @@ CrundDriver::printProperties() { cout << endl << "crund settings ..." << endl; cout << "renewOperations: " << renewOperations << endl; + cout << "lockMode: " << toStr(lockMode) << endl; cout << "logSumOfOps: " << logSumOfOps << endl; //cout << "allowExtendedPC: " << allowExtendedPC << endl; cout << "aStart: " << aStart << endl; @@ -186,21 +202,21 @@ CrundDriver::runTests() { assert(bStart <= bEnd && bScale > 1); for (int i = aStart; i <= aEnd; i *= aScale) { for (int j = bStart; j <= bEnd; j *= bScale) { - runOperations(i, j); + runLoads(i, j); } } cout << endl << "------------------------------------------------------------" << endl << endl; - + clearData(); closeOperations(); closeConnection(); } void -CrundDriver::runOperations(int countA, int countB) { +CrundDriver::runLoads(int countA, int countB) { cout << endl << "------------------------------------------------------------" << endl; @@ -234,21 +250,7 @@ CrundDriver::runOperations(int countA, i } clearData(); - // run operations - for (Operations::const_iterator i = operations.begin(); - i != operations.end(); ++i) { - // no need for pre-tx cleanup with NDBAPI-based loads - //if (!allowExtendedPC) { - // // effectively prevent caching beyond Tx scope by clearing - // // any data/result caches before the next transaction - // clearPersistenceContext(); - //} - runOp(**i, countA, countB); - } - if (logHeader) { - if (logSumOfOps) - header << "\ttotal"; - } + runOperations(countA, countB); if (logSumOfOps) { cout << endl @@ -264,7 +266,12 @@ CrundDriver::runOperations(int countA, i } // log buffers - logHeader = false; + if (logHeader) { + if (logSumOfOps) { + header << "\ttotal"; + } + logHeader = false; + } if (logRealTime) { if (logSumOfOps) { rtimes << "\t" << rta; @@ -280,6 +287,20 @@ CrundDriver::runOperations(int countA, i } void +CrundDriver::runOperations(int countA, int countB) { + for (Operations::const_iterator i = operations.begin(); + i != operations.end(); ++i) { + // no need for pre-tx cleanup with NDBAPI-based loads + //if (!allowExtendedPC) { + // // effectively prevent caching beyond Tx scope by clearing + // // any data/result caches before the next transaction + // clearPersistenceContext(); + //} + runOp(**i, countA, countB); + } +} + +void CrundDriver::runOp(const Op& op, int countA, int countB) { const string& name = op.name; if (exclude.find(name) == exclude.end()) { @@ -289,4 +310,34 @@ CrundDriver::runOp(const Op& op, int cou } } +const char* +CrundDriver::toStr(XMode mode) { + switch (mode) { + case SINGLE: + return "single"; + case BULK: + return "bulk"; + case BATCH: + return "batch"; + default: + assert(false); + return ""; + }; +} + +const char* +CrundDriver::toStr(LockMode mode) { + switch (mode) { + case SINGLE: + return "read_committed"; + case SHARED: + return "shared"; + case EXCLUSIVE: + return "exclusive"; + default: + assert(false); + return ""; + }; +} + //--------------------------------------------------------------------------- === modified file 'storage/ndb/test/crund/src/crundndb/CrundDriver.hpp' --- a/storage/ndb/test/crund/src/crundndb/CrundDriver.hpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/CrundDriver.hpp 2010-10-08 11:17:35 +0000 @@ -37,7 +37,12 @@ class CrundDriver : public Driver { protected: // benchmark settings + enum LockMode { READ_COMMITTED, SHARED, EXCLUSIVE }; + static const char* toStr(LockMode mode); + enum XMode { SINGLE, BULK, BATCH }; // XXX not used yet + static const char* toStr(XMode mode); // XXX not used yet bool renewOperations; + LockMode lockMode; bool logSumOfOps; //bool allowExtendedPC; // not used int aStart; @@ -56,7 +61,7 @@ protected: virtual void initProperties(); virtual void printProperties(); - // a database operation to be benchmarked + // measured units of work struct Op { const string name; @@ -66,8 +71,6 @@ protected: virtual ~Op() {} }; - - // the list of database operations to be benchmarked typedef vector< const Op* > Operations; Operations operations; @@ -75,11 +78,9 @@ protected: virtual void initOperations() = 0; virtual void closeOperations() = 0; virtual void runTests(); + virtual void runLoads(int countA, int countB); virtual void runOperations(int countA, int countB); virtual void runOp(const Op& op, int countA, int countB); - - // reports an error if a condition is not met // XXX not covered yet - //static void verify(bool cond); }; #endif // CrundDriver_hpp === modified file 'storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.cpp' --- a/storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.cpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.cpp 2010-10-08 11:17:35 +0000 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,7 @@ using std::cout; using std::flush; using std::endl; +using std::string; using std::vector; // JNI crashes with gcc & operator<<(ostream &, long/int) @@ -172,7 +174,8 @@ CrundModel::init(Ndb* ndb) void CrundNdbApiOperations::init(const char* mgmd_conn_str) { - assert (mgmd_conn_str); + assert(mgmd == NULL); + assert(mgmd_conn_str); // ndb_init must be called first cout << endl @@ -183,9 +186,10 @@ CrundNdbApiOperations::init(const char* cout << " [ok]" << endl; // instantiate NDB cluster singleton - cout << "creating cluster conn ..." << flush; + cout << "creating cluster connection ..." << flush; + assert(mgmd_conn_str); mgmd = new Ndb_cluster_connection(mgmd_conn_str); - cout << " [ok]" << endl; // no useful mgmd->string conversion + cout << " [ok]" << endl; // no useful mgmd->string conversion // connect to cluster management node (ndb_mgmd) cout << "connecting to mgmd ..." << flush; @@ -202,10 +206,12 @@ CrundNdbApiOperations::init(const char* void CrundNdbApiOperations::close() { - cout << "closing mgmd conn ..." << flush; + assert(mgmd != NULL); + + cout << "closing cluster connection ..." << flush; delete mgmd; mgmd = NULL; - cout << " [ok]" << endl; + cout << " [ok]" << endl; // ndb_close must be called last cout << "closing NDBAPI ... " << flush; @@ -214,49 +220,86 @@ CrundNdbApiOperations::close() } void -CrundNdbApiOperations::initConnection(const char* catalog, const char* schema) +CrundNdbApiOperations::initConnection(const char* catalog, const char* schema, + NdbOperation::LockMode defaultLockMode) { + assert(mgmd != NULL); + assert(ndb == NULL); + assert(tx == NULL); + assert(model == NULL); + // optionally, connect and wait for reaching the data nodes (ndbds) - cout << "waiting for data nodes..." << flush; + 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; + cout << " [ok]" << endl; // connect to database - cout << "connecting to database..." << flush; + cout << "connecting to database ..." << flush; ndb = new Ndb(mgmd, catalog, schema); 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]" << endl; + cout << " [ok: " << catalog << "." << schema << "]" << endl; - // initialize the schema shortcuts + cout << "caching metadata ..." << flush; CrundModel* m = new CrundModel(); m->init(ndb); model = m; + cout << " [ok]" << endl; + + cout << "using lock mode for reads ..." << flush; + ndbOpLockMode = defaultLockMode; + string lm; + switch (defaultLockMode) { + case NdbOperation::LM_CommittedRead: + lm = "LM_CommittedRead"; + break; + case NdbOperation::LM_Read: + lm = "LM_Read"; + break; + case NdbOperation::LM_Exclusive: + lm = "LM_Exclusive"; + break; + default: + ndbOpLockMode = NdbOperation::LM_CommittedRead; + lm = "LM_CommittedRead"; + assert(false); + } + cout << " [ok: " + lm + "]" << endl; } void CrundNdbApiOperations::closeConnection() { - cout << "closing database conn ..." << flush; + assert(mgmd != NULL); + assert(ndb != NULL); + assert(tx == NULL); + assert(model != NULL); + + 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 << " [ok]" << endl; } void CrundNdbApiOperations::beginTransaction() { + assert(tx == NULL); + // start a transaction // must be closed with Ndb::closeTransaction or NdbTransaction::close if ((tx = ndb->startTransaction()) == NULL) @@ -266,6 +309,8 @@ CrundNdbApiOperations::beginTransaction( void CrundNdbApiOperations::executeOperations() { + assert(tx != NULL); + // execute but don't commit the current transaction if (tx->execute(NdbTransaction::NoCommit) != 0 || tx->getNdbError().status != NdbError::Success) @@ -275,6 +320,8 @@ CrundNdbApiOperations::executeOperations void CrundNdbApiOperations::commitTransaction() { + assert(tx != NULL); + // commit the current transaction if (tx->execute(NdbTransaction::Commit) != 0 || tx->getNdbError().status != NdbError::Success) @@ -282,17 +329,10 @@ CrundNdbApiOperations::commitTransaction } void -CrundNdbApiOperations::rollbackTransaction() -{ - // abort the current transaction - if (tx->execute(NdbTransaction::Rollback) != 0 - || tx->getNdbError().status != NdbError::Success) - ABORT_NDB_ERROR(tx->getNdbError()); -} - -void CrundNdbApiOperations::closeTransaction() { + assert(tx != NULL); + // close the current transaction // to be called irrespectively of success or failure ndb->closeTransaction(tx); @@ -357,7 +397,7 @@ selectString(int length) case 100: return astring100; case 1000: return astring1000; default: - assert (false); + assert(false); return ""; } } @@ -417,11 +457,6 @@ CrundNdbApiOperations::delByScan(const N if (op->readTuples(lock_mode, scan_flags, parallel, batch_) != 0) ABORT_NDB_ERROR(tx->getNdbError()); - // define a read scan with exclusive locks - // XXX deprecated: readTuplesExclusive(int parallell = 0); - //if (op->readTuplesExclusive() != 0) - // ABORT_NDB_ERROR(tx->getNdbError()); - // start the scan; don't commit yet executeOperations(); @@ -501,7 +536,7 @@ CrundNdbApiOperations::setByPK(const Ndb { beginTransaction(); for (int i = from; i <= to; i++) { - // get an insert operation for the table + // get an update operation for the table NdbOperation* op = tx->getNdbOperation(table); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); @@ -545,7 +580,7 @@ CrundNdbApiOperations::getByPK_bb(const NdbOperation* op = tx->getNdbOperation(table); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - if (op->readTuple(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuple(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // set key attribute @@ -625,7 +660,7 @@ CrundNdbApiOperations::getByPK_ar(const NdbOperation* op = tx->getNdbOperation(table); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - if (op->readTuple(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuple(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // set key attribute @@ -711,7 +746,7 @@ CrundNdbApiOperations::setVar(const NdbD // XXX assumes column declared as VARBINARY/CHAR(<255) size_t sbuf = 1 + slen; // XXX buffer overflow if slen >255!!! - assert (slen < 255); + assert(slen < 255); buf = new char[sbuf]; buf[0] = (char)slen; memcpy(buf + 1, str, slen); @@ -722,7 +757,7 @@ CrundNdbApiOperations::setVar(const NdbD beginTransaction(); for (int i = from; i <= to; i++) { - // get an insert operation for the table + // get an update operation for the table NdbOperation* op = tx->getNdbOperation(table); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); @@ -753,7 +788,7 @@ CrundNdbApiOperations::getVar(const NdbD int from, int to, bool batch, const char* str) { - assert (str); + assert(str); // allocate attributes holder const int count = (to - from) + 1; @@ -775,7 +810,7 @@ CrundNdbApiOperations::getVar(const NdbD NdbOperation* op = tx->getNdbOperation(table); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - if (op->readTuple(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuple(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // set key attribute @@ -792,7 +827,7 @@ CrundNdbApiOperations::getVar(const NdbD } commitTransaction(); closeTransaction(); - assert (s == buf + sbuf); + assert(s == buf + sbuf); // copy (move) the strings to make them aligned and 0-terminated s = buf; @@ -812,7 +847,7 @@ CrundNdbApiOperations::getVar(const NdbD // check fetched values VERIFY(strcmp(s, str) == 0); } - assert (s == buf + sbuf); + assert(s == buf + sbuf); // release attributes holder delete[] buf; @@ -895,7 +930,7 @@ CrundNdbApiOperations::navB0ToA(int coun NdbOperation* op = tx->getNdbOperation(model->table_B0); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - if (op->readTuple(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuple(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // set key attribute @@ -914,11 +949,11 @@ CrundNdbApiOperations::navB0ToA(int coun NdbOperation* op = tx->getNdbOperation(model->table_A); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - if (op->readTuple(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuple(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // set key attribute - assert (a_id == ((i - 1) % count_A) + 1); + assert(a_id == ((i - 1) % count_A) + 1); if (op->equal(model->attr_id, a_id) != 0) ABORT_NDB_ERROR(tx->getNdbError()); @@ -973,7 +1008,7 @@ CrundNdbApiOperations::navB0ToAalt(int c NdbOperation* op = tx->getNdbOperation(model->table_B0); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - if (op->readTuple(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuple(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // set key attribute @@ -1001,11 +1036,11 @@ CrundNdbApiOperations::navB0ToAalt(int c NdbOperation* op = tx->getNdbOperation(model->table_A); if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - if (op->readTuple(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuple(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // set key attribute - assert (*pa_id == ((i - 1) % count_A) + 1); + assert(*pa_id == ((i - 1) % count_A) + 1); if (op->equal(model->attr_id, (Int32)*pa_id) != 0) ABORT_NDB_ERROR(tx->getNdbError()); @@ -1067,8 +1102,7 @@ CrundNdbApiOperations::navAToB0(int coun if (op == NULL) ABORT_NDB_ERROR(tx->getNdbError()); - // define a read scan without locks (LM_CommittedRead) - if (op->readTuples(NdbOperation::LM_CommittedRead) != 0) + if (op->readTuples(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // define the scan's bounds (more efficient than using a scan filter) @@ -1102,7 +1136,7 @@ CrundNdbApiOperations::navAToB0(int coun int stat; const bool allowFetch = true; // request new batches when exhausted while ((stat = op->nextResult(allowFetch, forceSend)) == 0) { - assert (ab <= pab && pab < ab + count_B); + assert(ab <= pab && pab < ab + count_B); *pab++ = h; } if (stat != 1) @@ -1113,7 +1147,7 @@ CrundNdbApiOperations::navAToB0(int coun commitTransaction(); closeTransaction(); //CDBG << "!!! pab - ab =" << toString(pab-ab) << endl; - assert (pab == ab + count_B); + assert(pab == ab + count_B); // check fetched values // XXX this is not the most efficient way of testing... @@ -1158,8 +1192,7 @@ CrundNdbApiOperations::navAToB0alt(int c ABORT_NDB_ERROR(tx->getNdbError()); // XXX ? no locks (LM_CommittedRead) or shared locks (LM_Read) - // define a read scan without locks - if (op[i]->readTuples(NdbOperation::LM_CommittedRead) != 0) + if (op[i]->readTuples(ndbOpLockMode) != 0) ABORT_NDB_ERROR(tx->getNdbError()); // define the scan's bounds (more efficient than using a scan filter) @@ -1197,7 +1230,7 @@ CrundNdbApiOperations::navAToB0alt(int c int stat; const bool allowFetch = true; // request new batches when exhausted while ((stat = op[i]->nextResult(allowFetch, forceSend)) == 0) { - assert (ab <= pab && pab < ab + count_B); + assert(ab <= pab && pab < ab + count_B); *pab++ = h; } if (stat != 1) @@ -1212,8 +1245,8 @@ CrundNdbApiOperations::navAToB0alt(int c commitTransaction(); closeTransaction(); //CDBG << "!!! pab - ab =" << toString(pab-ab) << endl; - assert (a_id == count_A + 1); - assert (pab == ab + count_B); + assert(a_id == count_A + 1); + assert(pab == ab + count_B); // check fetched values // XXX this is not the most efficient way of testing... === modified file 'storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.hpp' --- a/storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.hpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/CrundNdbApiOperations.hpp 2010-10-08 11:17:35 +0000 @@ -73,34 +73,50 @@ class CrundNdbApiOperations // But for now, having all in one class is good enough. public: - // the benchmark's metadata shortcuts + + CrundNdbApiOperations() + : model(NULL), mgmd(NULL), ndb(NULL), tx(NULL) { + } + + ~CrundNdbApiOperations() { + assert(model == NULL); + assert(mgmd == NULL); assert(ndb == NULL); assert(tx == NULL); + } + + // NDB Api metadata resources const CrundModel* model; -//protected: - // singleton object representing the NDB cluster (one per process) - Ndb_cluster_connection* mgmd; +protected: - // object representing a connection to an NDB database + // NDB API resources + Ndb_cluster_connection* mgmd; Ndb* ndb; - - // object representing an NDB database transaction NdbTransaction* tx; + NdbOperation::LockMode ndbOpLockMode; + + // NDB Api data resources + // XXX not used yet, see TwsDriver + //char* bb; + //char* bb_pos; + //NdbRecAttr** ra; + //NdbRecAttr** ra_pos; + +private: + + CrundNdbApiOperations(const CrundNdbApiOperations&); + CrundNdbApiOperations& operator=(const CrundNdbApiOperations&); public: + void init(const char* mgmd_conn_str); void close(); - void initConnection(const char* catalog, const char* schema); + void initConnection(const char* catalog, const char* schema, + NdbOperation::LockMode defaultLockMode); void closeConnection(); - void beginTransaction(); - - void commitTransaction(); - - void rollbackTransaction(); - void clearData(); void delByScan(const NdbDictionary::Table* table, int& count, @@ -152,10 +168,15 @@ public: bool batch); protected: - // executes the operations in the current transaction - void executeOperations(); - // closes the current transaction + // XXX not used yet, see TwsDriver + //void ndbapiBeginTransaction(); + //void ndbapiExecuteTransaction(); + //void ndbapiCommitTransaction(); + //void ndbapiCloseTransaction(); + void beginTransaction(); + void executeOperations(); + void commitTransaction(); void closeTransaction(); void setVar(const NdbDictionary::Table* table, int attr_cvar, @@ -163,6 +184,10 @@ protected: void getVar(const NdbDictionary::Table* table, int attr_cvar, int from, int to, bool batch, const char* str); + + // XXX not used yet, see TwsDriver + //static void ndbapiToBuffer1blp(void* to, const char* from, size_t width); + //static void ndbapiToString1blp(char* to, const void* from, size_t width); }; #endif // CrundNdbApiOperations_hpp === modified file 'storage/ndb/test/crund/src/crundndb/Driver.cpp' --- a/storage/ndb/test/crund/src/crundndb/Driver.cpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/Driver.cpp 2010-10-08 11:17:35 +0000 @@ -100,13 +100,13 @@ Driver::parseArguments(int argc, const c // 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); + assert(nchars == size-1); (void)nchars; logFileName += dest; logFileName += ".txt"; - //cout << "logFileName='" << logFileName << "'" << endl; } + //cout << "logFileName='" << logFileName << "'" << endl; } // ---------------------------------------------------------------------- @@ -115,40 +115,39 @@ void Driver::run() { init(); - // warmup runs - for (int i = 0; i < warmupRuns; i++) { - runTests(); - } + if (warmupRuns > 0) { + cout << endl + << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl + << "warmup runs ..." << endl + << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; - // truncate log file, reset log buffers - cout << endl - << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl - << "start logging results ..." << endl - << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl - << endl; - header.rdbuf()->str(""); - rtimes.rdbuf()->str(""); - closeLogFile(); - openLogFile(); + for (int i = 0; i < warmupRuns; i++) { + runTests(); + } - // hot runs - for (int i = 0; i < hotRuns; 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; - // write log buffers - if (logRealTime) { - // doesn't work: ostream << ostringstream->rdbuf() + 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; } - if (logCpuTime) { - // doesn't work: ostream << ostringstream->rdbuf() - log << descr << ", ctime[ms]" - << header.rdbuf()->str() << endl - << ctimes.rdbuf()->str() << endl << endl << endl; - } close(); } @@ -182,8 +181,7 @@ Driver::loadProperties() { i != propFileNames.end(); ++i) { cout << "reading properties file: " << *i << endl; props.load(i->c_str()); - props.load(i->c_str()); - //wcout << props << endl; + //cout << "props = {" << endl << props << "}" << endl; } } @@ -211,7 +209,8 @@ Driver::initProperties() { hotRuns = 1; } - if (msg.tellp() == 0) { + //if (msg.tellp() == 0) // netbeans reports amibuities + if (msg.str().empty()) { cout << " [ok]" << endl; } else { cout << endl << msg.str() << endl; @@ -238,17 +237,18 @@ Driver::printProperties() { void Driver::openLogFile() { cout << endl - << "writing results to file: " << logFileName << endl; - //log.open(logFileName.c_str()); + << "opening results file:" << flush; log.open(logFileName.c_str(), ios_base::out | ios_base::trunc); - assert (log.good()); + assert(log.good()); + cout << " [ok: " << logFileName << "]" << endl; } void Driver::closeLogFile() { - cout << "closing files ..." << flush; + cout << endl + << "closing results file:" << flush; log.close(); - cout << " [ok]" << endl; + cout << " [ok: " << logFileName << "]" << endl; } // ---------------------------------------------------------------------- === modified file 'storage/ndb/test/crund/src/crundndb/Driver.hpp' --- a/storage/ndb/test/crund/src/crundndb/Driver.hpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/Driver.hpp 2010-10-08 11:17:35 +0000 @@ -51,13 +51,18 @@ public: Driver() {} /** + * Deletes an instance. + */ + virtual ~Driver() {} + + /** * Runs the benchmark. */ void run(); protected: - // driver command-line arguments + // command-line arguments static vector< string > propFileNames; static string logFileName; === modified file 'storage/ndb/test/crund/src/crundndb/NdbApiDriver.cpp' --- a/storage/ndb/test/crund/src/crundndb/NdbApiDriver.cpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/NdbApiDriver.cpp 2010-10-08 11:17:35 +0000 @@ -104,10 +104,22 @@ NdbApiDriver::initProperties() { 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("crunddb"); + } + schema = toString(props[L"ndb.schema"]); + if (schema.empty()) { + schema = string("def"); + } - if (msg.tellp() == 0) { + //if (msg.tellp() == 0) { + if (msg.str().empty()) { cout << " [ok]" << endl; } else { cout << endl << msg.str() << endl; @@ -119,7 +131,7 @@ NdbApiDriver::initProperties() { void NdbApiDriver::printProperties() { CrundDriver::printProperties(); - + const ios_base::fmtflags f = cout.flags(); // no effect calling manipulator function, not sure why //cout << ios_base::boolalpha; @@ -133,15 +145,7 @@ NdbApiDriver::printProperties() { cout.flags(f); } -void -NdbApiDriver::initConnection() { - ops->initConnection(catalog.c_str(), schema.c_str()); -} - -void -NdbApiDriver::closeConnection() { - ops->closeConnection(); -} +//--------------------------------------------------------------------------- void NdbApiDriver::initOperations() { @@ -377,9 +381,37 @@ NdbApiDriver::closeOperations() { cout << " [ok]" << endl; } +//--------------------------------------------------------------------------- + +void +NdbApiDriver::initConnection() { + NdbOperation::LockMode ndbOpLockMode; + switch (lockMode) { + case READ_COMMITTED: + ndbOpLockMode = NdbOperation::LM_CommittedRead; + break; + case SHARED: + ndbOpLockMode = NdbOperation::LM_Read; + break; + case EXCLUSIVE: + ndbOpLockMode = NdbOperation::LM_Exclusive; + break; + default: + ndbOpLockMode = NdbOperation::LM_CommittedRead; + assert(false); + } + + ops->initConnection(catalog.c_str(), schema.c_str(), ndbOpLockMode); +} + +void +NdbApiDriver::closeConnection() { + ops->closeConnection(); +} + void NdbApiDriver::clearPersistenceContext() { - // XXX not implemented yet + assert(false); // XXX not implemented yet } void === modified file 'storage/ndb/test/crund/src/crundndb/NdbApiDriver.hpp' --- a/storage/ndb/test/crund/src/crundndb/NdbApiDriver.hpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/NdbApiDriver.hpp 2010-10-08 11:17:35 +0000 @@ -32,6 +32,14 @@ using std::string; typedef const NdbDictionary::Table* NdbTable; class NdbApiDriver : public CrundDriver { +public: + + // the generated features are OK + //NdbApiDriver() {} + //virtual ~NdbApsDriver() {} + //NdbApiDriver(const NdbApiDriver&) {} + //NdbApiDriver& operator=(const NdbApiDriver&) {} + protected: // NDB API resources @@ -47,12 +55,6 @@ protected: virtual void printProperties(); virtual void init(); virtual void close(); - virtual void initConnection(); - virtual void closeConnection(); - virtual void initOperations(); - virtual void closeOperations(); - virtual void clearPersistenceContext(); - virtual void clearData(); // NDB API operations template< bool feat > void initOperationsFeat(); @@ -80,6 +82,14 @@ protected: void (CrundNdbApiOperations::*)(int,int,bool), bool > struct RelOp; + virtual void initOperations(); + virtual void closeOperations(); + + // NDB API datastore operations + virtual void initConnection(); + virtual void closeConnection(); + virtual void clearPersistenceContext(); + virtual void clearData(); }; #endif // Driver_hpp === modified file 'storage/ndb/test/crund/src/crundndb/com_mysql_cluster_crund_NdbApiLoad.cpp' --- a/storage/ndb/test/crund/src/crundndb/com_mysql_cluster_crund_NdbApiLoad.cpp 2010-10-05 08:48:30 +0000 +++ b/storage/ndb/test/crund/src/crundndb/com_mysql_cluster_crund_NdbApiLoad.cpp 2010-10-08 11:17:35 +0000 @@ -73,7 +73,8 @@ JNIEXPORT void JNICALL Java_com_mysql_cluster_crund_NdbApiLoad_initConnection(JNIEnv* env, jobject obj, jstring catalog_jstr, - jstring schema_jstr) + jstring schema_jstr, + jint defaultLockMode) { TRACE("initConnection()"); assert (catalog_jstr); @@ -82,8 +83,9 @@ Java_com_mysql_cluster_crund_NdbApiLoad_ // get native strings from the Java strings const char* catalog_cstr = env->GetStringUTFChars(catalog_jstr, NULL); const char* schema_cstr = env->GetStringUTFChars(schema_jstr, NULL); + NdbOperation::LockMode dlm = (NdbOperation::LockMode)defaultLockMode; - ops->initConnection(catalog_cstr, schema_cstr); + ops->initConnection(catalog_cstr, schema_cstr, dlm); // release the native and Java strings env->ReleaseStringUTFChars(schema_jstr, schema_cstr); @@ -107,30 +109,6 @@ Java_com_mysql_cluster_crund_NdbApiLoad_ } JNIEXPORT void JNICALL -Java_com_mysql_cluster_crund_NdbApiLoad_beginTransaction(JNIEnv* env, - jobject obj) -{ - TRACE("beginTransaction()"); - ops->beginTransaction(); -} - -JNIEXPORT void JNICALL -Java_com_mysql_cluster_crund_NdbApiLoad_commitTransaction(JNIEnv* env, - jobject obj) -{ - TRACE("commitTransaction()"); - ops->commitTransaction(); -} - -JNIEXPORT void JNICALL -Java_com_mysql_cluster_crund_NdbApiLoad_rollbackTransaction(JNIEnv* env, - jobject obj) -{ - TRACE("rollbackTransaction()"); - ops->rollbackTransaction(); -} - -JNIEXPORT void JNICALL Java_com_mysql_cluster_crund_NdbApiLoad_delAllA(JNIEnv* env, jobject obj, jint count_A, --===============0581538626== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/martin.zaun@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: martin.zaun@stripped # target_branch: file:///Users/mz/mysql/ndb-7.1-opt64/ # testament_sha1: 2cd1f0f1b970621ac60f29f03d280120dabb353c # timestamp: 2010-10-08 04:17:42 -0700 # base_revision_id: martin.zaun@stripped\ # hntp9zn28m7lx601 # # Begin bundle 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 --===============0581538626==--