diff --git a/.bzrignore b/.bzrignore index 00d207919a8..3932ed4d127 100644 --- a/.bzrignore +++ b/.bzrignore @@ -859,6 +859,7 @@ ndb/test/ndbapi/testNodeRestart ndb/test/ndbapi/testOIBasic ndb/test/ndbapi/testOperations ndb/test/ndbapi/testRestartGci +ndb/test/ndbapi/testSRBank ndb/test/ndbapi/testScan ndb/test/ndbapi/testScan.dsp ndb/test/ndbapi/testScanInterpreter diff --git a/extra/Makefile.am b/extra/Makefile.am index 9fac05d0160..457fddce673 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -38,7 +38,7 @@ $(top_builddir)/include/mysqld_ername.h: $(top_builddir)/include/mysqld_error.h $(top_builddir)/include/sql_state.h: $(top_builddir)/include/mysqld_error.h bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \ - resolve_stack_dump mysql_waitpid # innochecksum + resolve_stack_dump mysql_waitpid innochecksum noinst_PROGRAMS = charset2html # Don't update the files from bitkeeper diff --git a/extra/innochecksum.c b/extra/innochecksum.c index bce4214847d..bbeb96224c9 100644 --- a/extra/innochecksum.c +++ b/extra/innochecksum.c @@ -140,10 +140,11 @@ int main(int argc, char **argv) { int now; // current time int lastt; // last time ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; // ulints for checksum storage - struct stat64 st; // for stat, if you couldn't guess + struct stat st; // for stat, if you couldn't guess unsigned long long int size; // size of file (has to be 64 bits) ulint pages; // number of pages in file ulint start_page = 0, end_page = 0, use_end_page = 0; // for starting and ending at certain pages + off_t offset = 0; int just_count = 0; // if true, just print page count int verbose = 0; int debug = 0; @@ -202,7 +203,7 @@ int main(int argc, char **argv) { } // stat the file to get size and page count - if (stat64(argv[optind], &st)) { + if (stat(argv[optind], &st)) { perror("error statting file"); return 1; } @@ -217,7 +218,7 @@ int main(int argc, char **argv) { } // open the file for reading - f = fopen64(argv[optind], "r"); + f = fopen(argv[optind], "r"); if (!f) { perror("error opening file"); return 1; @@ -230,7 +231,10 @@ int main(int argc, char **argv) { perror("unable to obtain file descriptor number"); return 1; } - if (lseek64(fd, start_page * UNIV_PAGE_SIZE, SEEK_SET) != (start_page * UNIV_PAGE_SIZE)) { + + offset = (off_t)start_page * (off_t)UNIV_PAGE_SIZE; + + if (lseek(fd, offset, SEEK_SET) != offset) { perror("unable to seek to necessary offset"); return 1; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 09d15f79198..b9532705683 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -179,6 +179,7 @@ our $exe_mysql_fix_system_tables; our $exe_mysqltest; our $exe_slave_mysqld; our $exe_im; +our $exe_my_print_defaults; our $opt_bench= 0; our $opt_small_bench= 0; @@ -872,6 +873,8 @@ sub executable_setup () { $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); $exe_mysql_fix_system_tables= mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables"); + $exe_my_print_defaults= + mtr_script_exists("$glob_basedir/extra/my_print_defaults"); $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/storage/ndb/tools"); $exe_ndb_mgm= "$glob_basedir/storage/ndb/src/mgmclient/ndb_mgm"; } @@ -887,6 +890,8 @@ sub executable_setup () { $exe_mysql_fix_system_tables= mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables", "$glob_basedir/scripts/mysql_fix_privilege_tables"); + $exe_my_print_defaults= + mtr_script_exists("path_client_bindir/my_print_defaults"); $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/", "$glob_basedir/share/english/"); @@ -2384,6 +2389,7 @@ sub run_mysqltest ($) { $ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables; $ENV{'MYSQL_CLIENT_TEST'}= $cmdline_mysql_client_test; $ENV{'CHARSETSDIR'}= $path_charsetsdir; + $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults; $ENV{'NDB_STATUS_OK'}= $flag_ndb_status_ok; $ENV{'NDB_MGM'}= $exe_ndb_mgm; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index ba9a710390f..4e09f7e2c10 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -575,6 +575,7 @@ if [ x$SOURCE_DIST = x1 ] ; then CLIENT_BINDIR="$BASEDIR/client" MYSQLADMIN="$CLIENT_BINDIR/mysqladmin" WAIT_PID="$BASEDIR/extra/mysql_waitpid" + MYSQL_MY_PRINT_DEFAULTS="$BASEDIR/extra/my_print_defaults" MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc" MYSQL_MANAGER="$BASEDIR/tools/mysqltestmanager" MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen" @@ -635,6 +636,7 @@ else MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog" MYSQLADMIN="$CLIENT_BINDIR/mysqladmin" WAIT_PID="$CLIENT_BINDIR/mysql_waitpid" + MYSQL_MY_PRINT_DEFAULTS="$CLIENT_BINDIR/my_print_defaults" MYSQL_MANAGER="$CLIENT_BINDIR/mysqltestmanager" MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc" MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen" @@ -716,7 +718,7 @@ MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --charact MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" MYSQL="$MYSQL --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD" export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES -export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR +export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR MYSQL_MY_PRINT_DEFAULTS export NDB_TOOLS_DIR export NDB_MGM export NDB_BACKUP_DIR diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index a56902e8ae7..df524b491f1 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -109,3 +109,9 @@ select * from t1 procedure analyse(); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype test.t1.df 1.1 2.2 8 8 0 0 1.650000000 0.302500000 ENUM('1.1','2.2') NOT NULL drop table t1; +create table t1 (d double); +insert into t1 values (100000); +select * from t1 procedure analyse (1,1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.d 100000 100000 6 6 0 0 100000 0 MEDIUMINT(6) UNSIGNED NOT NULL +drop table t1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 48ff82aeeb2..844750e3fed 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1027,3 +1027,15 @@ aa xxx yyy DROP TABLE t1; +set names utf8; +create table t1 (a char(1)) default character set utf8; +create table t2 (a char(1)) default character set utf8; +insert into t1 values('a'),('a'),(0xE38182),(0xE38182); +insert into t1 values('i'),('i'),(0xE38184),(0xE38184); +select * from t1 union distinct select * from t2; +a +a +あ +i +い +drop table t1,t2; diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 17f65d96abc..367b6205550 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -668,3 +668,13 @@ ERROR 42S22: Unknown column 't2.a' in 'field list' insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; ERROR 42S22: Unknown column 't2.b' in 'field list' drop table t1,t2,t3; +create table t1(f1 varchar(5) key); +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +select * from t1; +f1 +2000 +2001 +2002 +drop table t1; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 97d5aad2566..f795bda5553 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1875,6 +1875,8 @@ set @fired:= "No"; end if; end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER DROP TABLE t1, t2; +--port=1234 +--port=1234 DROP TABLE IF EXISTS `test1`; Warnings: Note 1051 Unknown table 'test1' diff --git a/mysql-test/r/rpl_slave_status.result b/mysql-test/r/rpl_slave_status.result index 8badbab85ff..2146132aeb0 100644 --- a/mysql-test/r/rpl_slave_status.result +++ b/mysql-test/r/rpl_slave_status.result @@ -19,7 +19,7 @@ flush privileges; stop slave; start slave; show slave status; -Slave_IO_State Connecting to master +Slave_IO_State # Master_Host 127.0.0.1 Master_User rpl Master_Port MASTER_MYPORT diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 24c89039566..5f2f5f50a16 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2912,3 +2912,13 @@ ERROR 23000: Column 'id' in from clause is ambiguous SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id); ERROR 23000: Column 'id' in from clause is ambiguous drop table t1, t2, t3; +create table t1 (a int(10),b int(10)); +create table t2 (a int(10),b int(10)); +insert into t1 values (1,10),(2,20),(3,30); +insert into t2 values (1,10); +select * from t1 inner join t2 using (A); +a b b +1 10 10 +select * from t1 inner join t2 using (a); +a b b +1 10 10 diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index 2003feee163..4060892c389 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -48,8 +48,6 @@ insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),( select * from t1 procedure analyse(); drop table t1; -# End of 4.1 tests - #decimal-related test create table t1 (df decimal(5,1)); @@ -57,3 +55,15 @@ insert into t1 values(1.1); insert into t1 values(2.2); select * from t1 procedure analyse(); drop table t1; + +# +# Bug#10716 - Procedure Analyse results in wrong values for optimal field type +# + +create table t1 (d double); +insert into t1 values (100000); +select * from t1 procedure analyse (1,1); +drop table t1; + +# End of 4.1 tests + diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 041451272d4..3a89da3a41e 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -863,3 +863,14 @@ SELECT DISTINCT id FROM t1; SELECT DISTINCT id FROM t1 ORDER BY id; DROP TABLE t1; + +# +# Bug#12891: UNION doesn't return DISTINCT result for multi-byte characters +# +set names utf8; +create table t1 (a char(1)) default character set utf8; +create table t2 (a char(1)) default character set utf8; +insert into t1 values('a'),('a'),(0xE38182),(0xE38182); +insert into t1 values('i'),('i'),(0xE38184),(0xE38184); +select * from t1 union distinct select * from t2; +drop table t1,t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 7116a25ff39..dcc43d1dc47 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -202,4 +202,14 @@ insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b; insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; drop table t1,t2,t3; +# +# Bug #12695 Item_func_isnull::update_used_tables() did not update +# const_item_cache +create table t1(f1 varchar(5) key); +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +select * from t1; +drop table t1; + # End of 4.1 tests diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 6ff5ea8451f..c34840b0725 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -762,7 +762,20 @@ show tables; show triggers; DROP TABLE t1, t2; +# +# Bugs #9136, #12917: problems with --defaults-extra-file option +# + +--exec echo "[client]" > $MYSQL_TEST_DIR/var/tmp/tmp.cnf +--exec echo "port=1234" >> $MYSQL_TEST_DIR/var/tmp/tmp.cnf +--exec $MYSQL_MY_PRINT_DEFAULTS -c $MYSQL_TEST_DIR/var/tmp/tmp.cnf client +--exec $MYSQL_MY_PRINT_DEFAULTS -e $MYSQL_TEST_DIR/var/tmp/tmp.cnf client +--exec rm $MYSQL_TEST_DIR/var/tmp/tmp.cnf + +# # Test of fix to BUG 12597 +# + DROP TABLE IF EXISTS `test1`; CREATE TABLE `test1` ( `a1` int(11) default NULL diff --git a/mysql-test/t/rpl_slave_status.test b/mysql-test/t/rpl_slave_status.test index 2c5bd2bffb0..67d3816f443 100644 --- a/mysql-test/t/rpl_slave_status.test +++ b/mysql-test/t/rpl_slave_status.test @@ -23,7 +23,9 @@ connection slave; stop slave; start slave; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 7 # 8 # 9 # 22 # 23 # +# Column 1 is replaced, since the output can be either +# "Connecting to master" or "Waiting for master update" +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # --vertical_results show slave status; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 62687a869b7..c4b50a7556b 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2487,3 +2487,15 @@ SELECT id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id); SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id); drop table t1, t2, t3; + +# +# Bug #13067 JOIN xxx USING is case sensitive +# + +create table t1 (a int(10),b int(10)); +create table t2 (a int(10),b int(10)); +insert into t1 values (1,10),(2,20),(3,30); +insert into t2 values (1,10); +# both queries should produce the same result +select * from t1 inner join t2 using (A); +select * from t1 inner join t2 using (a); diff --git a/mysys/default.c b/mysys/default.c index bde7cbf2563..bca3ec0fed3 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -136,6 +136,9 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, if (! defaults_group_suffix) defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV)); + + if (forced_extra_defaults) + defaults_extra_file= forced_extra_defaults; /* We can only handle 'defaults-group-suffix' if we are called from diff --git a/ndb/test/ndbapi/testSRBank.cpp b/ndb/test/ndbapi/testSRBank.cpp new file mode 100644 index 00000000000..6d57724f4c6 --- /dev/null +++ b/ndb/test/ndbapi/testSRBank.cpp @@ -0,0 +1,246 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include +#include + +#include "bank/Bank.hpp" + +int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){ + Bank bank(ctx->m_cluster_connection); + int overWriteExisting = true; + if (bank.createAndLoadBank(overWriteExisting, 10) != NDBT_OK) + return NDBT_FAILED; + return NDBT_OK; +} + +/** + * + * SR 0 - normal + * SR 1 - shutdown in progress + * SR 2 - restart in progress + */ +int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){ + int wait = 5; // Max seconds between each "day" + int yield = 1; // Loops before bank returns + + ctx->incProperty("ThreadCount"); + while (!ctx->isTestStopped()) + { + Bank bank(ctx->m_cluster_connection); + while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1) + if(bank.performIncreaseTime(wait, yield) == NDBT_FAILED) + break; + + ndbout_c("runBankTimer is stopped"); + ctx->incProperty("ThreadStopped"); + if(ctx->getPropertyWait("SR", (Uint32)0)) + break; + } + return NDBT_OK; +} + +int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){ + int wait = 0; // Max ms between each transaction + int yield = 1; // Loops before bank returns + + ctx->incProperty("ThreadCount"); + while (!ctx->isTestStopped()) + { + Bank bank(ctx->m_cluster_connection); + while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1) + if(bank.performTransactions(0, 1) == NDBT_FAILED) + break; + + ndbout_c("runBankTransactions is stopped"); + ctx->incProperty("ThreadStopped"); + if(ctx->getPropertyWait("SR", (Uint32)0)) + break; + } + return NDBT_OK; +} + +int runBankGL(NDBT_Context* ctx, NDBT_Step* step){ + int yield = 1; // Loops before bank returns + int result = NDBT_OK; + + ctx->incProperty("ThreadCount"); + while (ctx->isTestStopped() == false) + { + Bank bank(ctx->m_cluster_connection); + while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1) + if (bank.performMakeGLs(yield) != NDBT_OK) + { + if(ctx->getProperty("SR") != 0) + break; + ndbout << "bank.performMakeGLs FAILED" << endl; + return NDBT_FAILED; + } + + ndbout_c("runBankGL is stopped"); + ctx->incProperty("ThreadStopped"); + if(ctx->getPropertyWait("SR", (Uint32)0)) + break; + } + return NDBT_OK; +} + +int runBankSum(NDBT_Context* ctx, NDBT_Step* step){ + Bank bank(ctx->m_cluster_connection); + int wait = 2000; // Max ms between each sum of accounts + int yield = 1; // Loops before bank returns + int result = NDBT_OK; + + while (ctx->isTestStopped() == false) { + if (bank.performSumAccounts(wait, yield) != NDBT_OK){ + ndbout << "bank.performSumAccounts FAILED" << endl; + result = NDBT_FAILED; + } + } + return result ; +} + +#define CHECK(b) if (!(b)) { \ + g_err << "ERR: "<< step->getName() \ + << " failed on line " << __LINE__ << endl; \ + result = NDBT_FAILED; \ + continue; } + +int runSR(NDBT_Context* ctx, NDBT_Step* step) +{ + int result = NDBT_OK; + int runtime = ctx->getNumLoops(); + int sleeptime = ctx->getNumRecords(); + NdbRestarter restarter; + bool abort = true; + int timeout = 180; + + Uint32 now; + const Uint32 stop = time(0)+ runtime; + while(!ctx->isTestStopped() && ((now= time(0)) < stop) && result == NDBT_OK) + { + ndbout << " -- Sleep " << sleeptime << "s " << endl; + NdbSleep_SecSleep(sleeptime); + ndbout << " -- Shutting down " << endl; + ctx->setProperty("SR", 1); + CHECK(restarter.restartAll(false, true, abort) == 0); + ctx->setProperty("SR", 2); + CHECK(restarter.waitClusterNoStart(timeout) == 0); + + Uint32 cnt = ctx->getProperty("ThreadCount"); + Uint32 curr= ctx->getProperty("ThreadStopped"); + while(curr != cnt) + { + ndbout_c("%d %d", curr, cnt); + NdbSleep_MilliSleep(100); + curr= ctx->getProperty("ThreadStopped"); + } + + ctx->setProperty("ThreadStopped", (Uint32)0); + CHECK(restarter.startAll() == 0); + CHECK(restarter.waitClusterStarted(timeout) == 0); + + ndbout << " -- Validating starts " << endl; + { + int wait = 0; + int yield = 1; + Bank bank(ctx->m_cluster_connection); + if (bank.performSumAccounts(wait, yield) != 0) + { + ndbout << "bank.performSumAccounts FAILED" << endl; + return NDBT_FAILED; + } + + if (bank.performValidateAllGLs() != 0) + { + ndbout << "bank.performValidateAllGLs FAILED" << endl; + return NDBT_FAILED; + } + } + + ndbout << " -- Validating complete " << endl; + ctx->setProperty("SR", (Uint32)0); + ctx->broadcast(); + } + ctx->stopTest(); + return NDBT_OK; +} + +int runDropBank(NDBT_Context* ctx, NDBT_Step* step){ + Bank bank(ctx->m_cluster_connection); + if (bank.dropBank() != NDBT_OK) + return NDBT_FAILED; + return NDBT_OK; +} + + +NDBT_TESTSUITE(testSRBank); +TESTCASE("Graceful", + " Test that a consistent bank is restored after graceful shutdown\n" + "1. Create bank\n" + "2. Start bank and let it run\n" + "3. Restart ndb and verify consistency\n" + "4. Drop bank\n") +{ + INITIALIZER(runCreateBank); + STEP(runBankTimer); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankGL); + STEP(runSR); +} +TESTCASE("Abort", + " Test that a consistent bank is restored after graceful shutdown\n" + "1. Create bank\n" + "2. Start bank and let it run\n" + "3. Restart ndb and verify consistency\n" + "4. Drop bank\n") +{ + INITIALIZER(runCreateBank); + STEP(runBankTimer); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankTransactions); + STEP(runBankGL); + STEP(runSR); + FINALIZER(runDropBank); +} +NDBT_TESTSUITE_END(testSRBank); + +int main(int argc, const char** argv){ + ndb_init(); + return testSRBank.execute(argc, argv); +} + + diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index d97f0ece94f..a036ccdbf14 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6577,13 +6577,24 @@ void ndb_serialize_cond(const Item *item, void *arg) case Item_func::BETWEEN: { DBUG_PRINT("info", ("BETWEEN, rewriting using AND")); + Item_func_between *between_func= (Item_func_between *) func_item; Ndb_rewrite_context *rewrite_context= new Ndb_rewrite_context(func_item); rewrite_context->next= context->rewrite_stack; context->rewrite_stack= rewrite_context; + if (between_func->negated) + { + DBUG_PRINT("info", ("NOT_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::NOT_FUNC, 1); + prev_cond= curr_cond; + curr_cond= context->cond_ptr= new Ndb_cond(); + curr_cond->prev= prev_cond; + prev_cond->next= curr_cond; + } DBUG_PRINT("info", ("COND_AND_FUNC")); - curr_cond->ndb_item= new Ndb_item(Item_func::COND_AND_FUNC, - func_item->argument_count() - 1); + curr_cond->ndb_item= + new Ndb_item(Item_func::COND_AND_FUNC, + func_item->argument_count() - 1); context->expect_only(Item::FIELD_ITEM); context->expect(Item::INT_ITEM); context->expect(Item::STRING_ITEM); @@ -6594,10 +6605,20 @@ void ndb_serialize_cond(const Item *item, void *arg) case Item_func::IN_FUNC: { DBUG_PRINT("info", ("IN_FUNC, rewriting using OR")); + Item_func_in *in_func= (Item_func_in *) func_item; Ndb_rewrite_context *rewrite_context= new Ndb_rewrite_context(func_item); rewrite_context->next= context->rewrite_stack; context->rewrite_stack= rewrite_context; + if (in_func->negated) + { + DBUG_PRINT("info", ("NOT_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::NOT_FUNC, 1); + prev_cond= curr_cond; + curr_cond= context->cond_ptr= new Ndb_cond(); + curr_cond->prev= prev_cond; + prev_cond->next= curr_cond; + } DBUG_PRINT("info", ("COND_OR_FUNC")); curr_cond->ndb_item= new Ndb_item(Item_func::COND_OR_FUNC, func_item->argument_count() - 1); @@ -6919,6 +6940,7 @@ void ndb_serialize_cond(const Item *item, void *arg) DBUG_PRINT("info", ("End of condition group")); prev_cond= curr_cond; curr_cond= context->cond_ptr= new Ndb_cond(); + curr_cond->prev= prev_cond; prev_cond->next= curr_cond; curr_cond->ndb_item= new Ndb_item(NDB_END_COND); // Pop rewrite stack diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 6706cee8e9d..86a94cdf997 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -880,18 +880,23 @@ void field_real::get_opt_type(String *answer, if (!max_notzero_dec_len) { if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127)) - sprintf(buff, "TINYINT(%d)", (int) max_length - (item->decimals + 1)); + sprintf(buff, "TINYINT(%d)", (int) max_length - + ((item->decimals == NOT_FIXED_DEC) ? 0 : (item->decimals + 1))); else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ? UINT_MAX16 : INT_MAX16)) - sprintf(buff, "SMALLINT(%d)", (int) max_length - (item->decimals + 1)); + sprintf(buff, "SMALLINT(%d)", (int) max_length - + ((item->decimals == NOT_FIXED_DEC) ? 0 : (item->decimals + 1))); else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ? UINT_MAX24 : INT_MAX24)) - sprintf(buff, "MEDIUMINT(%d)", (int) max_length - (item->decimals + 1)); + sprintf(buff, "MEDIUMINT(%d)", (int) max_length - + ((item->decimals == NOT_FIXED_DEC) ? 0 : (item->decimals + 1))); else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ? UINT_MAX32 : INT_MAX32)) - sprintf(buff, "INT(%d)", (int) max_length - (item->decimals + 1)); + sprintf(buff, "INT(%d)", (int) max_length - + ((item->decimals == NOT_FIXED_DEC) ? 0 : (item->decimals + 1))); else - sprintf(buff, "BIGINT(%d)", (int) max_length - (item->decimals + 1)); + sprintf(buff, "BIGINT(%d)", (int) max_length - + ((item->decimals == NOT_FIXED_DEC) ? 0 : (item->decimals + 1))); answer->append(buff, (uint) strlen(buff)); if (min_arg >= 0) answer->append(" UNSIGNED"); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f578876bc5e..105cd6a6670 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3455,7 +3455,7 @@ test_if_string_in_list(const char *find, List *str_list) { if (find_length != curr_str->length()) continue; - if (!strncmp(find, curr_str->ptr(), find_length)) + if (!my_strcasecmp(system_charset_info, find, curr_str->ptr())) return TRUE; } return FALSE; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c2616ff3ef3..378be129444 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3520,7 +3520,6 @@ end_with_restore_list: !rpl_filter->db_ok_with_wild_table(lex->name))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); - reset_one_shot_variables(thd); break; } #endif @@ -3555,7 +3554,6 @@ end_with_restore_list: !rpl_filter->db_ok_with_wild_table(lex->name))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); - reset_one_shot_variables(thd); break; } #endif @@ -3596,7 +3594,6 @@ end_with_restore_list: !rpl_filter->db_ok_with_wild_table(lex->name))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); - reset_one_shot_variables(thd); break; } #endif diff --git a/storage/heap/hp_hash.c b/storage/heap/hp_hash.c index d643f776731..77f3cf6d80b 100644 --- a/storage/heap/hp_hash.c +++ b/storage/heap/hp_hash.c @@ -551,11 +551,13 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2, } if (cs->mbmaxlen > 1) { + uint safe_length1= char_length1; + uint safe_length2= char_length2; uint char_length= seg->length / cs->mbmaxlen; - char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length1); - set_if_smaller(char_length1, seg->length); - char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length2); - set_if_smaller(char_length2, seg->length); + char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length); + set_if_smaller(char_length1, safe_length1); + char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length); + set_if_smaller(char_length2, safe_length2); } if (cs->coll->strnncollsp(seg->charset, diff --git a/storage/ndb/include/util/Parser.hpp b/storage/ndb/include/util/Parser.hpp index c117498e1ba..3baf7601a6c 100644 --- a/storage/ndb/include/util/Parser.hpp +++ b/storage/ndb/include/util/Parser.hpp @@ -285,7 +285,7 @@ template inline void Parser::setBreakOnInvalidArg(bool v){ - impl->m_breakOnInvalidArg; + impl->m_breakOnInvalidArg = v; } #endif diff --git a/storage/ndb/src/common/portlib/NdbThread.c b/storage/ndb/src/common/portlib/NdbThread.c index 0914eede7de..d501ea2559a 100644 --- a/storage/ndb/src/common/portlib/NdbThread.c +++ b/storage/ndb/src/common/portlib/NdbThread.c @@ -66,6 +66,16 @@ ndb_thread_wrapper(void* _ss){ #ifdef NDB_SHM_TRANSPORTER NdbThread_set_shm_sigmask(TRUE); #endif + { + /** + * Block all signals to thread by default + * let them go to main process instead + */ + sigset_t mask; + sigfillset(&mask); + pthread_sigmask(SIG_BLOCK, &mask, 0); + } + { void *ret; struct NdbThread * ss = (struct NdbThread *)_ss; diff --git a/storage/ndb/src/mgmapi/mgmapi.cpp b/storage/ndb/src/mgmapi/mgmapi.cpp index c10eb073855..8263e8cbc93 100644 --- a/storage/ndb/src/mgmapi/mgmapi.cpp +++ b/storage/ndb/src/mgmapi/mgmapi.cpp @@ -678,12 +678,10 @@ ndb_mgm_get_status(NdbMgmHandle handle) Vector split; tmp.split(split, ":"); if(split.size() != 2){ - abort(); return NULL; } if(!(split[0].trim() == "nodes")){ - abort(); return NULL; } @@ -731,7 +729,6 @@ ndb_mgm_get_status(NdbMgmHandle handle) if(i+1 != noOfNodes){ free(state); - abort(); return NULL; } diff --git a/storage/ndb/test/include/NDBT_Test.hpp b/storage/ndb/test/include/NDBT_Test.hpp index 1b9c2751f64..027ac356e0c 100644 --- a/storage/ndb/test/include/NDBT_Test.hpp +++ b/storage/ndb/test/include/NDBT_Test.hpp @@ -67,7 +67,8 @@ public: const char* getPropertyWait(const char*, const char* ); void decProperty(const char *); - + void incProperty(const char *); + // Communicate with other tests void stopTest(); bool isTestStopped(); diff --git a/storage/ndb/test/ndbapi/Makefile.am b/storage/ndb/test/ndbapi/Makefile.am index f096a7c74e9..bf993d30111 100644 --- a/storage/ndb/test/ndbapi/Makefile.am +++ b/storage/ndb/test/ndbapi/Makefile.am @@ -34,7 +34,8 @@ test_event ndbapi_slow_select testReadPerf testLcp \ testPartitioning \ testBitfield \ DbCreate DbAsyncGenerator \ -test_event_multi_table +test_event_multi_table \ +testSRBank #flexTimedAsynch #testBlobs @@ -78,6 +79,7 @@ testBitfield_SOURCES = testBitfield.cpp DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp DbAsyncGenerator_SOURCES = bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp test_event_multi_table_SOURCES = test_event_multi_table.cpp +testSRBank_SOURCES = testSRBank.cpp INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/include/kernel @@ -89,6 +91,7 @@ include $(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am ##testSystemRestart_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel ##testTransactions_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel testBackup_LDADD = $(LDADD) bank/libbank.a +testSRBank_LDADD = bank/libbank.a $(LDADD) # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/storage/ndb/test/ndbapi/bank/Bank.cpp b/storage/ndb/test/ndbapi/bank/Bank.cpp index 40819ecc849..37224fdd055 100644 --- a/storage/ndb/test/ndbapi/bank/Bank.cpp +++ b/storage/ndb/test/ndbapi/bank/Bank.cpp @@ -19,12 +19,13 @@ #include #include -Bank::Bank(Ndb_cluster_connection& con): +Bank::Bank(Ndb_cluster_connection& con, bool _init): m_ndb(&con, "BANK"), m_maxAccount(-1), m_initialized(false) { - + if(_init) + init(); } int Bank::init(){ @@ -34,40 +35,39 @@ int Bank::init(){ myRandom48Init(NdbTick_CurrentMillisecond()); m_ndb.init(); - while (m_ndb.waitUntilReady(10) != 0) - ndbout << "Waiting for ndb to be ready" << endl; - + if (m_ndb.waitUntilReady(30) != 0) + { + ndbout << "Ndb not ready" << endl; + return NDBT_FAILED; + } + if (getNumAccounts() != NDBT_OK) return NDBT_FAILED; + + m_initialized = true; return NDBT_OK; } int Bank::performTransactions(int maxSleepBetweenTrans, int yield){ - if (init() != NDBT_OK) - return NDBT_FAILED; int transactions = 0; - while(1){ - - while(m_ndb.waitUntilReady(10) != 0) - ndbout << "Waiting for ndb to be ready" << endl; - - while(performTransaction() != NDBT_FAILED){ - transactions++; - - if (maxSleepBetweenTrans > 0){ - int val = myRandom48(maxSleepBetweenTrans); - NdbSleep_MilliSleep(val); - } - - if((transactions % 100) == 0) - g_info << transactions << endl; - - if (yield != 0 && transactions >= yield) - return NDBT_OK; + while(performTransaction() == NDBT_OK) + { + transactions++; + + if (maxSleepBetweenTrans > 0){ + int val = myRandom48(maxSleepBetweenTrans); + NdbSleep_MilliSleep(val); } + + if((transactions % 100) == 0) + g_info << transactions << endl; + + if (yield != 0 && transactions >= yield) + return NDBT_OK; } + return NDBT_FAILED; } @@ -92,7 +92,7 @@ int Bank::performTransaction(){ int amount = myRandom48(maxAmount); - retry_transaction: +retry_transaction: int res = performTransaction(fromAccount, toAccount, amount); if (res != 0){ switch (res){ @@ -158,8 +158,9 @@ int Bank::performTransactionImpl1(int fromAccountId, // Ok, all clear to do the transaction Uint64 transId; - if (getNextTransactionId(transId) != NDBT_OK){ - return NDBT_FAILED; + int result = NDBT_OK; + if ((result= getNextTransactionId(transId)) != NDBT_OK){ + return result; } NdbConnection* pTrans = m_ndb.startTransaction(); @@ -500,8 +501,6 @@ int Bank::performTransactionImpl1(int fromAccountId, int Bank::performMakeGLs(int yield){ int result; - if (init() != NDBT_OK) - return NDBT_FAILED; int counter, maxCounter; int yieldCounter = 0; @@ -512,9 +511,6 @@ int Bank::performMakeGLs(int yield){ counter = 0; maxCounter = 50 + myRandom48(100); - while(m_ndb.waitUntilReady(10) != 0) - ndbout << "Waiting for ndb to be ready" << endl; - /** * Validate GLs and Transactions for previous days * @@ -526,6 +522,7 @@ int Bank::performMakeGLs(int yield){ return NDBT_FAILED; } g_info << "performValidateGLs failed" << endl; + return NDBT_FAILED; continue; } @@ -536,7 +533,7 @@ int Bank::performMakeGLs(int yield){ return NDBT_FAILED; } g_info << "performValidatePurged failed" << endl; - continue; + return NDBT_FAILED; } while (1){ @@ -607,14 +604,9 @@ int Bank::performMakeGLs(int yield){ int Bank::performValidateAllGLs(){ int result; - if (init() != NDBT_OK) - return NDBT_FAILED; while (1){ - while(m_ndb.waitUntilReady(10) != 0) - ndbout << "Waiting for ndb to be ready" << endl; - /** * Validate GLs and Transactions for previous days * Set age so that ALL GL's are validated @@ -1930,39 +1922,29 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, } - int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield){ - if (init() != NDBT_OK) - return NDBT_FAILED; - +int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield) +{ int yieldCounter = 0; - - while(1){ - - while(m_ndb.waitUntilReady(10) != 0) - ndbout << "Waiting for ndb to be ready" << endl; - - while(1){ - - Uint64 currTime; - if (incCurrTime(currTime) != NDBT_OK) - break; - - g_info << "Current time is " << currTime << endl; - if (maxSleepBetweenDays > 0){ - int val = myRandom48(maxSleepBetweenDays); - NdbSleep_SecSleep(val); - } - - yieldCounter++; - if (yield != 0 && yieldCounter >= yield) - return NDBT_OK; - - } - } - return NDBT_FAILED; - } - - + + while(1){ + + Uint64 currTime; + if (incCurrTime(currTime) != NDBT_OK) + break; + + g_info << "Current time is " << currTime << endl; + if (maxSleepBetweenDays > 0){ + int val = myRandom48(maxSleepBetweenDays); + NdbSleep_SecSleep(val); + } + + yieldCounter++; + if (yield != 0 && yieldCounter >= yield) + return NDBT_OK; + + } + return NDBT_FAILED; +} int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){ @@ -1971,22 +1953,30 @@ int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){ NdbConnection* pTrans = m_ndb.startTransaction(); if (pTrans == NULL){ ERR(m_ndb.getNdbError()); + if(m_ndb.getNdbError().status == NdbError::TemporaryError) + return NDBT_TEMPORARY; return NDBT_FAILED; } - if (prepareReadSystemValueOp(pTrans, sysValId, value) != NDBT_OK) { + int result; + if ((result= prepareReadSystemValueOp(pTrans, sysValId, value)) != NDBT_OK) { ERR(pTrans->getNdbError()); m_ndb.closeTransaction(pTrans); - return NDBT_FAILED; + return result; } check = pTrans->execute(Commit); if( check == -1 ) { ERR(pTrans->getNdbError()); + if(pTrans->getNdbError().status == NdbError::TemporaryError) + { + m_ndb.closeTransaction(pTrans); + return NDBT_TEMPORARY; + } m_ndb.closeTransaction(pTrans); return NDBT_FAILED; } - + m_ndb.closeTransaction(pTrans); return NDBT_OK; @@ -2092,6 +2082,8 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){ NdbConnection* pTrans = m_ndb.startTransaction(); if (pTrans == NULL){ ERR(m_ndb.getNdbError()); + if (m_ndb.getNdbError().status == NdbError::TemporaryError) + DBUG_RETURN(NDBT_TEMPORARY); DBUG_RETURN(NDBT_FAILED); } @@ -2127,6 +2119,11 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){ check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); + if (pTrans->getNdbError().status == NdbError::TemporaryError) + { + m_ndb.closeTransaction(pTrans); + DBUG_RETURN(NDBT_TEMPORARY); + } m_ndb.closeTransaction(pTrans); DBUG_RETURN(NDBT_FAILED); } @@ -2201,16 +2198,21 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){ check = pTrans->execute(Commit); if( check == -1 ) { ERR(pTrans->getNdbError()); + if (pTrans->getNdbError().status == NdbError::TemporaryError) + { + m_ndb.closeTransaction(pTrans); + DBUG_RETURN(NDBT_TEMPORARY); + } m_ndb.closeTransaction(pTrans); DBUG_RETURN(NDBT_FAILED); } // Check that value updated equals the value we read after the update if (valueNewRec->u_64_value() != value){ - + printf("value actual=%lld\n", valueNewRec->u_64_value()); printf("value expected=%lld actual=%lld\n", value, valueNewRec->u_64_value()); - + DBUG_PRINT("info", ("value expected=%ld actual=%ld", value, valueNewRec->u_64_value())); g_err << "getNextTransactionId: value was not updated" << endl; m_ndb.closeTransaction(pTrans); @@ -2218,7 +2220,7 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){ } m_ndb.closeTransaction(pTrans); - + DBUG_RETURN(0); } @@ -2235,6 +2237,8 @@ int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){ NdbConnection* pTrans = m_ndb.startTransaction(); if (pTrans == NULL){ ERR(m_ndb.getNdbError()); + if(m_ndb.getNdbError().status == NdbError::TemporaryError) + return NDBT_TEMPORARY; return NDBT_FAILED; } @@ -2277,6 +2281,11 @@ int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){ check = pTrans->execute(Commit); if( check == -1 ) { ERR(pTrans->getNdbError()); + if(pTrans->getNdbError().status == NdbError::TemporaryError) + { + m_ndb.closeTransaction(pTrans); + return NDBT_TEMPORARY; + } m_ndb.closeTransaction(pTrans); return NDBT_FAILED; } @@ -2301,16 +2310,11 @@ int Bank::prepareGetCurrTimeOp(NdbConnection *pTrans, Uint64 &time){ int Bank::performSumAccounts(int maxSleepBetweenSums, int yield){ - if (init() != NDBT_OK) - return NDBT_FAILED; int yieldCounter = 0; while (1){ - while (m_ndb.waitUntilReady(10) != 0) - ndbout << "Waiting for ndb to be ready" << endl; - Uint32 sumAccounts = 0; Uint32 numAccounts = 0; if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){ diff --git a/storage/ndb/test/ndbapi/bank/Bank.hpp b/storage/ndb/test/ndbapi/bank/Bank.hpp index d9dd7b25944..b80f02dae97 100644 --- a/storage/ndb/test/ndbapi/bank/Bank.hpp +++ b/storage/ndb/test/ndbapi/bank/Bank.hpp @@ -27,7 +27,7 @@ class Bank { public: - Bank(Ndb_cluster_connection&); + Bank(Ndb_cluster_connection&, bool init = true); int createAndLoadBank(bool overWrite, int num_accounts=10); int dropBank(); diff --git a/storage/ndb/test/src/NDBT_Test.cpp b/storage/ndb/test/src/NDBT_Test.cpp index 7fd92db533e..8fecf56531f 100644 --- a/storage/ndb/test/src/NDBT_Test.cpp +++ b/storage/ndb/test/src/NDBT_Test.cpp @@ -148,6 +148,15 @@ NDBT_Context::decProperty(const char * name){ NdbCondition_Broadcast(propertyCondPtr); NdbMutex_Unlock(propertyMutexPtr); } +void +NDBT_Context::incProperty(const char * name){ + NdbMutex_Lock(propertyMutexPtr); + Uint32 val = 0; + props.get(name, &val); + props.put(name, (val + 1), true); + NdbCondition_Broadcast(propertyCondPtr); + NdbMutex_Unlock(propertyMutexPtr); +} void NDBT_Context::setProperty(const char* _name, const char* _val){ NdbMutex_Lock(propertyMutexPtr);