From: Martin Zaun Date: October 1 2010 4:10am Subject: bzr commit into mysql-5.1-telco-7.1 branch (martin.zaun:3849) List-Archive: http://lists.mysql.com/commits/119678 Message-Id: <201010010410.o913mN8K004426@acsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0467141801==" --===============0467141801== 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:jonas@stripped 3849 Martin Zaun 2010-09-30 crund - fixes and cleanups modified: storage/ndb/test/crund/config_samples/crundClusterj.properties storage/ndb/test/crund/config_samples/crundMysql.properties storage/ndb/test/crund/config_samples/crundNdbapi.properties storage/ndb/test/crund/config_samples/crundNdbjtie.properties storage/ndb/test/crund/config_samples/crundOpenjpaClusterj.properties storage/ndb/test/crund/config_samples/crundRun.properties storage/ndb/test/crund/config_samples/env.properties storage/ndb/test/crund/martins_little_helpers/src/utils/Makefile storage/ndb/test/crund/martins_little_helpers/src/utils/helpers.hpp storage/ndb/test/crund/martins_little_helpers/src/utils/string_helpers.hpp storage/ndb/test/crund/src/com/mysql/cluster/crund/Driver.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/com/mysql/cluster/crund/NdbJTieLoad.java storage/ndb/test/crund/src/crundndb/Driver.cpp storage/ndb/test/crund/src/crundndb/Operations.cpp storage/ndb/test/crund/src/crundndb/Operations.hpp storage/ndb/test/crund/src/crundndb/com_mysql_cluster_crund_NdbApiLoad.cpp === modified file 'storage/ndb/test/crund/config_samples/crundClusterj.properties' --- a/storage/ndb/test/crund/config_samples/crundClusterj.properties 2010-02-25 15:00:17 +0000 +++ b/storage/ndb/test/crund/config_samples/crundClusterj.properties 2010-10-01 04:10:21 +0000 @@ -1,7 +1,7 @@ # XXX NPE with clusterj if field = null #exclude=setVarbinary1,setVarbinary1_batch,getVarbinary1,getVarbinary1_batch,setVarbinary10,setVarbinary10_batch,getVarbinary10,getVarbinary10_batch,setVarbinary100,setVarbinary100_batch,getVarbinary100,getVarbinary100_batch -exclude=navA->B0 +#exclude=navA->B0 #exclude= com.mysql.clusterj.connectstring=localhost === modified file 'storage/ndb/test/crund/config_samples/crundMysql.properties' --- a/storage/ndb/test/crund/config_samples/crundMysql.properties 2010-02-25 15:00:17 +0000 +++ b/storage/ndb/test/crund/config_samples/crundMysql.properties 2010-10-01 04:10:21 +0000 @@ -1,6 +1,6 @@ # blobs seem to work but not implemented in other backends yet -exclude=setBlob1000,getBlob1000,setBlob10000,getBlob10000,setBlob100000,getBlob100000,setText1000,getText1000,setText10000,getText10000,setText100000,getText100000 +exclude=setBlob1000,setBlob1000_batch,getBlob1000,getBlob1000_batch,setBlob10000,setBlob10000_batch,getBlob10000,getBlob10000_batch,setBlob100000,setBlob100000_batch,getBlob100000,getBlob100000_batch,setText1000,setText1000_batch,getText1000,getText1000_batch,setText10000,setText10000_batch,getText10000,getText10000_batch,setText100000,setText100000_batch,getText100000,getText100000_batch # JDBC - MySQL connection settings jdbc.url=jdbc:mysql://localhost/crunddb === modified file 'storage/ndb/test/crund/config_samples/crundNdbapi.properties' --- a/storage/ndb/test/crund/config_samples/crundNdbapi.properties 2010-02-25 15:00:17 +0000 +++ b/storage/ndb/test/crund/config_samples/crundNdbapi.properties 2010-10-01 04:10:21 +0000 @@ -3,6 +3,7 @@ #exclude=navA->B0_alt,navA->B0_alt_forceSend #exclude=navA->B0_alt_forceSend #exclude=navA->B0,navA->B0alt +#exclude=getAByPK_ar,getB0ByPK_ar,getAByPK_ar_batch,getB0ByPK_ar_batch # NDBAPI connection settings ndb.mgmdConnect=localhost === modified file 'storage/ndb/test/crund/config_samples/crundNdbjtie.properties' --- a/storage/ndb/test/crund/config_samples/crundNdbjtie.properties 2010-02-25 15:00:17 +0000 +++ b/storage/ndb/test/crund/config_samples/crundNdbjtie.properties 2010-10-01 04:10:21 +0000 @@ -2,7 +2,7 @@ # XXX not yet implemented by NdbJTie #exclude=setVarbinary1,setVarbinary1_batch,getVarbinary1,getVarbinary1_batch,setVarchar1,setVarchar1_batch,getVarchar1,getVarchar1_batch,setVarbinary10,setVarbinary10_batch,getVarbinary10,getVarbinary10_batch,setVarchar10,setVarchar10_batch,getVarchar10,getVarchar10_batch,setVarbinary100,setVarbinary100_batch,getVarbinary100,getVarbinary100_batch,setVarchar100,setVarchar100_batch,getVarchar100,getVarchar100_batch,setB0->A,setB0->A_batch,navB0->A,navB0->A_batch,navB0->A_alt,navB0->A_alt_batch,navA->B0,navA->B0_forceSend,navA->B0_alt,navA->B0_alt_forceSend,nullB0->A,nullB0->A_batch #exclude=navA->B0,navA->B0_forceSend,navA->B0_alt,navA->B0_alt_forceSend -#exclude= +#exclude=getAByPK_bb,getB0ByPK_bb,getAByPK_bb_batch,getB0ByPK_bb_batch # NDBJTIE connection settings ndb.mgmdConnect=localhost === modified file 'storage/ndb/test/crund/config_samples/crundOpenjpaClusterj.properties' --- a/storage/ndb/test/crund/config_samples/crundOpenjpaClusterj.properties 2010-02-25 15:00:17 +0000 +++ b/storage/ndb/test/crund/config_samples/crundOpenjpaClusterj.properties 2010-10-01 04:10:21 +0000 @@ -1,5 +1,6 @@ #exclude=navA->B0,navA->B0_opt +#exclude=setAByPK_bulk,setB0ByPK_bulk,setAByPK,setB0ByPK,getAByPK,getB0ByPK # OpenJPA - MySQL JDBC connection settings openjpa.ConnectionURL=jdbc:mysql://localhost/crunddb === modified file 'storage/ndb/test/crund/config_samples/crundRun.properties' --- a/storage/ndb/test/crund/config_samples/crundRun.properties 2010-02-25 15:00:17 +0000 +++ b/storage/ndb/test/crund/config_samples/crundRun.properties 2010-10-01 04:10:21 +0000 @@ -5,33 +5,35 @@ logMemUsage=false includeFullGC=false logSumOfOps=true -# the number of rows for tables A in a transaction and a scale factor +# optional number of rows per transaction with a scale factor #aStart=4 #aStart=256 #aStart=1024 -aStart=4096 +#aStart=4096 #aStart=16384 +#aStart=65536 #aEnd=4 #aEnd=256 #aEnd=1024 -aEnd=4096 +#aEnd=4096 #aEnd=16384 #aEnd=65536 -aIncr=4 +#aScale=4 -# the number of rows for tables B0 in a transaction and a scale factor +# optional number of rows per transaction with a scale factor #bStart=4 #bStart=256 #bStart=1024 -bStart=4096 +#bStart=4096 #bStart=16384 +#bStart=65536 #bEnd=4 #bEnd=256 #bEnd=1024 -bEnd=4096 +#bEnd=4096 #bEnd=16384 #bEnd=65536 -bIncr=4 +#bScale=4 # the max length (multiple of 10) up to which to scale up strings # CRUND CODE (AND SCHEMA) CURRENTLY DO NOT SUPPORT @@ -50,7 +52,8 @@ allowExtendedPC=false # the number of warmup and finally recorded runs warmupRuns=0 -hotRuns=20 +hotRuns=1 +#hotRuns=20 # CURRENT LIMITS: # === modified file 'storage/ndb/test/crund/config_samples/env.properties' --- a/storage/ndb/test/crund/config_samples/env.properties 2010-09-29 10:02:15 +0000 +++ b/storage/ndb/test/crund/config_samples/env.properties 2010-10-01 04:10:21 +0000 @@ -48,8 +48,8 @@ MYSQL_LIBEXEC="$MYSQL_HOME/libexec" # - Martin's Little Helpers utilities (see below) #JAVA_INCLUDEOPTS=-I"/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Headers" -#JAVA_INCLUDEOPTS=-I"/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers" -JAVA_INCLUDEOPTS=-I"/usr/lib/jvm/java-6-sun/include" -I"/usr/lib/jvm/java-6-sun/include/linux" +JAVA_INCLUDEOPTS=-I"/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers" +#JAVA_INCLUDEOPTS=-I"/usr/lib/jvm/java-6-sun/include" -I"/usr/lib/jvm/java-6-sun/include/linux" # Comments: # === modified file 'storage/ndb/test/crund/martins_little_helpers/src/utils/Makefile' --- a/storage/ndb/test/crund/martins_little_helpers/src/utils/Makefile 2010-09-29 10:02:15 +0000 +++ b/storage/ndb/test/crund/martins_little_helpers/src/utils/Makefile 2010-10-01 04:10:21 +0000 @@ -17,8 +17,10 @@ include ../../../env.properties # -DHRT_CPUTIME_METHOD=HRT_USE_GETRUSAGE \ DDEFINES = \ - -DHRT_REALTIME_METHOD=HRT_USE_CLOCK_GETTIME \ - -DHRT_CPUTIME_METHOD=HRT_USE_CLOCK_GETTIME \ + -DHRT_REALTIME_METHOD=HRT_USE_GETTIMEOFDAY \ + -DHRT_CPUTIME_METHOD=HRT_USE_GETRUSAGE \ + #-DHRT_REALTIME_METHOD=HRT_USE_CLOCK_GETTIME \ + #-DHRT_CPUTIME_METHOD=HRT_USE_CLOCK_GETTIME \ #-DHRT_REALTIME_METHOD=HRT_USE_GETTIMEOFDAY \ #-DHRT_CPUTIME_METHOD=HRT_USE_GETRUSAGE \ #-DHRT_REALTIME_METHOD=HRT_USE_TIMES \ @@ -66,8 +68,8 @@ include ../../../env.properties # LOADLIBES for libs for the individual case # check with non-gnu makes: use of LOADLIBES, LDLIBS # CLOCK_GETTIME requires -lrt -# LDLIBS = - LDLIBS = -lrt + LDLIBS = +# LDLIBS = -lrt #------------------------------------------------------------------------------ === modified file 'storage/ndb/test/crund/martins_little_helpers/src/utils/helpers.hpp' --- a/storage/ndb/test/crund/martins_little_helpers/src/utils/helpers.hpp 2010-02-14 05:05:31 +0000 +++ b/storage/ndb/test/crund/martins_little_helpers/src/utils/helpers.hpp 2010-10-01 04:10:21 +0000 @@ -36,11 +36,11 @@ using std::flush; * Helper Macros & Functions ************************************************************/ -// gcc: crashes when printing source code file number: -// << ", line: " << (__LINE__) +// JNI crashes with gcc & operator<<(ostream &, long/int) // so, we use C99's __func__ and also convert to string using sprintf() #define ABORT_ERROR(message) \ - do { char l[1024]; \ + do { \ + char l[1024]; \ sprintf(l, "%d", __LINE__); \ cout << "!!! error, file: " << (__FILE__) \ << ", function: " << (__func__) \ === modified file 'storage/ndb/test/crund/martins_little_helpers/src/utils/string_helpers.hpp' --- a/storage/ndb/test/crund/martins_little_helpers/src/utils/string_helpers.hpp 2010-02-14 05:05:31 +0000 +++ b/storage/ndb/test/crund/martins_little_helpers/src/utils/string_helpers.hpp 2010-10-01 04:10:21 +0000 @@ -8,6 +8,7 @@ //#include #include +#include #include #include @@ -20,6 +21,7 @@ namespace utils { using std::string; using std::wstring; using std::ostream; +using std::wistringstream; using std::set; /************************************************************ @@ -59,14 +61,47 @@ toBool(const wstring& ws) } /** + * Parses a wide character string as a (signed) decimal integer. + * + * Returns the integral value of a wide character string, the default value + * if the string is empty, or the error value if the conversion has failed. + */ +template< typename I > +inline I +toI(const wstring& ws, I vdefault, I verror) +{ + I val; + if (ws.length() == 0) { + val = vdefault; + } else { + wistringstream wiss(ws); + wiss >> val; + if (wiss.fail() || !wiss.eof()) { + val = verror; + } + } + return val; +} + +inline int +toInt(const wstring& ws, int vdefault, int verror) +{ + return toI< int >(ws, vdefault, verror); +} + +/** * Returns the character representation of an int. */ inline string toString(int i) { - std::ostringstream o; - o << i; - return o.str(); + // JNI crashes with gcc & operator<<(ostream &, long/int) + //std::ostringstream o; + //o << i; + //return o.str(); + char s[256]; + snprintf(s, 256, "%d", i); + return string(s); } /** @@ -86,36 +121,6 @@ toString(const wstring& ws) } /** - * Inserts all elements of a set s into the output stream os. - */ -/* -// neither matches operator<< in: set s ; cout << s; - -inline ostream & -operator<< (ostream & os, const set< string >& s) -{ - os << "{"; - set< string >::iterator i = s.begin(); - if (i != s.end()) { - os << *i; - while (++i != s.end()) - os << "," << *i; - } - os << "}"; - return os; -} - -template< typename T > -inline ostream & -operator<< (ostream& os, const set< T >& s) -{ - typename set< T >::iterator i = s.begin(); -... -} - -*/ - -/** * Returns a string representation of all elements in the set. * * This function is not very efficient in that it involves multiple @@ -125,19 +130,19 @@ inline string toString(const set< string >& s) { string r; - r += "{"; + r += "["; set< string >::iterator i = s.begin(); if (i != s.end()) { r += "\""; r += *i; r += "\""; while (++i != s.end()) { - r += ",\""; + r += ", \""; r += *i; r += "\""; } } - r += "}"; + r += "]"; return r; } === modified file 'storage/ndb/test/crund/src/com/mysql/cluster/crund/Driver.java' --- a/storage/ndb/test/crund/src/com/mysql/cluster/crund/Driver.java 2010-03-01 19:10:54 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/Driver.java 2010-10-01 04:10:21 +0000 @@ -89,23 +89,25 @@ abstract public class Driver { // benchmark settings protected final Properties props = new Properties(); protected String descr = ""; - protected boolean logRealTime = false; - protected boolean logMemUsage = false; - protected boolean includeFullGC = false; - protected boolean logSumOfOps = false; - protected boolean renewOperations = false; - protected boolean renewConnection = false; - protected boolean allowExtendedPC = false; - protected int aRows = (1 << 8); - protected int bRows = (1 << 8); - protected int aStart = (1 << 8), aEnd = (1 << 12), aIncr = (1 << 2); - protected int bStart = (1 << 8), bEnd = (1 << 12), bIncr = (1 << 2); - protected int maxVarbinaryBytes = 100; - protected int maxVarcharChars = 100; - protected int maxBlobBytes = 1000; - protected int maxTextChars = 1000; - protected int warmupRuns = 0; - protected int hotRuns = 0; + protected boolean logRealTime; + protected boolean logMemUsage; + protected boolean includeFullGC; + protected boolean logSumOfOps; + protected boolean renewOperations; + protected boolean renewConnection; + protected boolean allowExtendedPC; + protected int aStart; + protected int bStart; + protected int aEnd; + protected int bEnd; + protected int aScale; + protected int bScale; + protected int maxVarbinaryBytes; + protected int maxVarcharChars; + protected int maxBlobBytes; + protected int maxTextChars; + protected int warmupRuns; + protected int hotRuns; protected final Set exclude = new HashSet(); // ---------------------------------------------------------------------- @@ -263,9 +265,10 @@ abstract public class Driver { init(); // warmup runs - for (int i = 0; i < warmupRuns; i++) + for (int i = 0; i < warmupRuns; i++) { runTests(); - + } + // truncate log file, reset log buffers out.println(); out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); @@ -280,9 +283,10 @@ abstract public class Driver { openLogFile(); // hot runs - for (int i = 0; i < hotRuns; i++) + for (int i = 0; i < hotRuns; i++) { runTests(); - + } + // write log buffers if (logRealTime) { log.println(descr + ", rtime[ms]" @@ -311,7 +315,6 @@ abstract public class Driver { loadProperties(); initProperties(); printProperties(); - checkProperties(); openLogFile(); // init log buffers @@ -383,7 +386,12 @@ abstract public class Driver { * Initializes the benchmark properties. */ protected void initProperties() { - // initialize boolean/numeric properties + //props.list(out); + out.print("initializing properties ... "); + + final StringBuilder msg = new StringBuilder(); + final String eol = System.getProperty("line.separator"); + logRealTime = parseBoolean("logRealTime"); logMemUsage = parseBoolean("logMemUsage"); includeFullGC = parseBoolean("includeFullGC"); @@ -391,14 +399,39 @@ abstract public class Driver { renewOperations = parseBoolean("renewOperations"); renewConnection = parseBoolean("renewConnection"); allowExtendedPC = parseBoolean("allowExtendedPC"); - aRows = parseInt("aRows", 0); - bRows = parseInt("bRows", 0); - aStart = parseInt("aStart", 0); - aEnd = parseInt("aEnd", 0); - aIncr = parseInt("aIncr", 0); - bStart = parseInt("bStart", 0); - bEnd = parseInt("bEnd", 0); - bIncr = parseInt("bIncr", 0); + + aStart = parseInt("aStart", 256); + if (aStart < 1) { + msg.append("[ignored] aStart: " + aStart + eol); + aStart = 256; + } + aEnd = parseInt("aEnd", aStart); + if (aEnd < aStart) { + msg.append("[ignored] aEnd: "+ aEnd + eol); + aEnd = aStart; + } + aScale = parseInt("aScale", 2); + if (aScale < 2) { + msg.append("[ignored] aScale: " + aScale + eol); + aScale = 2; + } + + bStart = parseInt("bStart", 256); + if (bStart < 1) { + msg.append("[ignored] bStart: " + bStart + eol); + bStart = 256; + } + bEnd = parseInt("bEnd", bStart); + if (bEnd < bStart) { + msg.append("[ignored] bEnd: " + bEnd + eol); + bEnd = bStart; + } + bScale = parseInt("bScale", 2); + if (bScale < 2) { + msg.append("[ignored] bScale: " + bScale + eol); + bScale = 2; + } + maxVarbinaryBytes = parseInt("maxVarbinaryBytes", 100); maxVarcharChars = parseInt("maxVarcharChars", 100); maxBlobBytes = parseInt("maxBlobBytes", 1000); @@ -411,13 +444,22 @@ abstract public class Driver { for (int i = 0; i < e.length; i++) { exclude.add(e[i]); } - } + if (msg.length() == 0) { + out.println("[ok]"); + } else { + out.println(); + out.print(msg.toString()); + } + out.println("data set: " + + "[A=" + aStart + ".." + aEnd + + ", B=" + bStart + ".." + bEnd + "]"); + } + /** * Prints the benchmark's properties. */ protected void printProperties() { - //props.list(out); out.println(); out.println("main settings:"); out.println("logRealTime: " + logRealTime); @@ -427,14 +469,12 @@ abstract public class Driver { out.println("renewOperations: " + renewOperations); out.println("renewConnection: " + renewConnection); out.println("allowExtendedPC: " + allowExtendedPC); - out.println("aRows: " + aRows); out.println("aStart: " + aStart); - out.println("aEnd: " + aEnd); - out.println("aIncr: " + aIncr); - out.println("bRows: " + bRows); out.println("bStart: " + bStart); + out.println("aEnd: " + aEnd); out.println("bEnd: " + bEnd); - out.println("bIncr: " + bIncr); + out.println("aScale: " + aScale); + out.println("bScale: " + bScale); out.println("maxVarbinaryBytes: " + maxVarbinaryBytes); out.println("maxVarcharChars: " + maxVarcharChars); out.println("maxBlobBytes: " + maxBlobBytes); @@ -445,109 +485,6 @@ abstract public class Driver { } /** - * Checks the benchmark's properties. - */ - protected void checkProperties() { - out.println(); - out.print("checking properties ... "); - final StringBuilder msg = new StringBuilder(); - final String eol = System.getProperty("line.separator"); - if (aRows > 0) { - if (aStart > 0) { - msg.append("[ignored] aStart: "); - msg.append(aStart); - msg.append(eol); - } - if (aEnd > 0) { - msg.append("[ignored] aEnd: "); - msg.append(aEnd); - msg.append(eol); - } - if (aIncr > 0) { - msg.append("[ignored] aIncr: "); - msg.append(aIncr); - msg.append(eol); - } - aStart = aRows; - aEnd = aRows; - aIncr = 2; - } else { - if (aStart <= 0) { - aStart = (1 << 8); - msg.append("[changed] aStart: "); - msg.append(aStart); - msg.append(eol); - } - if (aEnd < aStart) { - aEnd = aStart; - msg.append("[changed] aEnd: "); - msg.append(aEnd); - msg.append(eol); - } - if (aIncr <= 1) { - aIncr = 2; - msg.append("[changed] aIncr: "); - msg.append(aIncr); - msg.append(eol); - } - } - if (bRows > 0) { - if (bRows < aRows) { - bRows = aRows; - msg.append("[changed] bRows: "); - msg.append(bRows); - msg.append(eol); - } - if (bStart > 0) { - msg.append("[ignored] bStart: "); - msg.append(bStart); - msg.append(eol); - } - if (bEnd > 0) { - msg.append("[ignored] bEnd: "); - msg.append(bEnd); - msg.append(eol); - } - if (bIncr > 0) { - msg.append("[ignored] bIncr: "); - msg.append(bIncr); - msg.append(eol); - } - bStart = bRows; - bEnd = bRows; - bIncr = 2; - } else { - if (bStart < aStart) { - bStart = aStart; - msg.append("[changed] bStart: "); - msg.append(bStart); - msg.append(eol); - } - if (bEnd < bStart) { - bEnd = bStart; - msg.append("[changed] bEnd: "); - msg.append(bEnd); - msg.append(eol); - } - if (bIncr <= 1) { - bIncr = 2; - msg.append("[changed] bIncr: "); - msg.append(bIncr); - msg.append(eol); - } - } - if (msg.length() == 0) { - out.println("[ok]"); - } else { - out.println(); - out.print(msg.toString()); - } - out.println("data range: " - + "[A=" + aStart + ".." + aEnd - + ", B=" + bStart + ".." + bEnd + "]"); - } - - /** * Opens the benchmark's data log file. */ private void openLogFile() throws IOException { @@ -578,9 +515,10 @@ abstract public class Driver { initConnection(); initOperations(); - for (int i = aStart; i <= aEnd; i *= aIncr) { - //for (int j = bBeg; j <= bEnd; j *= bIncr) - for (int j = (i > bStart ? i : bStart); j <= bEnd; j *= bIncr) { + assert (aStart <= aEnd && aScale > 1); + assert (bStart <= bEnd && bScale > 1); + for (int i = aStart; i <= aEnd; i *= aScale) { + for (int j = bStart; j <= bEnd; j *= bScale) { try { runOperations(i, j); } catch (Exception ex) { @@ -606,8 +544,14 @@ abstract public class Driver { protected void runOperations(int countA, int countB) throws Exception { out.println(); out.println("------------------------------------------------------------"); - out.println("countA = " + countA + ", countB = " + countB); - out.println(); + + if (countA > countB) { + out.println("skipping operations ... " + + "[A=" + countA + ", B=" + countB + "]"); + return; + } + out.println("running operations ... " + + "[A=" + countA + ", B=" + countB + "]"); // log buffers if (logRealTime) { @@ -653,7 +597,8 @@ abstract public class Driver { rtimes.append("\t" + ta); out.println(); out.println("total"); - out.println("tx real time = " + ta + "\tms [begin..commit]"); + out.println("tx real time\t\t= " + ta + + "\tms [begin..commit]"); } rtimes.append(endl); } @@ -662,7 +607,7 @@ abstract public class Driver { musage.append("\t" + ma); out.println(); out.println("total"); - out.println("net mem usage = " + (ma >= 0 ? "+" : "") + ma + out.println("net mem usage\t\t= " + (ma >= 0 ? "+" : "") + ma + "\tKiB"); } musage.append(endl); @@ -718,7 +663,8 @@ abstract public class Driver { //t1 = System.currentTimeMillis(); t1 = System.nanoTime() / 1000000; final long t = t1 - t0; - out.println("tx real time = " + t + "\tms [begin..commit]"); + out.println("tx real time\t\t= " + t + + "\tms [begin..commit]"); //rtimes.append("\t" + (Math.round(t / 100.0) / 10.0)); rtimes.append("\t" + t); ta += t; @@ -731,16 +677,8 @@ abstract public class Driver { final long m0K = (m0 / 1024); final long m1K = (m1 / 1024); final long mK = m1K - m0K; - out.println("net mem usage = " + (mK >= 0 ? "+" : "") + mK + out.println("net mem usage\t\t= " + (mK >= 0 ? "+" : "") + mK + "\tKiB [" + m0K + "K->" + m1K + "K]"); -/* - out.println("allocated memory = " - + m1 + "\tK after commit"); - out.println("total memory = " - + (rt.totalMemory() / 1024) + "\tK after commit"); - out.println("max memory = " - + (rt.maxMemory() / 1024) + "\tK after commit"); -*/ musage.append("\t" + mK); ma += mK; } === 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-03-01 19:10:54 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbApiLoad.java 2010-10-01 04:10:21 +0000 @@ -50,32 +50,23 @@ public class NdbApiLoad extends NdbBase loadSystemLibrary("crundndb"); // initialize NDB resources - out.println(); - try { - final int ret = ndbinit(mgmdConnect); - if (ret != 0) { - err.println("NdbApiLoad: failed initializing NDBAPI;" - + " return value = " + ret); - } - } catch (RuntimeException e) { - err.println("NdbApiLoad: failed initializing NDBAPI;" - + " caught exception: " + e); - throw e; + final int ret = ndbinit(mgmdConnect); + if (ret != 0) { + String msg = ("NdbApiLoad: failed initializing NDBAPI;" + + " return value = " + ret); + err.println(msg); + throw new Exception(msg); } } protected void close() throws Exception { // release NDB resources - try { - final int ret = ndbclose(); - if (ret != 0) { - err.println("NdbApiLoad: failed closing NDBAPI;" - + " return value = " + ret); - } - } catch (RuntimeException e) { - err.println("NdbApiLoad: failed closing NDBAPI;" - + " caught exception: " + e); - throw e; + final int ret = ndbclose(); + if (ret != 0) { + String msg = ("NdbApiLoad: failed closing NDBAPI;" + + " return value = " + ret); + err.println(msg); + throw new Exception(msg); } super.close(); } @@ -107,10 +98,14 @@ public class NdbApiLoad extends NdbBase boolean batch); protected native void setB0ByPK(int countA, int countB, boolean batch); - protected native void getAByPK(int countA, int countB, - boolean batch); - protected native void getB0ByPK(int countA, int countB, - boolean batch); + protected native void getAByPK_bb(int countA, int countB, + boolean batch); + protected native void getB0ByPK_bb(int countA, int countB, + boolean batch); + protected native void getAByPK_ar(int countA, int countB, + boolean batch); + protected native void getB0ByPK_ar(int countA, int countB, + boolean batch); protected native void setVarbinary(int countA, int countB, boolean batch, int length); protected native void getVarbinary(int countA, int countB, @@ -171,16 +166,30 @@ public class NdbApiLoad extends NdbBase }); ops.add( - new Op("getAByPK" + (batch ? "_batch" : "")) { + new Op("getAByPK_bb" + (batch ? "_batch" : "")) { + public void run(int countA, int countB) { + getAByPK_bb(countA, countB, batch); + } + }); + + ops.add( + new Op("getAByPK_ar" + (batch ? "_batch" : "")) { + public void run(int countA, int countB) { + getAByPK_ar(countA, countB, batch); + } + }); + + ops.add( + new Op("getB0ByPK_bb" + (batch ? "_batch" : "")) { public void run(int countA, int countB) { - getAByPK(countA, countB, batch); + getB0ByPK_bb(countA, countB, batch); } }); ops.add( - new Op("getB0ByPK" + (batch ? "_batch" : "")) { + new Op("getB0ByPK_ar" + (batch ? "_batch" : "")) { public void run(int countA, int countB) { - getB0ByPK(countA, countB, batch); + getB0ByPK_ar(countA, countB, batch); } }); === 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-02-14 05:05:31 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbBase.java 2010-10-01 04:10:21 +0000 @@ -53,8 +53,8 @@ abstract public class NdbBase extends Dr protected void printProperties() { super.printProperties(); - out.println("ndb.mgmdConnect " + mgmdConnect); - out.println("ndb.catalog " + catalog); - out.println("ndb.schema " + schema); + out.println("ndb.mgmdConnect \"" + mgmdConnect + "\""); + out.println("ndb.catalog \"" + catalog + "\""); + out.println("ndb.schema \"" + schema + "\""); } } === modified file 'storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbJTieLoad.java' --- a/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbJTieLoad.java 2010-09-27 05:31:17 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/NdbJTieLoad.java 2010-10-01 04:10:21 +0000 @@ -182,12 +182,11 @@ public class NdbJTieLoad extends NdbBase // instantiate NDB cluster singleton out.println(); - out.print("creating cluster conn..."); + out.print("creating cluster conn ..."); out.flush(); mgmd = Ndb_cluster_connection.create(mgmdConnect); assert mgmd != null; - //out.println(" [ok]"); - out.println(" [ok, mgmd=" + mgmd + "]"); + out.println(" [ok, mgmd=" + mgmd + "]"); // connect to cluster management node (ndb_mgmd) out.print("connecting to mgmd ..."); @@ -222,7 +221,6 @@ public class NdbJTieLoad extends NdbBase out.flush(); final int initial_wait = 10; // secs to wait until first node detected final int final_wait = 0; // secs 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) { final String msg = ("data nodes were not ready within " @@ -232,10 +230,9 @@ public class NdbJTieLoad extends NdbBase } out.println(" [ok]"); - // connect to database - out.println(); - out.println("connecting to database..."); + out.print("connecting to database..."); + out.flush(); ndb = Ndb.create(mgmd, catalog, schema); final int max_no_tx = 10; // maximum number of parallel tx (<=1024) // note each scan or index scan operation uses one extra transaction @@ -346,7 +343,7 @@ public class NdbJTieLoad extends NdbBase }); ops.add( - new Op("clearVarbinary" + (batch ? "_batch" : "")) { + new Op("clearVarbinary" + l + (batch ? "_batch" : "")) { public void run(int countA, int countB) { setVarbinary(meta.table_B0, 1, countB, batch, null); } @@ -370,6 +367,13 @@ public class NdbJTieLoad extends NdbBase getVarchar(meta.table_B0, 1, countB, batch, s); } }); + + ops.add( + new Op("clearVarchar" + l + (batch ? "_batch" : "")) { + public void run(int countA, int countB) { + setVarchar(meta.table_B0, 1, countB, batch, null); + } + }); } ops.add( === modified file 'storage/ndb/test/crund/src/crundndb/Driver.cpp' --- a/storage/ndb/test/crund/src/crundndb/Driver.cpp 2010-02-14 05:05:31 +0000 +++ b/storage/ndb/test/crund/src/crundndb/Driver.cpp 2010-10-01 04:10:21 +0000 @@ -64,11 +64,14 @@ protected: bool logSumOfOps; bool renewConnection; bool renewOperations; - unsigned int aStart, aEnd, aIncr; - unsigned int bStart, bEnd, bIncr; - unsigned int maxStringLength; - unsigned int warmupRuns; - unsigned int hotRuns; + int aStart, aEnd, aScale; + int bStart, bEnd, bScale; + int maxVarbinaryBytes; + int maxVarcharChars; + int maxBlobBytes; + int maxTextChars; + int warmupRuns; + int hotRuns; set< string > exclude; // the NDB database connection @@ -133,6 +136,16 @@ protected: void printProperties(); /** + * Opens the benchmark's data log file. + */ + void openLogFile(); + + /** + * Closes the benchmark's data log file. + */ + void closeLogFile(); + + /** * Initializes the benchmark's resources. */ void init(); @@ -187,27 +200,36 @@ protected: void clearData(); // operation invocation templates - template< bool, bool > struct DelAllOp; + template< bool > struct ADelAllOp; - template< bool, bool, bool > struct InsOp; + template< bool > struct B0DelAllOp; + + template< bool, bool > struct AInsOp; + + template< bool, bool > struct B0InsOp; + + template< const char** opName, + void (crund_ndb::Operations::*OP)(const NdbDictionary::Table*, + int,int,bool), + bool batch > + struct AByPKOp; template< const char** opName, - bool isTableA, void (crund_ndb::Operations::*OP)(const NdbDictionary::Table*, int,int,bool), bool batch > - struct byPKOp; + struct B0ByPKOp; template< const char** opName, void (crund_ndb::Operations::*OP)(const NdbDictionary::Table*, int,int,bool,int), bool batch > - struct lengthOp; + struct LengthOp; template< const char** opName, void (crund_ndb::Operations::*OP)(int,int,bool), bool forceSend > - struct relOp; + struct RelOp; }; } // crund_ndb @@ -224,6 +246,7 @@ using std::string; using std::wstring; using utils::toBool; +using utils::toInt; using utils::toString; using crund_ndb::Driver; @@ -242,23 +265,23 @@ Driver::run() { init(); // warmup runs - for (unsigned int i = 0; i < warmupRuns; i++) + for (int i = 0; i < warmupRuns; i++) { runTests(); - + } + // truncate log file, reset log buffers cout << endl << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl << "start logging results ..." << endl << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl << endl; - log.close(); - log.open(logFileName.c_str(), ios_base::out | ios_base::trunc); - assert (log.good()); header.rdbuf()->str(""); rtimes.rdbuf()->str(""); + closeLogFile(); + openLogFile(); // hot runs - for (unsigned int i = 0; i < hotRuns; i++) { + for (int i = 0; i < hotRuns; i++) { runTests(); } @@ -284,22 +307,17 @@ Driver::init() { loadProperties(); initProperties(); printProperties(); - - // initialize the benchmark's resources - ops = new crund_ndb::Operations(); - assert (!mgmdConnect.empty()); - ops->init(mgmdConnect.c_str()); - - // open the benchmark's data log file - cout << endl; - cout << "writing results to file: " << logFileName << endl; - log.open(logFileName.c_str()); - assert (log.good()); + openLogFile(); // clear log buffers logHeader = true; header.rdbuf()->str(""); rtimes.rdbuf()->str(""); + + // initialize the benchmark's resources + ops = new crund_ndb::Operations(); + assert (!mgmdConnect.empty()); + ops->init(mgmdConnect.c_str()); } void @@ -308,16 +326,13 @@ Driver::close() { header.rdbuf()->str(""); rtimes.rdbuf()->str(""); - // close the benchmark's data log file - cout << "closing files ... " << flush; - log.close(); - cout << " [ok]" << endl; - // release the benchmark's resources assert (!mgmdConnect.empty()); ops->close(); delete ops; ops = NULL; + + closeLogFile(); } void @@ -338,38 +353,95 @@ Driver::loadProperties() { void Driver::initProperties() { - descr = ""; - logRealTime = false; - logCpuTime = false; - logSumOfOps = false; - renewConnection = false; - renewOperations = false; - aStart = (1 << 8), aEnd = (1 << 12), aIncr = (1 << 2); - bStart = (1 << 8), bEnd = (1 << 12), bIncr = (1 << 2); - maxStringLength = 100; - warmupRuns = 0; - hotRuns = 1; - mgmdConnect = "localhost"; - catalog = ""; - schema = ""; + cout << "initializing properties ... " << flush; + + ostringstream msg; - // initialize boolean properties logRealTime = toBool(props[L"logRealTime"]); logCpuTime = toBool(props[L"logCpuTime"]); logSumOfOps = toBool(props[L"logSumOfOps"]); renewOperations = toBool(props[L"renewOperations"]); renewConnection = toBool(props[L"renewConnection"]); - - // initialize numeric properties - wistringstream(props[L"aStart"]) >> aStart; - wistringstream(props[L"aEnd"]) >> aEnd; - wistringstream(props[L"aIncr"]) >> aIncr; - wistringstream(props[L"bStart"]) >> bStart; - wistringstream(props[L"bEnd"]) >> bEnd; - wistringstream(props[L"bIncr"]) >> bIncr; - wistringstream(props[L"maxStringLength"]) >> maxStringLength; - wistringstream(props[L"warmupRuns"]) >> warmupRuns; - wistringstream(props[L"hotRuns"]) >> hotRuns; + + aStart = toInt(props[L"aStart"], 256, 0); + if (aStart < 1) { + msg << "[ignored] aStart: '" + << toString(props[L"aStart"]) << "'" << endl; + aStart = 256; + } + aEnd = toInt(props[L"aEnd"], aStart, 0); + if (aEnd < aStart) { + msg << "[ignored] aEnd: '" + << toString(props[L"aEnd"]) << "'" << endl; + aEnd = aStart; + } + aScale = toInt(props[L"aScale"], 2, 0); + if (aScale < 2) { + msg << "[ignored] aScale: '" + << toString(props[L"aScale"]) << "'" << endl; + aScale = 2; + } + + bStart = toInt(props[L"bStart"], aStart, 0); + if (bStart < 1) { + msg << "[ignored] bStart: '" + << toString(props[L"bStart"]) << "'" << endl; + bStart = aStart; + } + bEnd = toInt(props[L"bEnd"], bStart, 0); + if (bEnd < bStart) { + msg << "[ignored] bEnd: '" + << toString(props[L"bEnd"]) << "'" << endl; + bEnd = bStart; + } + bScale = toInt(props[L"bScale"], 2, 0); + if (bScale < 2) { + msg << "[ignored] bScale: '" + << toString(props[L"bScale"]) << "'" << endl; + bScale = 2; + } + + maxVarbinaryBytes = toInt(props[L"maxVarbinaryBytes"], 100, 0); + if (maxVarbinaryBytes < 1) { + msg << "[ignored] maxVarbinaryBytes: '" + << toString(props[L"maxVarbinaryBytes"]) << "'" << endl; + maxVarbinaryBytes = 100; + } + + maxVarcharChars = toInt(props[L"maxVarcharChars"], 100, 0); + if (maxVarcharChars < 1) { + msg << "[ignored] maxVarcharChars: '" + << toString(props[L"maxVarcharChars"]) << "'" << endl; + maxVarcharChars = 100; + } + + maxBlobBytes = toInt(props[L"maxBlobBytes"], 1000, 0); + if (maxBlobBytes < 1) { + msg << "[ignored] maxBlobBytes: '" + << toString(props[L"maxBlobBytes"]) << "'" << endl; + maxBlobBytes = 1000; + } + + maxTextChars = toInt(props[L"maxTextChars"], 1000, 0); + if (maxTextChars < 1) { + msg << "[ignored] maxTextChars: '" + << toString(props[L"maxTextChars"]) << "'" << endl; + maxTextChars = 1000; + } + + 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; + } // initialize exclude set const wstring& estr = props[L"exclude"]; @@ -397,11 +469,18 @@ Driver::initProperties() { schema = toString(props[L"ndb.schema"]); descr = "C++->NDBAPI(" + mgmdConnect + ")"; + + if (msg.tellp() == 0) { + cout << "[ok]" << endl; + } else { + cout << endl << msg.str() << endl; + } + + cout << "data set: " + << "[A=" << aStart << ".." << aEnd + << ", B=" << bStart << ".." << bEnd << "]" << endl; } -/** - * Prints the benchmark's properties. - */ void Driver::printProperties() { const ios_base::fmtflags f = cout.flags(); @@ -409,19 +488,22 @@ Driver::printProperties() { //cout << ios_base::boolalpha; cout.flags(ios_base::boolalpha); - cout << "main settings:" << endl; + cout << endl << "main settings:" << endl; cout << "logRealTime: " << logRealTime << endl; cout << "logCpuTime: " << logCpuTime << endl; cout << "logSumOfOps: " << logSumOfOps << endl; cout << "renewOperations: " << renewOperations << endl; cout << "renewConnection: " << renewConnection << endl; cout << "aStart: " << aStart << endl; - cout << "aEnd: " << aEnd << endl; - cout << "aIncr: " << aIncr << endl; cout << "bStart: " << bStart << endl; + cout << "aEnd: " << aEnd << endl; cout << "bEnd: " << bEnd << endl; - cout << "bIncr: " << bIncr << endl; - cout << "maxStringLength: " << maxStringLength << endl; + cout << "aScale: " << aScale << endl; + cout << "bScale: " << bScale << endl; + cout << "maxVarbinaryBytes: " << maxVarbinaryBytes << endl; + cout << "maxVarcharChars: " << maxVarcharChars << endl; + cout << "maxBlobBytes: " << maxBlobBytes << endl; + cout << "maxTextChars: " << maxTextChars << endl; cout << "warmupRuns: " << warmupRuns << endl; cout << "hotRuns: " << hotRuns << endl; cout << "exclude: " << toString(exclude) << endl; @@ -432,6 +514,22 @@ Driver::printProperties() { cout.flags(f); } +void +Driver::openLogFile() { + cout << endl + << "writing results to file: " << logFileName << endl; + //log.open(logFileName.c_str()); + log.open(logFileName.c_str(), ios_base::out | ios_base::trunc); + assert (log.good()); +} + +void +Driver::closeLogFile() { + cout << "closing files ... " << flush; + log.close(); + cout << " [ok]" << endl; +} + // ---------------------------------------------------------------------- void @@ -439,9 +537,10 @@ Driver::runTests() { initConnection(); initOperations(); - for (unsigned int i = aStart; i <= aEnd; i *= aIncr) { - //for (int j = bBeg; j <= bEnd; j *= bIncr) - for (unsigned int j = (i > bStart ? i : bStart); j <= bEnd; j *= bIncr) { + assert(aStart <= aEnd && aScale > 1); + assert(bStart <= bEnd && bScale > 1); + for (int i = aStart; i <= aEnd; i *= aScale) { + for (int j = bStart; j <= bEnd; j *= bScale) { runOperations(i, j); } } @@ -458,9 +557,15 @@ Driver::runTests() { void Driver::runOperations(int countA, int countB) { cout << endl - << "------------------------------------------------------------" << endl - << "countA = " << countA << ", countB = " << countB << endl - << endl; + << "------------------------------------------------------------" << endl; + + if (countA > countB) { + cout << "skipping operations ... " + << "[A=" << countA << ", B=" << countB << "]" << endl; + return; + } + cout << "running operations ... " + << "[A=" << countA << ", B=" << countB << "]" << endl; // log buffers if (logRealTime) { @@ -507,7 +612,7 @@ Driver::runOperations(int countA, int co rtimes << "\t" << rta; cout << endl << "total" << endl - << "tx real time = " << rta + << "tx real time\t\t= " << rta << "\tms [begin..commit]" << endl; } rtimes << endl; @@ -517,7 +622,7 @@ Driver::runOperations(int countA, int co ctimes << "\t" << cta; cout << endl << "total" << endl - << "tx cpu time = " << cta + << "tx cpu time\t\t= " << cta << "\tms [begin..commit]" << endl; } ctimes << endl; @@ -570,7 +675,7 @@ Driver::commit(const string& name) { rtimes << "\tERROR"; } else { long t = long(hrt_rtmicros(&t1.rtstamp, &t0.rtstamp)/1000); - cout << "tx real time = " << t + cout << "tx real time\t\t= " << t << "\tms [begin..commit]" << endl; rtimes << "\t" << t; rta += t; @@ -583,7 +688,7 @@ Driver::commit(const string& name) { ctimes << "\tERROR"; } else { long t = long(hrt_ctmicros(&t1.ctstamp, &t0.ctstamp)/1000); - cout << "tx cpu time = " << t + cout << "tx cpu time\t\t= " << t << "\tms [begin..commit]" << endl; ctimes << "\t" << t; cta += t; @@ -620,47 +725,81 @@ Driver::initOperations() { // the operation invocation templates look a bit complex, but they help // a lot to factorize code over the operations' parameter signatures -template< bool tableA, bool batch > -struct Driver::DelAllOp : Op { - DelAllOp() : Op(string(string(tableA ? "delAllA" : "delAllB0") - + (batch ? "_batch" : ""))) { +template< bool batch > +struct Driver::ADelAllOp : Op { + ADelAllOp() : Op(string("delAllA") + + (batch ? "_batch" : "")) { + } + + virtual void run(int countA, int countB) const { + int count; + ops->delByScan(ops->meta->table_A, count, batch); + assert (count == countA); + } +}; + +template< bool batch > +struct Driver::B0DelAllOp : Op { + B0DelAllOp() : Op(string("delAllB0") + + (batch ? "_batch" : "")) { } virtual void run(int countA, int countB) const { int count; - ops->delByScan((tableA ? ops->meta->table_A : ops->meta->table_B0), - count, batch); - assert (count == (tableA ? countA : countB)); + ops->delByScan(ops->meta->table_B0, count, batch); + assert (count == countB); + } +}; + +template< bool setAttrs, bool batch > +struct Driver::AInsOp : Op { + AInsOp() : Op(string("insA") + + (setAttrs ? "_attr" : "") + + (batch ? "_batch" : "")) { + } + + virtual void run(int countA, int countB) const { + ops->ins(ops->meta->table_A, 1, countA, setAttrs, batch); } }; -template< bool tableA, bool setAttrs, bool batch > -struct Driver::InsOp : Op { - InsOp() : Op(string(string(tableA ? "insA" : "insB0") - + (setAttrs ? "_attr" : "") - + (batch ? "_batch" : ""))) { +template< bool setAttrs, bool batch > +struct Driver::B0InsOp : Op { + B0InsOp() : Op(string("insB0") + + (setAttrs ? "_attr" : "") + + (batch ? "_batch" : "")) { } virtual void run(int countA, int countB) const { - ops->ins((tableA ? ops->meta->table_A : ops->meta->table_B0), - 1, (tableA ? countA : countB), setAttrs, batch); + ops->ins(ops->meta->table_B0, 1, countB, setAttrs, batch); } }; template< const char** opName, - bool isTableA, void (crund_ndb::Operations::*OP)(const NdbDictionary::Table*, int,int,bool), bool batch > -struct Driver::byPKOp : Op { - byPKOp() : Op(string(*opName) - + string(isTableA ? "AByPK" : "B0ByPK") +struct Driver::AByPKOp : Op { + AByPKOp() : Op(string(*opName) + (batch ? "_batch" : "")) { } virtual void run(int countA, int countB) const { - (ops->*OP)((isTableA ? ops->meta->table_A : ops->meta->table_B0), - 1, (isTableA ? countA : countB), batch); + (ops->*OP)(ops->meta->table_A, 1, countA, batch); + } +}; + +template< const char** opName, + void (crund_ndb::Operations::*OP)(const NdbDictionary::Table*, + int,int,bool), + bool batch > +struct Driver::B0ByPKOp : Op { + B0ByPKOp() : Op(string(*opName) + + (batch ? "_batch" : "")) { + } + + virtual void run(int countA, int countB) const { + (ops->*OP)(ops->meta->table_B0, 1, countB, batch); } }; @@ -668,10 +807,10 @@ template< const char** opName, void (crund_ndb::Operations::*OP)(const NdbDictionary::Table*, int,int,bool,int), bool batch > -struct Driver::lengthOp : Op { +struct Driver::LengthOp : Op { const int length; - lengthOp(int length) : Op(string(*opName) + LengthOp(int length) : Op(string(*opName) + toString(length) + (batch ? "_batch" : "")), length(length) { @@ -685,8 +824,8 @@ struct Driver::lengthOp : Op { template< const char** opName, void (crund_ndb::Operations::*OP)(int x,int y,bool z), bool forceSend > -struct Driver::relOp : Op { - relOp() : Op(string(*opName) + (forceSend ? "_forceSend" : "")) { +struct Driver::RelOp : Op { + RelOp() : Op(string(*opName) + (forceSend ? "_forceSend" : "")) { } virtual void run(int countA, int countB) const { @@ -700,15 +839,22 @@ struct Driver::relOp : Op { // // Until then, we have to allocate the operation names as variables // (which are external at file scope by default). -const char* del_s = "del"; -const char* set_s = "set"; -const char* get_s = "get"; +const char* delAByPK_s = "delAByPK"; +const char* delB0ByPK_s = "delB0ByPK"; +const char* setAByPK_s = "setAByPK"; +const char* setB0ByPK_s = "setB0ByPK"; +const char* getAByPK_bb_s = "getAByPK_bb"; +const char* getB0ByPK_bb_s = "getB0ByPK_bb"; +const char* getAByPK_ar_s = "getAByPK_ar"; +const char* getB0ByPK_ar_s = "getB0ByPK_ar"; + const char* setVarbinary_s = "setVarbinary"; const char* getVarbinary_s = "getVarbinary"; const char* clearVarbinary_s = "clearVarbinary"; const char* setVarchar_s = "setVarchar"; const char* getVarchar_s = "getVarchar"; const char* clearVarchar_s = "clearVarchar"; + const char* setB0ToA_s = "setB0->A"; const char* navB0ToA_s = "navB0->A"; const char* navB0ToAalt_s = "navB0->A_alt"; @@ -719,84 +865,92 @@ const char* nullB0ToA_s = "nullB0->A"; template< bool feat > void Driver::initOperationsFeat() { - const bool tableA = true; const bool setAttr = true; operations.push_back( - new InsOp< tableA, !setAttr, feat >()); + new AInsOp< !setAttr, feat >()); + + operations.push_back( + new B0InsOp< !setAttr, feat >()); operations.push_back( - new InsOp< !tableA, !setAttr, feat >()); + new AByPKOp< &setAByPK_s, &crund_ndb::Operations::setByPK, feat >()); operations.push_back( - new byPKOp< &set_s, tableA, &crund_ndb::Operations::setByPK, feat >()); + new B0ByPKOp< &setB0ByPK_s, &crund_ndb::Operations::setByPK, feat >()); operations.push_back( - new byPKOp< &set_s, !tableA, &crund_ndb::Operations::setByPK, feat >()); + new AByPKOp< &getAByPK_bb_s, &crund_ndb::Operations::getByPK_bb, feat >()); operations.push_back( - new byPKOp< &get_s, tableA, &crund_ndb::Operations::getByPK, feat >()); + new AByPKOp< &getAByPK_ar_s, &crund_ndb::Operations::getByPK_ar, feat >()); operations.push_back( - new byPKOp< &get_s, !tableA, &crund_ndb::Operations::getByPK, feat >()); + new B0ByPKOp< &getB0ByPK_bb_s, &crund_ndb::Operations::getByPK_bb, feat >()); - for (unsigned int i = 1; i <= maxStringLength; i *= 10) { + operations.push_back( + new B0ByPKOp< &getB0ByPK_ar_s, &crund_ndb::Operations::getByPK_ar, feat >()); + + for (int i = 1; i <= maxVarbinaryBytes; i *= 10) { const int length = i; operations.push_back( - new lengthOp< &setVarbinary_s, &crund_ndb::Operations::setVarbinary, feat >(length)); + new LengthOp< &setVarbinary_s, &crund_ndb::Operations::setVarbinary, feat >(length)); operations.push_back( - new lengthOp< &getVarbinary_s, &crund_ndb::Operations::getVarbinary, feat >(length)); + new LengthOp< &getVarbinary_s, &crund_ndb::Operations::getVarbinary, feat >(length)); operations.push_back( - new lengthOp< &clearVarbinary_s, &crund_ndb::Operations::setVarbinary, feat >(0)); + new LengthOp< &clearVarbinary_s, &crund_ndb::Operations::setVarbinary, feat >(0)); + } + + for (int i = 1; i <= maxVarcharChars; i *= 10) { + const int length = i; operations.push_back( - new lengthOp< &setVarchar_s, &crund_ndb::Operations::setVarchar, feat >(length)); + new LengthOp< &setVarchar_s, &crund_ndb::Operations::setVarchar, feat >(length)); operations.push_back( - new lengthOp< &getVarchar_s, &crund_ndb::Operations::getVarchar, feat >(length)); + new LengthOp< &getVarchar_s, &crund_ndb::Operations::getVarchar, feat >(length)); operations.push_back( - new lengthOp< &clearVarchar_s, &crund_ndb::Operations::setVarchar, feat >(0)); - + new LengthOp< &clearVarchar_s, &crund_ndb::Operations::setVarchar, feat >(0)); } operations.push_back( - new relOp< &setB0ToA_s, &crund_ndb::Operations::setB0ToA, feat >()); + new RelOp< &setB0ToA_s, &crund_ndb::Operations::setB0ToA, feat >()); operations.push_back( - new relOp< &navB0ToA_s, &crund_ndb::Operations::navB0ToA, feat >()); + new RelOp< &navB0ToA_s, &crund_ndb::Operations::navB0ToA, feat >()); operations.push_back( - new relOp< &navB0ToAalt_s, &crund_ndb::Operations::navB0ToAalt, feat >()); + new RelOp< &navB0ToAalt_s, &crund_ndb::Operations::navB0ToAalt, feat >()); operations.push_back( - new relOp< &navAToB0_s, &crund_ndb::Operations::navAToB0, feat >()); + new RelOp< &navAToB0_s, &crund_ndb::Operations::navAToB0, feat >()); operations.push_back( - new relOp< &navAToB0alt_s, &crund_ndb::Operations::navAToB0alt, feat >()); + new RelOp< &navAToB0alt_s, &crund_ndb::Operations::navAToB0alt, feat >()); operations.push_back( - new relOp< &nullB0ToA_s, &crund_ndb::Operations::nullB0ToA, feat >()); + new RelOp< &nullB0ToA_s, &crund_ndb::Operations::nullB0ToA, feat >()); operations.push_back( - new byPKOp< &del_s, !tableA, &crund_ndb::Operations::delByPK, feat >()); + new B0ByPKOp< &setAByPK_s, &crund_ndb::Operations::delByPK, feat >()); operations.push_back( - new byPKOp< &del_s, tableA, &crund_ndb::Operations::delByPK, feat >()); + new AByPKOp< &setB0ByPK_s, &crund_ndb::Operations::delByPK, feat >()); operations.push_back( - new InsOp< tableA, setAttr, feat >()); + new AInsOp< setAttr, feat >()); operations.push_back( - new InsOp< !tableA, setAttr, feat >()); + new B0InsOp< setAttr, feat >()); operations.push_back( - new DelAllOp< !tableA, feat >()); + new ADelAllOp< feat >()); operations.push_back( - new DelAllOp< tableA, feat >()); + new B0DelAllOp< feat >()); } void @@ -813,14 +967,7 @@ Driver::closeOperations() { void Driver::clearData() { - cout << "deleting all rows ..." << flush; - int delB0 = -1; - const bool batch = true; - ops->delByScan(ops->meta->table_B0, delB0, batch); - cout << " [B0: " << delB0 << flush; - int delA = -1; - ops->delByScan(ops->meta->table_A, delA, batch); - cout << ", A: " << delA << "]" << endl; + ops->clearData(); } //--------------------------------------------------------------------------- === modified file 'storage/ndb/test/crund/src/crundndb/Operations.cpp' --- a/storage/ndb/test/crund/src/crundndb/Operations.cpp 2010-09-29 10:02:15 +0000 +++ b/storage/ndb/test/crund/src/crundndb/Operations.cpp 2010-10-01 04:10:21 +0000 @@ -15,6 +15,7 @@ #include #include "helpers.hpp" +#include "string_helpers.hpp" #include "Operations.hpp" //using namespace std; @@ -26,6 +27,9 @@ using std::endl; using crund_ndb::Meta; using crund_ndb::Operations; +// JNI crashes with gcc & operator<<(ostream &, long/int) +using utils::toString; + /************************************************************ * Helper Macros & Functions ************************************************************/ @@ -35,8 +39,8 @@ using crund_ndb::Operations; // - all errors are reported and then followed by a process exit /* -// runtime/compiler bug? macro aborts during into->string conversion -#define ABORT_NDB_ERROR0(error) \ +// JNI crashes with gcc & operator<<(ostream &, long/int) +#define ABORT_NDB_ERROR0(error) \ do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \ << ", code: " << (int)error.code \ << ", msg: " << error.message << "." << endl; \ @@ -59,14 +63,6 @@ using crund_ndb::Operations; #define VERIFY(cond) \ if (cond); else ABORT_ERROR("wrong data; verification failed") -/* -static ostream& operator<<(ostream& s, const NdbError& e) -{ - s << "code: " << e.code << ", msg: " << e.message << "."; - return s; -} -*/ - /************************************************************ * Member Functions of Class Meta ************************************************************/ @@ -168,14 +164,17 @@ Operations::init(const char* mgmd_conn_s assert (mgmd_conn_str); // ndb_init must be called first - cout << "initializing NDBAPI..." << flush; + cout << endl + << "initializing NDBAPI ..." << flush; int stat = ndb_init(); if (stat != 0) ABORT_ERROR("ndb_init() returned: " << stat); - cout << " [ok]" << endl; + cout << " [ok]" << endl; // instantiate NDB cluster singleton + cout << "creating cluster conn ..." << flush; mgmd = new Ndb_cluster_connection(mgmd_conn_str); + cout << " [ok]" << endl; // no useful mgmd->string conversion // connect to cluster management node (ndb_mgmd) cout << "connecting to mgmd ..." << flush; @@ -219,10 +218,10 @@ Operations::initConnection(const char* c // connect to database cout << "connecting to database..." << flush; ndb = new Ndb(mgmd, catalog, schema); - //const int max_no_tx = 10; // maximum number of parallel tx (<=1024) + 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(max_no_tx) != 0) - if (ndb->init() != 0) + //if (ndb->init() != 0) + if (ndb->init(max_no_tx) != 0) ABORT_NDB_ERROR(ndb->getNdbError()); cout << " [ok]" << endl; @@ -291,6 +290,19 @@ Operations::closeTransaction() // ---------------------------------------------------------------------- +void +Operations::clearData() +{ + cout << "deleting all rows ..." << flush; + const bool batch = true; + int delB0 = -1; + delByScan(meta->table_B0, delB0, batch); + cout << " [B0: " << toString(delB0) << flush; + int delA = -1; + delByScan(meta->table_A, delA, batch); + cout << ", A: " << toString(delA) << "]" << endl; +} + struct CommonAB { Int32 id; Int32 cint; @@ -439,7 +451,7 @@ Operations::delByScan(const NdbDictionar const bool forceSend_ = false; const bool releaseOp = false; op->close(forceSend_, releaseOp); - //CDBG << " deleted " << count << " rows" << endl; + //CDBG << "!!! deleted " << toString(count) << " rows" << endl; commitTransaction(); closeTransaction(); @@ -506,9 +518,9 @@ Operations::setByPK(const NdbDictionary: } void -Operations::getByPK(const NdbDictionary::Table* table, - int from, int to, - bool batch) +Operations::getByPK_bb(const NdbDictionary::Table* table, + int from, int to, + bool batch) { // allocate attributes holder const int count = (to - from) + 1; @@ -556,7 +568,7 @@ Operations::getByPK(const NdbDictionary: VERIFY(id == i); Int32 j = getCommonAB(pab); - //CDBG << "!!! id=" << id << ", i=" << i << endl; + //CDBG << "!!! id=" << toString(id) << ", i=" << toString(i) << endl; VERIFY(j == id); } @@ -564,7 +576,6 @@ Operations::getByPK(const NdbDictionary: delete[] ab; } -// XXX struct CommonAB_AR { NdbRecAttr* id; NdbRecAttr* cint; @@ -573,7 +584,6 @@ struct CommonAB_AR { NdbRecAttr* cdouble; }; -// XXX static inline Int32 getCommonAB(const CommonAB_AR* const ab) { @@ -587,7 +597,6 @@ getCommonAB(const CommonAB_AR* const ab) return cint; } -// XXX void Operations::getByPK_ar(const NdbDictionary::Table* table, int from, int to, @@ -639,7 +648,7 @@ Operations::getByPK_ar(const NdbDictiona VERIFY(id == i); Int32 j = getCommonAB(pab); - //CDBG << "!!! id=" << id << ", i=" << i << endl; + //CDBG << "!!! id=" << toString(id) << ", i=" << toString(i) << endl; VERIFY(j == id); } @@ -695,11 +704,9 @@ Operations::setVar(const NdbDictionary:: buf = new char[sbuf]; buf[0] = (char)slen; memcpy(buf + 1, str, slen); -#if 0 - CDBG << "!!! buf[0]=" << (int)buf[0] << endl; - CDBG << "!!! buf[1]=" << (int)buf[1] << endl; - CDBG << "!!! buf[" << slen << "]=" << (int)buf[slen] << endl; -#endif + //CDBG << "!!! buf[0]=" << toString(buf[0]) << endl; + //CDBG << "!!! buf[1]=" << toString(buf[1]) << endl; + //CDBG << "!!! buf[" << toString(slen) << "]=" << toString(buf[slen]) << endl; } beginTransaction(); @@ -743,13 +750,11 @@ Operations::getVar(const NdbDictionary:: const size_t sline = (1 + slen); const size_t sbuf = count * sline; char* const buf = new char[sbuf]; -#if 0 - memset(buf, 1, sbuf); - CDBG << "!!! buf[0]=" << (int)buf[0] << endl; - CDBG << "!!! buf[1]=" << (int)buf[1] << endl; - CDBG << "!!! buf[" << slen << "]=" << (int)buf[slen] << endl; - CDBG << "!!! buf[" << (slen+1) << "]=" << (int)buf[slen + 1] << endl; -#endif + //memset(buf, 1, sbuf); + //CDBG << "!!! buf[0]=" << toString(buf[0]) << endl; + //CDBG << "!!! buf[1]=" << toString(buf[1]) << endl; + //CDBG << "!!! buf[" << toString(slen) << "]=" << toString(buf[slen]) << endl; + //CDBG << "!!! buf[" << toString(slen+1) << "]=" << toString(buf[slen+1]) << endl; // fetch string attribute by key char* s = buf; @@ -781,12 +786,11 @@ Operations::getVar(const NdbDictionary:: // copy (move) the strings to make them aligned and 0-terminated s = buf; for (int i = from; i <= to; i++, s += sline) { -#if 0 - CDBG << "!!! s[0]=" << (int)s[0] << endl; - CDBG << "!!! s[1]=" << (int)s[1] << endl; - CDBG << "!!! s[" << slen << "]=" << (int)s[slen] << endl; - CDBG << "!!! s[" << (slen+1) << "]=" << (int)s[slen + 1] << endl; -#endif + //CDBG << "!!! s[0]=" << toString(s[0]) << endl; + //CDBG << "!!! s[1]=" << toString(s[1]) << endl; + //CDBG << "!!! s[" << toString(slen) << "]=" << toString(s[slen]) << endl; + //CDBG << "!!! s[" << toString(slen+1) << "]=" << toString(s[slen + 1]) << endl; + const size_t n = s[0]; VERIFY(n < sline); @@ -795,7 +799,6 @@ Operations::getVar(const NdbDictionary:: s[n] = 0; // check fetched values - //CDBG << "!!! s=" << (void*)s << ", '" << s << "'" << endl; VERIFY(strcmp(s, str) == 0); } assert (s == buf + sbuf); @@ -936,7 +939,7 @@ Operations::navB0ToA(int count_A, int co VERIFY(id == ((i - 1) % count_A) + 1); Int32 j = getCommonAB(pab); - //CDBG << "!!! id=" << id << ", i=" << i << endl; + //CDBG << "!!! id=" << toString(id) << ", i=" << toString(i) << endl; VERIFY(j == id); } @@ -1025,7 +1028,7 @@ Operations::navB0ToAalt(int count_A, int VERIFY(id == ((i - 1) % count_A) + 1); Int32 j = getCommonAB(pab); - //CDBG << "!!! id=" << id << ", i=" << i << endl; + //CDBG << "!!! id=" << toString(id) << ", i=" << toString(i) << endl; VERIFY(j == id); } @@ -1098,21 +1101,19 @@ Operations::navAToB0(int count_A, int co } commitTransaction(); closeTransaction(); - //CDBG << "!!! pab - ab =" << (pab-ab) << endl; + //CDBG << "!!! pab - ab =" << toString(pab-ab) << endl; assert (pab == ab + count_B); // check fetched values - // XXX this is may not be the most efficient way of testing... -// #ifndef NDEBUG + // XXX this is not the most efficient way of testing... vector b(ab, ab + count_B); sort(b.begin(), b.end(), compare); vector::const_iterator it = b.begin(); for (int i = 1; i <= count_B; i++, it++) { Int32 id = getCommonAB(&it[0]); - //CDBG << "!!! id=" << id << ", i=" << i << endl; + //CDBG << "!!! id=" << toString(id) << ", i=" << toString(i) << endl; VERIFY(id == i); } -//#endif // release attributes holder delete[] ab; @@ -1199,22 +1200,20 @@ Operations::navAToB0alt(int count_A, int } commitTransaction(); closeTransaction(); - //CDBG << "!!! a_id=" << a_id << ", pab - ab =" << (pab-ab) << endl; + //CDBG << "!!! pab - ab =" << toString(pab-ab) << endl; assert (a_id == count_A + 1); assert (pab == ab + count_B); // check fetched values - // XXX this is may not be the most efficient way of testing... -// #ifndef NDEBUG + // XXX this is not the most efficient way of testing... vector b(ab, ab + count_B); sort(b.begin(), b.end(), compare); vector::const_iterator it = b.begin(); for (int i = 1; i <= count_B; i++, it++) { Int32 id = getCommonAB(&it[0]); - //CDBG << "!!! id=" << id << ", i=" << i << endl; + //CDBG << "!!! id=" << toString(id) << ", i=" << toString(i) << endl; VERIFY(id == i); } -//#endif // release attributes holder delete[] ab; === modified file 'storage/ndb/test/crund/src/crundndb/Operations.hpp' --- a/storage/ndb/test/crund/src/crundndb/Operations.hpp 2010-02-14 05:05:31 +0000 +++ b/storage/ndb/test/crund/src/crundndb/Operations.hpp 2010-10-01 04:10:21 +0000 @@ -88,6 +88,8 @@ public: void rollbackTransaction(); + void clearData(); + void delByScan(const NdbDictionary::Table* table, int& count, bool batch); @@ -100,10 +102,9 @@ public: void setByPK(const NdbDictionary::Table* table, int from, int to, bool batch); - void getByPK(const NdbDictionary::Table* table, int from, int to, - bool batch); + void getByPK_bb(const NdbDictionary::Table* table, int from, int to, + bool batch); - // XXX void getByPK_ar(const NdbDictionary::Table* table, int from, int to, bool batch); === 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-02-14 05:05:31 +0000 +++ b/storage/ndb/test/crund/src/crundndb/com_mysql_cluster_crund_NdbApiLoad.cpp 2010-10-01 04:10:21 +0000 @@ -4,7 +4,6 @@ */ #include -#include #include #include "com_mysql_cluster_crund_NdbApiLoad.h" @@ -93,13 +92,7 @@ Java_com_mysql_cluster_crund_NdbApiLoad_ jobject obj) { TRACE("clearData()"); - cout << "deleting all rows ..." << flush; - int delB0; - ops->delByScan(ops->meta->table_B0, delB0, true); - cout << " [B0: " << delB0 << flush; - int delA; - ops->delByScan(ops->meta->table_A, delA, true); - cout << ", A: " << delA << "]" << endl; + ops->clearData(); } JNIEXPORT void JNICALL @@ -223,25 +216,47 @@ Java_com_mysql_cluster_crund_NdbApiLoad_ } JNIEXPORT void JNICALL -Java_com_mysql_cluster_crund_NdbApiLoad_getAByPK(JNIEnv* env, - jobject obj, - jint count_A, - jint count_B, - jboolean batch) +Java_com_mysql_cluster_crund_NdbApiLoad_getAByPK_1bb(JNIEnv* env, + jobject obj, + jint count_A, + jint count_B, + jboolean batch) { - TRACE("getAByPK()"); - ops->getByPK(ops->meta->table_A, 1, count_A, batch == JNI_TRUE); + TRACE("getAByPK_bb()"); + ops->getByPK_bb(ops->meta->table_A, 1, count_A, batch == JNI_TRUE); } JNIEXPORT void JNICALL -Java_com_mysql_cluster_crund_NdbApiLoad_getB0ByPK(JNIEnv* env, - jobject obj, - jint count_A, - jint count_B, - jboolean batch) +Java_com_mysql_cluster_crund_NdbApiLoad_getB0ByPK_1bb(JNIEnv* env, + jobject obj, + jint count_A, + jint count_B, + jboolean batch) +{ + TRACE("getB0ByPK_bb()"); + ops->getByPK_bb(ops->meta->table_B0, 1, count_B, batch == JNI_TRUE); +} + +JNIEXPORT void JNICALL +Java_com_mysql_cluster_crund_NdbApiLoad_getAByPK_1ar(JNIEnv* env, + jobject obj, + jint count_A, + jint count_B, + jboolean batch) +{ + TRACE("getAByPK_ar()"); + ops->getByPK_ar(ops->meta->table_A, 1, count_A, batch == JNI_TRUE); +} + +JNIEXPORT void JNICALL +Java_com_mysql_cluster_crund_NdbApiLoad_getB0ByPK_1ar(JNIEnv* env, + jobject obj, + jint count_A, + jint count_B, + jboolean batch) { - TRACE("getB0ByPK()"); - ops->getByPK(ops->meta->table_B0, 1, count_B, batch == JNI_TRUE); + TRACE("getB0ByPK_ar()"); + ops->getByPK_ar(ops->meta->table_B0, 1, count_B, batch == JNI_TRUE); } JNIEXPORT void JNICALL --===============0467141801== 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: 9ab9e4c4628dc7a1b3afd637dce384384248bbc5 # timestamp: 2010-09-30 21:10:45 -0700 # base_revision_id: jonas@stripped # # Begin bundle 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 --===============0467141801==--