From bcc517cb3751296d131ed27fa776a0f0ba87eb6f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Aug 2007 14:32:39 +0800 Subject: [PATCH 1/8] BUG#30271 NDB_LE_MemoryUsage.page_size_kb actually returns page size in bytes, not kilobyte ndb/include/mgmapi/ndb_logevent.h: Add page_size_bytes member variable for MemoryUsage. And don't remove page_size_kb member variable at present for the compatibility backward. ndb/src/mgmapi/ndb_logevent.cpp: change the page_size_kb member variable of MemoryUsage to page_size_bytes --- ndb/include/mgmapi/ndb_logevent.h | 8 +++++++- ndb/src/mgmapi/ndb_logevent.cpp | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ndb/include/mgmapi/ndb_logevent.h b/ndb/include/mgmapi/ndb_logevent.h index 76e4c31baa2..389004da06b 100644 --- a/ndb/include/mgmapi/ndb_logevent.h +++ b/ndb/include/mgmapi/ndb_logevent.h @@ -551,7 +551,13 @@ extern "C" { /** Log event specific data for for corresponding NDB_LE_ log event */ struct { int gth; - unsigned page_size_kb; + /* union is for compatibility backward. + * page_size_kb member variable should be removed in the future + */ + union { + unsigned page_size_kb; + unsigned page_size_bytes; + }; unsigned pages_used; unsigned pages_total; unsigned block; diff --git a/ndb/src/mgmapi/ndb_logevent.cpp b/ndb/src/mgmapi/ndb_logevent.cpp index 3885bb79536..f0b7c26cf78 100644 --- a/ndb/src/mgmapi/ndb_logevent.cpp +++ b/ndb/src/mgmapi/ndb_logevent.cpp @@ -256,7 +256,7 @@ struct Ndb_logevent_body_row ndb_logevent_body[]= { ROW( ReceiveBytesStatistic, "mean_received_bytes", 2, mean_received_bytes), ROW( MemoryUsage, "gth", 1, gth), - ROW( MemoryUsage, "page_size_kb", 2, page_size_kb), + ROW( MemoryUsage, "page_size_bytes", 2, page_size_bytes), ROW( MemoryUsage, "pages_used", 3, pages_used), ROW( MemoryUsage, "pages_total", 4, pages_total), ROW( MemoryUsage, "block", 5, block), From bafa5fe8aa6a79ab5f28a9275d71647049709863 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Sep 2007 09:16:41 +0800 Subject: [PATCH 2/8] BUG#29851 TRUNCATE causes error 4350 from cluster in INSERT... ON DUPLICATE KEY UPDATE mysql-test/r/ndb_alter_table2.result: Add test case for BUG#29851 mysql-test/t/ndb_alter_table2.test: Add test case for BUG#29851 sql/ha_ndbcluster.cc: Indexes are dropped also when dropping table in GlobalDictCache --- mysql-test/r/ndb_alter_table2.result | 19 +++++++++++++++++ mysql-test/t/ndb_alter_table2.test | 31 ++++++++++++++++++++++++++++ sql/ha_ndbcluster.cc | 10 ++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ndb_alter_table2.result b/mysql-test/r/ndb_alter_table2.result index 399578dc97b..886c300d53d 100644 --- a/mysql-test/r/ndb_alter_table2.result +++ b/mysql-test/r/ndb_alter_table2.result @@ -40,3 +40,22 @@ a b c select * from t1; a b c drop table t1; +DROP TABLE IF EXISTS truncate_test; +CREATE TABLE truncate_test ( +i INT PRIMARY KEY, +a INT, +b VARCHAR(11), +UNIQUE KEY (a) +) ENGINE = NDB; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +TRUNCATE truncate_test; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; +i a b +1 1 test +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; +i a b +1 1 new +DROP TABLE truncate_test; diff --git a/mysql-test/t/ndb_alter_table2.test b/mysql-test/t/ndb_alter_table2.test index 3861fcc6c9d..99c201f7370 100644 --- a/mysql-test/t/ndb_alter_table2.test +++ b/mysql-test/t/ndb_alter_table2.test @@ -81,3 +81,34 @@ select * from t1; select * from t1; drop table t1; + +#For BUG#29851 TRUNCATE causes error 4350 from cluster in INSERT... ON DUPLICATE KEY UPDATE + +connection con1; + +--disable_warnings +DROP TABLE IF EXISTS truncate_test; +--enable_warnings + +CREATE TABLE truncate_test ( + i INT PRIMARY KEY, + a INT, + b VARCHAR(11), + UNIQUE KEY (a) +) ENGINE = NDB; + +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; + +connection con2; +TRUNCATE truncate_test; + +connection con1; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; + +connection con2; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; + +DROP TABLE truncate_test; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 03b6bcf3242..76857900ea2 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -439,7 +439,8 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) void ha_ndbcluster::invalidate_dictionary_cache(bool global) { - NDBDICT *dict= get_ndb()->getDictionary(); + Ndb * ndb= get_ndb(); + NDBDICT *dict= ndb->getDictionary(); DBUG_ENTER("invalidate_dictionary_cache"); DBUG_PRINT("info", ("invalidating %s", m_tabname)); @@ -459,6 +460,7 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global) } else dict->removeCachedTable(m_tabname); + build_index_list(ndb, table, ILBP_OPEN); table->s->version=0L; /* Free when thread is ready */ /* Invalidate indexes */ for (uint i= 0; i < table->s->keys; i++) @@ -470,17 +472,23 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global) switch (idx_type) { case PRIMARY_KEY_ORDERED_INDEX: case ORDERED_INDEX: + if (!index) + break; if (global) dict->invalidateIndex(index->getName(), m_tabname); else dict->removeCachedIndex(index->getName(), m_tabname); break; case UNIQUE_ORDERED_INDEX: + if (!index) + break; if (global) dict->invalidateIndex(index->getName(), m_tabname); else dict->removeCachedIndex(index->getName(), m_tabname); case UNIQUE_INDEX: + if (!unique_index) + break; if (global) dict->invalidateIndex(unique_index->getName(), m_tabname); else From 3a3e2c796c9a3555b445b940de5670ca683fee2f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Sep 2007 09:49:16 +0800 Subject: [PATCH 3/8] BUG#28298 Node Id larger than MAX_NDB_NODES in config file doesn't generate error ndb/include/kernel/ndb_limits.h: 1) define a macro MAX_DATA_NODE_ID to set the max ID of data nodes to be MAX_NDB_NODES - 1 2) define a macro MAX_NODES_ID to set the max ID of API and MGM to be MAX_NODES -1 ndb/src/mgmsrv/ConfigInfo.cpp: 1) replace MAX_NODES with MAX_DATA_NODE_ID (= MAX_NDB_NODES - 1) when the NodeId represents data nodes. 2) replace MAX_NODES with MAX_NODES_ID (= MAX_NODES -1) when the NodeId represents API or MGM nodes. --- ndb/include/kernel/ndb_limits.h | 11 +++++++++++ ndb/src/mgmsrv/ConfigInfo.cpp | 12 ++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h index c82288c762a..82fd0bd5d51 100644 --- a/ndb/include/kernel/ndb_limits.h +++ b/ndb/include/kernel/ndb_limits.h @@ -27,6 +27,17 @@ #define MAX_NDB_NODES 49 #define MAX_NODES 64 +/************************************************************************** + * IT SHOULD BE (MAX_NDB_NODES - 1). + * WHEN MAX_NDB_NODE IS CHANGED, IT SHOULD BE CHANGED ALSO + **************************************************************************/ +#define MAX_DATA_NODE_ID 48 +/************************************************************************** + * IT SHOULD BE (MAX_NODES - 1). + * WHEN MAX_NODES IS CHANGED, IT SHOULD BE CHANGED ALSO + **************************************************************************/ +#define MAX_NODES_ID 63 + /** * MAX_API_NODES = MAX_NODES - No of NDB Nodes in use */ diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp index 0cf37b5f874..657dccb0d98 100644 --- a/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/ndb/src/mgmsrv/ConfigInfo.cpp @@ -398,7 +398,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_DATA_NODE_ID) }, { CFG_NODE_ID, @@ -410,7 +410,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_DATA_NODE_ID) }, { KEY_INTERNAL, @@ -1261,7 +1261,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { CFG_NODE_ID, @@ -1273,7 +1273,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { KEY_INTERNAL, @@ -1404,7 +1404,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { CFG_NODE_ID, @@ -1416,7 +1416,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { CFG_LOG_DESTINATION, From 6c4500517dc32805efcef75e478eb1c0f7e34284 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Dec 2007 13:43:48 +0100 Subject: [PATCH 4/8] Bug #33237 NDB_MGM 'eat' 99% cpu utilization --- mysql-test/r/bdb_notembedded.result | 35 ---------------------- mysql-test/t/bdb_notembedded.test | 38 ------------------------ ndb/src/mgmclient/CommandInterpreter.cpp | 17 +++++++---- 3 files changed, 11 insertions(+), 79 deletions(-) delete mode 100644 mysql-test/r/bdb_notembedded.result delete mode 100644 mysql-test/t/bdb_notembedded.test diff --git a/mysql-test/r/bdb_notembedded.result b/mysql-test/r/bdb_notembedded.result deleted file mode 100644 index 14cb5fad915..00000000000 --- a/mysql-test/r/bdb_notembedded.result +++ /dev/null @@ -1,35 +0,0 @@ -set autocommit=1; -reset master; -create table bug16206 (a int); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; -show binlog events; -Log_name Pos Event_type Server_id End_log_pos Info -f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 -f n Query 1 n use `test`; create table bug16206 (a int) -f n Query 1 n use `test`; insert into bug16206 values(1) -f n Query 1 n use `test`; insert into bug16206 values(2) -drop table bug16206; -reset master; -create table bug16206 (a int) engine= bdb; -insert into bug16206 values(0); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; -insert into bug16206 values(3); -show binlog events; -Log_name Pos Event_type Server_id End_log_pos Info -f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 -f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb -f n Query 1 n use `test`; insert into bug16206 values(0) -f n Query 1 n use `test`; insert into bug16206 values(1) -f n Query 1 n use `test`; BEGIN -f n Query 1 n use `test`; insert into bug16206 values(2) -f n Query 1 n use `test`; COMMIT -f n Query 1 n use `test`; insert into bug16206 values(3) -drop table bug16206; -set autocommit=0; -End of 5.0 tests diff --git a/mysql-test/t/bdb_notembedded.test b/mysql-test/t/bdb_notembedded.test deleted file mode 100644 index 24e64ebbfb2..00000000000 --- a/mysql-test/t/bdb_notembedded.test +++ /dev/null @@ -1,38 +0,0 @@ --- source include/not_embedded.inc --- source include/have_bdb.inc - -# -# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode -# -set autocommit=1; - -let $VERSION=`select version()`; - -reset master; -create table bug16206 (a int); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; ---replace_result $VERSION VERSION ---replace_column 1 f 2 n 5 n -show binlog events; -drop table bug16206; - -reset master; -create table bug16206 (a int) engine= bdb; -insert into bug16206 values(0); -insert into bug16206 values(1); -start transaction; -insert into bug16206 values(2); -commit; -insert into bug16206 values(3); ---replace_result $VERSION VERSION ---replace_column 1 f 2 n 5 n -show binlog events; -drop table bug16206; - -set autocommit=0; - - ---echo End of 5.0 tests diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 1036461d404..b72f7b12f9b 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -921,10 +921,14 @@ event_thread_run(void* p) { do_event_thread= 1; do { - if (ndb_logevent_get_next(log_handle, &log_event, 2000) <= 0) - continue; - Guard g(printmutex); - printLogEvent(&log_event); + int res= ndb_logevent_get_next(log_handle, &log_event, 2000); + if (res > 0) + { + Guard g(printmutex); + printLogEvent(&log_event); + } + else if (res < 0) + break; } while(do_event_thread); ndb_mgm_destroy_logevent_handle(&log_handle); } @@ -2722,8 +2726,9 @@ CommandInterpreter::executeStartBackup(char* parameters, bool interactive) { int count = 0; int retry = 0; + int res; do { - if (ndb_logevent_get_next(log_handle, &log_event, 60000) > 0) + if ((res= ndb_logevent_get_next(log_handle, &log_event, 60000)) > 0) { int print = 0; switch (log_event.type) { @@ -2753,7 +2758,7 @@ CommandInterpreter::executeStartBackup(char* parameters, bool interactive) { retry++; } - } while(count < 2 && retry < 3); + } while(res >= 0 && count < 2 && retry < 3); if (retry >= 3) ndbout << "get backup event failed for " << retry << " times" << endl; From 9b14ac8d0199e0f53fa857e85af78a7b1d715e36 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Jan 2008 14:51:08 +0800 Subject: [PATCH 5/8] Fix for view.test. the result should be added by 1 by the year(now()) function. mysql-test/r/view.result: SELECT (year(now())-year(DOB)) AS Age FROM t1 HAVING Age < 75; the above statement in test file has a year(now()) function, the result should increase by 1 from 2007 year to 2008 year. --- mysql-test/r/view.result | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 8d9d802949d..1a1a5f68c6c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2698,12 +2698,12 @@ View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (year(now()) - year(`t1`.`DOB`)) AS `Age` from `t1` having (`Age` < 75) SELECT (year(now())-year(DOB)) AS Age FROM t1 HAVING Age < 75; Age -43 -39 +44 +40 SELECT * FROM v1; Age -43 -39 +44 +40 DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a char(6) DEFAULT 'xxx'); From a79ebb850311886e8d50bb39a14efccc36e88974 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Jan 2008 09:59:06 +0100 Subject: [PATCH 6/8] ndb - bug#33750 make sure that getField does not write after supplied buffer (recommit to correct clone, for easy merging) ndb/include/util/Bitmask.hpp: ndb- bug#33750 make sure that getField does not write after supplied buffer ndb/src/common/util/Bitmask.cpp: ndb- bug#33750 make sure that getField does not write after supplied buffer ndb/test/ndbapi/testBitfield.cpp: move test from Bitmask.cpp into testBitfield for automatic testing --- ndb/include/util/Bitmask.hpp | 10 +- ndb/src/common/util/Bitmask.cpp | 353 ++++----------------------- ndb/test/ndbapi/testBitfield.cpp | 407 ++++++++++++++++++++++++++++++- 3 files changed, 464 insertions(+), 306 deletions(-) diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp index 3b3fe721cca..0383841a666 100644 --- a/ndb/include/util/Bitmask.hpp +++ b/ndb/include/util/Bitmask.hpp @@ -126,6 +126,7 @@ public: /** * setField - Set bitfield at given position and length (max 32 bits) + * Note : length == 0 not supported. */ static void setField(unsigned size, Uint32 data[], unsigned pos, unsigned len, Uint32 val); @@ -133,6 +134,7 @@ public: /** * getField - Get bitfield at given position and length + * Note : length == 0 not supported. */ static void getField(unsigned size, const Uint32 data[], unsigned pos, unsigned len, Uint32 dst[]); @@ -814,7 +816,10 @@ BitmaskImpl::getField(unsigned size, const Uint32 src[], unsigned pos, unsigned len, Uint32 dst[]) { assert(pos + len <= (size << 5)); - + assert (len != 0); + if (len == 0) + return; + src += (pos >> 5); Uint32 offset = pos & 31; * dst = (* src >> offset) & (len >= 32 ? ~0 : (1 << len) - 1); @@ -833,6 +838,9 @@ BitmaskImpl::setField(unsigned size, Uint32 dst[], unsigned pos, unsigned len, const Uint32 src[]) { assert(pos + len <= (size << 5)); + assert(len != 0); + if (len == 0) + return; dst += (pos >> 5); Uint32 offset = pos & 31; diff --git a/ndb/src/common/util/Bitmask.cpp b/ndb/src/common/util/Bitmask.cpp index f5b822ff08e..22919fe585a 100644 --- a/ndb/src/common/util/Bitmask.cpp +++ b/ndb/src/common/util/Bitmask.cpp @@ -16,49 +16,63 @@ #include #include -static -void print(const Uint32 src[], Uint32 len, Uint32 pos = 0) -{ - printf("b'"); - for(unsigned i = 0; i> 5, src, i+pos)) - printf("1"); - else - printf("0"); - if((i & 31) == 31) - printf(" "); - } -} - -#ifndef __TEST_BITMASK__ - void BitmaskImpl::getFieldImpl(const Uint32 src[], unsigned shiftL, unsigned len, Uint32 dst[]) { + /* Copy whole words of src to dst, shifting src left + * by shiftL. Undefined bits of the last written dst word + * should be zeroed. + */ assert(shiftL < 32); unsigned shiftR = 32 - shiftL; unsigned undefined = shiftL ? ~0 : 0; + /* Merge first word with previously set bits if there's a shift */ * dst = shiftL ? * dst : 0; - - while(len >= 32) + + /* Treat the zero-shift case separately to avoid + * trampling or reading past the end of src + */ + if (shiftL == 0) { - * dst++ |= (* src) << shiftL; - * dst = ((* src++) >> shiftR) & undefined; - len -= 32; + while(len >= 32) + { + * dst++ = * src++; + len -=32; + } + + if (len != 0) + { + /* Last word has some bits set */ + Uint32 mask= ((1 << len) -1); // 0000111 + * dst = (* src) & mask; + } } - - if(len < shiftR) + else // shiftL !=0, need to build each word from two words shifted { - * dst |= ((* src) & ((1 << len) - 1)) << shiftL; - } - else - { - * dst++ |= ((* src) << shiftL); - * dst = ((* src) >> shiftR) & ((1 << (len - shiftR)) - 1) & undefined; + while(len >= 32) + { + * dst++ |= (* src) << shiftL; + * dst = ((* src++) >> shiftR) & undefined; + len -= 32; + } + + /* Have space for shiftR more bits in the current dst word + * is that enough? + */ + if(len <= shiftR) + { + /* Fit the remaining bits in the current dst word */ + * dst |= ((* src) & ((1 << len) - 1)) << shiftL; + } + else + { + /* Need to write to two dst words */ + * dst++ |= ((* src) << shiftL); + * dst = ((* src) >> shiftR) & ((1 << (len - shiftR)) - 1) & undefined; + } } } @@ -81,286 +95,23 @@ BitmaskImpl::setFieldImpl(Uint32 dst[], len -= 32; } + /* Copy last bits */ Uint32 mask = ((1 << len) -1); * dst = (* dst & ~mask); - if(len < shiftR) + if(len <= shiftR) { + /* Remaining bits fit in current word */ * dst |= ((* src++) >> shiftL) & mask; } else { + /* Remaining bits update 2 words */ * dst |= ((* src++) >> shiftL); * dst |= ((* src) & ((1 << (len - shiftR)) - 1)) << shiftR ; } } -#else -#define DEBUG 0 -#include -static void do_test(int bitmask_size); - -int -main(int argc, char** argv) -{ - int loops = argc > 1 ? atoi(argv[1]) : 1000; - int max_size = argc > 2 ? atoi(argv[2]) : 1000; - - - for(int i = 0; i data; -}; - -static void require(bool b) -{ - if(!b) abort(); -} - -static -bool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len) -{ - Uint32 sz32 = (len + 31) >> 5; - for(int i = 0; i> 5, dst, i, (lrand() % 1000) > 500); -} - -static -void simple(int pos, int size) -{ - ndbout_c("simple pos: %d size: %d", pos, size); - Vector _mask; - Vector _src; - Vector _dst; - Uint32 sz32 = (size + pos + 32) >> 5; - const Uint32 sz = 4 * sz32; - - Uint32 zero = 0; - _mask.fill(sz32+1, zero); - _src.fill(sz32+1, zero); - _dst.fill(sz32+1, zero); - - Uint32 * src = _src.getBase(); - Uint32 * dst = _dst.getBase(); - Uint32 * mask = _mask.getBase(); - - memset(src, 0x0, sz); - memset(dst, 0x0, sz); - memset(mask, 0xFF, sz); - rand(src, size); - BitmaskImpl::setField(sz32, mask, pos, size, src); - BitmaskImpl::getField(sz32, mask, pos, size, dst); - printf("src: "); print(src, size+31); printf("\n"); - printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n"); - printf("dst: "); print(dst, size+31); printf("\n"); - require(cmp(src, dst, size+31)); -}; - -static -void simple2(int size, int loops) -{ - ndbout_c("simple2 %d - ", size); - Vector _mask; - Vector _src; - Vector _dst; - - Uint32 sz32 = (size + 32) >> 5; - Uint32 sz = sz32 << 2; - - Uint32 zero = 0; - _mask.fill(sz32+1, zero); - _src.fill(sz32+1, zero); - _dst.fill(sz32+1, zero); - - Uint32 * src = _src.getBase(); - Uint32 * dst = _dst.getBase(); - Uint32 * mask = _mask.getBase(); - - Vector save; - for(int i = 0; i alloc_list; - bitmask_size = (bitmask_size + 31) & ~31; - Uint32 sz32 = (bitmask_size >> 5); - Vector alloc_mask; - Vector test_mask; - - ndbout_c("Testing bitmask of size %d", bitmask_size); - Uint32 zero = 0; - alloc_mask.fill(sz32, zero); - test_mask.fill(sz32, zero); - - for(int i = 0; i<5000; i++) - { - Vector tmp; - tmp.fill(sz32, zero); - - int pos = lrand() % (bitmask_size - 1); - int free = 0; - if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos)) - { - // Bit was allocated - // 1) Look up allocation - // 2) Check data - // 3) free it - size_t j; - int min, max; - for(j = 0; j= min && pos < max) - { - break; - } - } - require(pos >= min && pos < max); - BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min, - tmp.getBase()); - if(DEBUG) - { - printf("freeing [ %d %d ]", min, max); - printf("- mask: "); - print(tmp.getBase(), max - min); - - printf(" save: "); - size_t k; - Alloc& a = alloc_list[j]; - for(k = 0; k> 3; - if(!cmp(tmp.getBase(), alloc_list[j].data.getBase(), max - min)) - { - abort(); - } - while(min < max) - BitmaskImpl::clear(sz32, alloc_mask.getBase(), min++); - alloc_list.erase(j); - } - else - { - Vector tmp; - tmp.fill(sz32, zero); - - // Bit was free - // 1) Check how much space is avaiable - // 2) Create new allocation of lrandom size - // 3) Fill data with lrandom data - // 4) Update alloc mask - while(pos+free < bitmask_size && - !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free)) - free++; - - Uint32 sz = - (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free); - sz = sz ? sz : 1; - sz = pos + sz == bitmask_size ? sz - 1 : sz; - Alloc a; - a.pos = pos; - a.size = sz; - a.data.fill(((sz+31)>> 5)-1, zero); - if(DEBUG) - printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz); - for(size_t j = 0; j 500) - BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j); - } - if(DEBUG) - { - printf("- mask: "); - print(a.data.getBase(), sz); - printf("\n"); - } - BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz, - a.data.getBase()); - alloc_list.push_back(a); - } - } -#endif -} - -template class Vector; -template class Vector; - -#endif +/* Bitmask testcase code moved from here to + * storage/ndb/test/ndbapi/testBitfield.cpp + * to get coverage from automated testing + */ diff --git a/ndb/test/ndbapi/testBitfield.cpp b/ndb/test/ndbapi/testBitfield.cpp index e26f495f5a4..6c958da693d 100644 --- a/ndb/test/ndbapi/testBitfield.cpp +++ b/ndb/test/ndbapi/testBitfield.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include static const char* _dbname = "TEST_DB"; static int g_loops = 7; @@ -28,6 +30,7 @@ static int unique_indexes(Ndb*, const NdbDictionary::Table* tab); static int ordered_indexes(Ndb*, const NdbDictionary::Table* tab); static int node_restart(Ndb*, const NdbDictionary::Table* tab); static int system_restart(Ndb*, const NdbDictionary::Table* tab); +static int testBitmask(); int main(int argc, char** argv){ @@ -38,6 +41,15 @@ main(int argc, char** argv){ argc--; argv++; + + int res = NDBT_FAILED; + + /* Run cluster-independent tests */ + for (int i=0; i<(10*g_loops); i++) + { + if (NDBT_OK != (res= testBitmask())) + return NDBT_ProgramExit(res); + } Ndb_cluster_connection con(opt_connect_str); if(con.connect(12, 5, 1)) @@ -50,7 +62,6 @@ main(int argc, char** argv){ pNdb = new Ndb(&con, _dbname); pNdb->init(); while (pNdb->waitUntilReady() != 0); - int res = NDBT_FAILED; NdbDictionary::Dictionary * dict = pNdb->getDictionary(); @@ -111,14 +122,12 @@ create_random_table(Ndb* pNdb) do { NdbDictionary::Table tab; Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1)); - Uint32 keys = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; Uint32 length = 4090; - Uint32 key_size = NDB_MAX_KEYSIZE_IN_WORDS; BaseString name; name.assfmt("TAB_%d", rand() & 65535); tab.setName(name.c_str()); - for(int i = 0; i 2; i++) + for(Uint32 i = 0; i 2; i++) { NdbDictionary::Column col; name.assfmt("COL_%d", i); @@ -196,3 +205,393 @@ system_restart(Ndb* pNdb, const NdbDictionary::Table* tab) { return 0; } + +/* Note : folowing classes test functionality of storage/ndb/src/common/util/Bitmask.cpp + * and were originally defined there. + * Set BITMASK_DEBUG to 1 to get more test debugging info. + */ +#define BITMASK_DEBUG 0 + +static +bool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len) +{ + Uint32 sz32 = (len + 31) >> 5; + for(Uint32 i = 0; i> 5, src, i+pos)) + printf("1"); + else + printf("0"); + if((i & 31) == 31) + printf(" "); + } +} + +static int lrand() +{ + return rand(); +} + +static +void rand(Uint32 dst[], Uint32 len) +{ + for(Uint32 i = 0; i> 5, dst, i, (lrand() % 1000) > 500); +} + +static +int checkNoTramplingGetSetField(const Uint32 totalTests) +{ + const Uint32 numWords= 67; + const Uint32 maxBitsToCopy= (numWords * 32); + Uint32 sourceBuf[numWords]; + Uint32 targetBuf[numWords]; + + ndbout << "Testing : Bitmask NoTrampling\n"; + + memset(sourceBuf, 0x00, (numWords*4)); + + for (Uint32 test=0; test= srcStart) && + (bitNum < (srcStart + length))); + bool actualValue= (((targetWord >> bit) & 1) == 1); + if (BITMASK_DEBUG) + ndbout << "bitNum=%u expectedValue=%u, actual value=%u" + << bitNum << expectedValue << actualValue; + + if (actualValue != expectedValue) + { + ndbout << "Notrampling setField failed for srcStart " + << srcStart + << " length " << length + << " at word " << word << " bit " << bit << "\n"; + ndbout << "bitNum=%u expectedValue=%u, actual value=%u" + << bitNum << expectedValue << actualValue; + return -1; + } + } + } + + } + + return 0; +} + +static +int simple(int pos, int size) +{ + ndbout << "Testing : Bitmask simple pos: " << pos << " size: " << size << "\n"; + Vector _mask; + Vector _src; + Vector _dst; + Uint32 sz32 = (size + pos + 32) >> 5; + const Uint32 sz = 4 * sz32; + + Uint32 zero = 0; + _mask.fill(sz32+1, zero); + _src.fill(sz32+1, zero); + _dst.fill(sz32+1, zero); + + Uint32 * src = _src.getBase(); + Uint32 * dst = _dst.getBase(); + Uint32 * mask = _mask.getBase(); + + memset(src, 0x0, sz); + memset(dst, 0x0, sz); + memset(mask, 0xFF, sz); + rand(src, size); + BitmaskImpl::setField(sz32, mask, pos, size, src); + BitmaskImpl::getField(sz32, mask, pos, size, dst); + if (BITMASK_DEBUG) + { + printf("src: "); print(src, size+31); printf("\n"); + printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n"); + printf("dst: "); print(dst, size+31); printf("\n"); + } + return (cmp(src, dst, size+31)?0 : -1); +}; + +struct Alloc +{ + Uint32 pos; + Uint32 size; + Vector data; +}; + +static +int +testRanges(Uint32 bitmask_size) +{ + Vector alloc_list; + bitmask_size = (bitmask_size + 31) & ~31; + Uint32 sz32 = (bitmask_size >> 5); + Vector alloc_mask; + Vector test_mask; + + ndbout_c("Testing : Bitmask ranges for bitmask of size %d", bitmask_size); + Uint32 zero = 0; + alloc_mask.fill(sz32, zero); + test_mask.fill(sz32, zero); + + /* Loop a number of times, setting and clearing bits in the mask + * and tracking the modifications in a separate structure. + * Check that both structures remain in sync + */ + for(int i = 0; i<5000; i++) + { + Vector tmp; + tmp.fill(sz32, zero); + + Uint32 pos = lrand() % (bitmask_size - 1); + Uint32 free = 0; + if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos)) + { + // Bit was allocated + // 1) Look up allocation + // 2) Check data + // 3) free it + size_t j; + Uint32 min, max; + for(j = 0; j= min && pos < max) + { + break; + } + } + if (! ((pos >= min) && (pos < max))) + { + printf("Failed with pos %u, min %u, max %u\n", + pos, min, max); + return -1; + } + BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min, + tmp.getBase()); + if(BITMASK_DEBUG) + { + printf("freeing [ %d %d ]", min, max); + printf("- mask: "); + print(tmp.getBase(), max - min); + + printf(" save: "); + size_t k; + Alloc& a = alloc_list[j]; + for(k = 0; k tmp; + tmp.fill(sz32, zero); + + // Bit was free + // 1) Check how much space is avaiable + // 2) Create new allocation of lrandom size + // 3) Fill data with lrandom data + // 4) Update alloc mask + while(pos+free < bitmask_size && + !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free)) + free++; + + Uint32 sz = + (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free); + sz = sz ? sz : 1; + sz = pos + sz == bitmask_size ? sz - 1 : sz; + Alloc a; + a.pos = pos; + a.size = sz; + a.data.fill(((sz+31)>> 5)-1, zero); + if(BITMASK_DEBUG) + printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz); + for(size_t j = 0; j 500) + BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j); + } + if(BITMASK_DEBUG) + { + printf("- mask: "); + print(a.data.getBase(), sz); + printf("\n"); + } + BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz, + a.data.getBase()); + alloc_list.push_back(a); + } + } + +#ifdef NDB_BM_SUPPORT_RANGE + for(Uint32 i = 0; i<1000; i++) + { + Uint32 sz32 = 10+rand() % 100; + Uint32 zero = 0; + Vector map; + map.fill(sz32, zero); + + Uint32 sz = 32 * sz32; + Uint32 start = (rand() % sz); + Uint32 stop = start + ((rand() % (sz - start)) & 0xFFFFFFFF); + + Vector check; + check.fill(sz32, zero); + + /* Verify range setting method works correctly */ + for(Uint32 j = 0; j= start && j= start && j; +template class Vector; From ac632f5cbbb5b9acbbd8c6ec9d0147893e1878a2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Jan 2008 12:56:27 +0100 Subject: [PATCH 7/8] ndb - bug#34005 make sure whole send buffer is flushed, even when wrapping around end ndb/src/common/transporter/TCP_Transporter.cpp: ndb - bug#34005 make sure whole send buffer is flush, even when wrapping around end --- .../common/transporter/TCP_Transporter.cpp | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/ndb/src/common/transporter/TCP_Transporter.cpp b/ndb/src/common/transporter/TCP_Transporter.cpp index 91a5fb50c57..8e09c9d90c8 100644 --- a/ndb/src/common/transporter/TCP_Transporter.cpp +++ b/ndb/src/common/transporter/TCP_Transporter.cpp @@ -330,22 +330,32 @@ TCP_Transporter::doSend() { // Empty the SendBuffers - const char * const sendPtr = m_sendBuffer.sendPtr; - const Uint32 sizeToSend = m_sendBuffer.sendDataSize; - if (sizeToSend > 0){ + bool sent_any = true; + while (m_sendBuffer.dataSize > 0) + { + const char * const sendPtr = m_sendBuffer.sendPtr; + const Uint32 sizeToSend = m_sendBuffer.sendDataSize; const int nBytesSent = inet_send(theSocket, sendPtr, sizeToSend, 0); - if (nBytesSent > 0) { + if (nBytesSent > 0) + { + sent_any = true; m_sendBuffer.bytesSent(nBytesSent); sendCount ++; sendSize += nBytesSent; - if(sendCount == reportFreq){ + if(sendCount == reportFreq) + { reportSendLen(get_callback_obj(), remoteNodeId, sendCount, sendSize); sendCount = 0; sendSize = 0; } - } else { + } + else + { + if (nBytesSent < 0 && InetErrno == EAGAIN && sent_any) + break; + // Send failed #if defined DEBUG_TRANSPORTER ndbout_c("Send Failure(disconnect==%d) to node = %d nBytesSent = %d " From 6fc612e87b2c189fc5fd7911345dfc9c02716470 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Jan 2008 21:51:01 +0100 Subject: [PATCH 8/8] correct result to be the same as in 5.0 --- mysql-test/r/view.result | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 7c1da1b3bab..0e3d650c571 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2720,12 +2720,12 @@ View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (year(`t1`.`test_date`) - year(`t1`.`DOB`)) AS `Age` from `t1` having (`Age` < 75) SELECT (year(test_date)-year(DOB)) AS Age FROM t1 HAVING Age < 75; Age -44 -40 +43 +39 SELECT * FROM v1; Age -44 -40 +43 +39 DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a char(6) DEFAULT 'xxx');