From: Maitrayi Sabaratnam Date: November 3 2010 9:06am Subject: bzr commit into mysql-5.1-telco-7.1 branch (maitrayi.sabaratnam:3941) List-Archive: http://lists.mysql.com/commits/122612 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1707998047==" --===============1707998047== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/tmp/maitrayi/mysql-src/repo-7.1/mysql-5.1-telco-7.1-ndbinfo/ based on revid:jonas@stripped 3941 Maitrayi Sabaratnam 2010-11-03 WORKLOG5567 ndbinfo: disk page buffer modified: BUILD/autorun.sh mysql-test/suite/ndb/r/ndbinfo.result scripts/mysql_system_tables.sql storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp storage/ndb/src/kernel/blocks/pgman.cpp storage/ndb/src/kernel/blocks/pgman.hpp storage/ndb/src/kernel/vm/Ndbinfo.hpp storage/ndb/src/kernel/vm/NdbinfoTables.cpp storage/ndb/tools/ndbinfo_sql.cpp === modified file 'BUILD/autorun.sh' === modified file 'BUILD/autorun.sh' --- a/BUILD/autorun.sh 2008-04-25 06:32:23 +0000 +++ b/BUILD/autorun.sh 2010-11-03 09:06:38 +0000 @@ -20,12 +20,12 @@ done IFS="$save_ifs" -aclocal || die "Can't execute aclocal" +aclocal-1.10 || die "Can't execute aclocal" autoheader || die "Can't execute autoheader" # --force means overwrite ltmain.sh script if it already exists $LIBTOOLIZE --automake --force --copy || die "Can't execute libtoolize" # --add-missing instructs automake to install missing auxiliary files # and --force to overwrite them if they already exist -automake --add-missing --force --copy --gnu -W no-portability || die "Can't execute automake" +automake-1.10 --add-missing --force --copy --gnu -W no-portability || die "Can't execute automake" autoconf || die "Can't execute autoconf" === modified file 'mysql-test/suite/ndb/r/ndbinfo.result' --- a/mysql-test/suite/ndb/r/ndbinfo.result 2010-08-18 10:20:02 +0000 +++ b/mysql-test/suite/ndb/r/ndbinfo.result 2010-11-03 09:06:38 +0000 @@ -35,9 +35,10 @@ 7 resources resources usage (a.k.a superpool) 8 counters monotonic counters 9 nodes node status +10 diskpagebuffer disk page buffer info SELECT COUNT(*) FROM ndb$tables; COUNT(*) -10 +11 SELECT * FROM ndb$tables WHERE table_id = 2; table_id table_name comment 2 test for testing @@ -47,11 +48,12 @@ 7 resources resources usage (a.k.a superpool) 8 counters monotonic counters 9 nodes node status +10 diskpagebuffer disk page buffer info SELECT * FROM ndb$tables WHERE table_name = 'LOGDESTINATION'; table_id table_name comment SELECT COUNT(*) FROM ndb$tables t1, ndb$tables t2 WHERE t1.table_id = t1.table_id; COUNT(*) -100 +121 SELECT table_id, table_name, comment from ndb$tables WHERE table_id > 2 AND table_id <= 5 ORDER BY table_id; @@ -66,6 +68,7 @@ table_id table_name 1 columns 8 counters +10 diskpagebuffer 6 logbuffers 5 logspaces 9 nodes @@ -119,6 +122,7 @@ 7 8 9 +10 TRUNCATE ndb$tables; ERROR HY000: Table 'ndb$tables' is read only === modified file 'scripts/mysql_system_tables.sql' --- a/scripts/mysql_system_tables.sql 2010-08-17 13:53:11 +0000 +++ b/scripts/mysql_system_tables.sql 2010-11-03 09:06:38 +0000 @@ -156,6 +156,16 @@ EXECUTE stmt; DROP PREPARE stmt; +SET @str=IF(@have_ndbinfo,'DROP VIEW IF EXISTS ndbinfo.diskpagebuffer','SET @dummy = 0'); +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + +SET @str=IF(@have_ndbinfo,'DROP VIEW IF EXISTS ndbinfo.diskpagebufferusage','SET @dummy = 0'); +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + # Drop any old lookup tables in ndbinfo SET @str=IF(@have_ndbinfo,'DROP TABLE IF EXISTS ndbinfo.blocks','SET @dummy = 0'); PREPARE stmt FROM @str; @@ -277,6 +287,17 @@ EXECUTE stmt; DROP PREPARE stmt; +# ndbinfo.ndb$diskpagebuffer +SET @str=IF(@have_ndbinfo,'DROP TABLE IF EXISTS `ndbinfo`.`ndb$diskpagebuffer`','SET @dummy = 0'); +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + +SET @str=IF(@have_ndbinfo,'CREATE TABLE `ndbinfo`.`ndb$diskpagebuffer` (`node_id` INT UNSIGNED,`block_instance` INT UNSIGNED,`pages_written` BIGINT UNSIGNED COMMENT "Pages written to disk",`pages_written_lcp` BIGINT UNSIGNED COMMENT "Pages written by local checkpoint",`pages_read` BIGINT UNSIGNED COMMENT "Pages read from disk",`log_waits` BIGINT UNSIGNED COMMENT "Page writes waiting for log to be written to disk",`page_requests_direct_return` BIGINT UNSIGNED COMMENT "Page in buffer and no requests waiting for it",`page_requests_wait_queue` BIGINT UNSIGNED COMMENT "Page in buffer, but some requests are already waiting for it",`page_requests_wait_io` BIGINT UNSIGNED COMMENT "Page not in buffer, waiting to be read from disk") COMMENT="disk page buffer info" ENGINE=NDBINFO','SET @dummy = 0'); +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + # ndbinfo.blocks SET @str=IF(@have_ndbinfo,'CREATE TABLE `ndbinfo`.`blocks` (block_number INT UNSIGNED PRIMARY KEY, block_name VARCHAR(512))','SET @dummy = 0'); PREPARE stmt FROM @str; @@ -341,3 +362,14 @@ EXECUTE stmt; DROP PREPARE stmt; +# ndbinfo.diskpagebuffer +SET @str=IF(@have_ndbinfo,'CREATE OR REPLACE SQL SECURITY INVOKER VIEW `ndbinfo`.`diskpagebuffer` AS SELECT node_id, block_instance, pages_written, pages_written_lcp, pages_read, log_waits, page_requests_direct_return, page_requests_wait_queue, page_requests_wait_io FROM ndbinfo.ndb$diskpagebuffer','SET @dummy = 0'); +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + +# ndbinfo.diskpagebufferusage +SET @str=IF(@have_ndbinfo,'CREATE OR REPLACE SQL SECURITY INVOKER VIEW `ndbinfo`.`diskpagebufferusage` AS SELECT node_id, SUM(pages_written) AS pages_written, SUM(pages_written_lcp) AS pages_written_LCP, SUM(pages_read) AS pages_read, SUM(log_waits) AS log_waits, (SUM(page_requests_direct_return) + SUM(page_requests_wait_queue) + SUM(page_requests_wait_io) ) AS `page_requests_total =`, SUM(page_requests_direct_return) AS `(PR_direct_return`, SUM(page_requests_wait_queue) AS ` + PR_wait_queue`, SUM(page_requests_wait_io) AS ` + PR_wait_IO)` FROM ndbinfo.ndb$diskpagebuffer GROUP BY node_id','SET @dummy = 0'); +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; === modified file 'storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp' --- a/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp 2010-08-17 11:47:55 +0000 +++ b/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp 2010-11-03 09:06:38 +0000 @@ -29,7 +29,8 @@ #endif Uint32 dbinfo_blocks[] = { DBACC, DBTUP, BACKUP, DBTC, SUMA, DBUTIL, - TRIX, DBTUX, DBDICT, CMVMI, DBLQH, LGMAN, 0}; + TRIX, DBTUX, DBDICT, CMVMI, DBLQH, LGMAN, + PGMAN, 0}; Dbinfo::Dbinfo(Block_context& ctx) : SimulatedBlock(DBINFO, ctx) === modified file 'storage/ndb/src/kernel/blocks/pgman.cpp' --- a/storage/ndb/src/kernel/blocks/pgman.cpp 2010-08-20 11:10:25 +0000 +++ b/storage/ndb/src/kernel/blocks/pgman.cpp 2010-11-03 09:06:38 +0000 @@ -72,6 +72,7 @@ addRecSignal(GSN_DATA_FILE_ORD, &Pgman::execDATA_FILE_ORD); addRecSignal(GSN_RELEASE_PAGES_REQ, &Pgman::execRELEASE_PAGES_REQ); + addRecSignal(GSN_DBINFO_SCANREQ, &Pgman::execDBINFO_SCANREQ); // loop status m_stats_loop_on = false; @@ -187,15 +188,6 @@ { } -Pgman::Stats::Stats() : - m_num_pages(0), - m_num_hot_pages(0), - m_current_io_waits(0), - m_page_hits(0), - m_page_faults(0) -{ -} - void Pgman::execSTTOR(Signal* signal) { @@ -1448,6 +1440,7 @@ ndbrequire(m_stats.m_current_io_waits > 0); m_stats.m_current_io_waits--; + m_stats.m_pages_read++; ptr.p->m_last_lcp = m_last_lcp_complete; do_busy_loop(signal, true); @@ -1490,6 +1483,7 @@ else { ndbrequire(ret == 0); + m_stats.m_log_waits++; state |= Page_entry::LOGSYNC; } set_page_state(ptr, state); @@ -1542,6 +1536,7 @@ state &= ~ Page_entry::LCP; ndbrequire(m_lcp_outstanding); m_lcp_outstanding--; + m_stats.m_pages_written_lcp++; if (ptr.p->m_copy_page_i != RNIL) { jam(); @@ -1552,6 +1547,10 @@ return; } } + else + { + m_stats.m_pages_written++; + } set_page_state(ptr, state); do_busy_loop(signal, true); @@ -1715,6 +1714,7 @@ ! (req_flags & Page_request::UNLOCK_PAGE)) { ptr.p->m_state |= (req_flags & DIRTY_FLAGS ? Page_entry::DIRTY : 0); + m_stats.m_page_requests_direct_return++; if (ptr.p->m_copy_page_i != RNIL) { D("m_real_page_i != RNIL); + m_stats.m_page_requests_direct_return++; return ptr.p->m_real_page_i; } } @@ -1757,6 +1758,12 @@ } // queue the request + + if ((state & Page_entry::MAPPED) && ! (state & Page_entry::PAGEOUT)) + m_stats.m_page_requests_wait_q++; + else + m_stats.m_page_requests_wait_io++; + Ptr req_ptr; { Local_page_request_list req_list(m_page_request_pool, ptr.p->m_requests); @@ -2780,3 +2787,36 @@ SET_ERROR_INSERT_VALUE(11009); } } + +void +Pgman::execDBINFO_SCANREQ(Signal *signal) +{ + DbinfoScanReq req= *(DbinfoScanReq*)signal->theData; + const Ndbinfo::ScanCursor* cursor = + reinterpret_cast(DbinfoScan::getCursorPtr(&req)); + Ndbinfo::Ratelimit rl; + + jamEntry(); + switch(req.tableId) { + case Ndbinfo::DISKPAGEBUFFER_TABLEID: + { + jam(); + BlockNumber bn = blockToMain(number()); + Ndbinfo::Row row(signal, req); + row.write_uint32(getOwnNodeId()); + row.write_uint32(instance()); // block instance + row.write_uint64(m_stats.m_pages_written); + row.write_uint64(m_stats.m_pages_written_lcp); + row.write_uint64(m_stats.m_pages_read); + row.write_uint64(m_stats.m_log_waits); + row.write_uint64(m_stats.m_page_requests_direct_return); + row.write_uint64(m_stats.m_page_requests_wait_q); + row.write_uint64(m_stats.m_page_requests_wait_io); + + ndbinfo_send_row(signal, req, row, rl); + } + default: + break; + } + ndbinfo_send_scan_conf(signal, req, rl); +} === modified file 'storage/ndb/src/kernel/blocks/pgman.hpp' --- a/storage/ndb/src/kernel/blocks/pgman.hpp 2010-08-20 11:10:25 +0000 +++ b/storage/ndb/src/kernel/blocks/pgman.hpp 2010-11-03 09:06:38 +0000 @@ -424,12 +424,32 @@ // runtime sizes and statistics struct Stats { - Stats(); + Stats() : + m_num_pages(0), + m_num_hot_pages(0), + m_current_io_waits(0), + m_page_hits(0), + m_page_faults(0), + m_pages_written(0), + m_pages_written_lcp(0), + m_pages_read(0), + m_log_waits(0), + m_page_requests_direct_return(0), + m_page_requests_wait_q(0), + m_page_requests_wait_io(0) + {} Uint32 m_num_pages; // current number of cache pages Uint32 m_num_hot_pages; Uint32 m_current_io_waits; Uint64 m_page_hits; Uint64 m_page_faults; + Uint64 m_pages_written; + Uint64 m_pages_written_lcp; + Uint64 m_pages_read; + Uint64 m_log_waits; // wait for undo WAL to flush the log recs + Uint64 m_page_requests_direct_return; + Uint64 m_page_requests_wait_q; + Uint64 m_page_requests_wait_io; } m_stats; enum CallbackIndex { @@ -459,6 +479,8 @@ void execDATA_FILE_ORD(Signal*); + void execDBINFO_SCANREQ(Signal*); + private: static Uint32 get_sublist_no(Page_state state); void set_page_state(Ptr ptr, Page_state new_state); === modified file 'storage/ndb/src/kernel/vm/Ndbinfo.hpp' --- a/storage/ndb/src/kernel/vm/Ndbinfo.hpp 2010-03-10 10:13:54 +0000 +++ b/storage/ndb/src/kernel/vm/Ndbinfo.hpp 2010-11-03 09:06:38 +0000 @@ -46,7 +46,8 @@ LOGBUFFERS_TABLEID = 6, RESOURCES_TABLEID = 7, COUNTERS_TABLEID = 8, - NODES_TABLEID = 9 + NODES_TABLEID = 9, + DISKPAGEBUFFER_TABLEID = 10 }; struct Table { === modified file 'storage/ndb/src/kernel/vm/NdbinfoTables.cpp' --- a/storage/ndb/src/kernel/vm/NdbinfoTables.cpp 2010-01-20 08:09:28 +0000 +++ b/storage/ndb/src/kernel/vm/NdbinfoTables.cpp 2010-11-03 09:06:38 +0000 @@ -153,6 +153,22 @@ } }; +DECLARE_NDBINFO_TABLE(DISKPAGEBUFFER, 9) = +{ { "diskpagebuffer", 9, 0, "disk page buffer info" }, + { + {"node_id", Ndbinfo::Number, ""}, + {"block_instance", Ndbinfo::Number, ""}, + + {"pages_written", Ndbinfo::Number64, "Pages written to disk"}, + {"pages_written_lcp", Ndbinfo::Number64, "Pages written by local checkpoint"}, + {"pages_read", Ndbinfo::Number64, "Pages read from disk"}, + {"log_waits", Ndbinfo::Number64, "Page writes waiting for log to be written to disk"}, + {"page_requests_direct_return", Ndbinfo::Number64, "Page in buffer and no requests waiting for it"}, + {"page_requests_wait_queue", Ndbinfo::Number64, "Page in buffer, but some requests are already waiting for it"}, + {"page_requests_wait_io", Ndbinfo::Number64, "Page not in buffer, waiting to be read from disk"}, + } +}; + #define DBINFOTBL(x) { Ndbinfo::x##_TABLEID, (Ndbinfo::Table*)&ndbinfo_##x } static @@ -171,7 +187,8 @@ DBINFOTBL(LOGBUFFERS), DBINFOTBL(RESOURCES), DBINFOTBL(COUNTERS), - DBINFOTBL(NODES) + DBINFOTBL(NODES), + DBINFOTBL(DISKPAGEBUFFER) }; static int no_ndbinfo_tables = === modified file 'storage/ndb/tools/ndbinfo_sql.cpp' --- a/storage/ndb/tools/ndbinfo_sql.cpp 2010-08-17 13:53:11 +0000 +++ b/storage/ndb/tools/ndbinfo_sql.cpp 2010-11-03 09:06:38 +0000 @@ -154,6 +154,28 @@ "WHERE block_number IN (248, 254) AND " " (pool_name = \"Index memory\" OR pool_name = \"Data memory\") " "GROUP BY node_id, memory_type" + }, + { "diskpagebuffer", + "SELECT node_id, block_instance, " + "pages_written, pages_written_lcp, pages_read, log_waits, " + "page_requests_direct_return, page_requests_wait_queue, page_requests_wait_io " + "FROM .diskpagebuffer" + }, + { "diskpagebufferusage", + "SELECT node_id, " + " SUM(pages_written) AS pages_written, " + " SUM(pages_written_lcp) AS pages_written_LCP, " + " SUM(pages_read) AS pages_read, " + " SUM(log_waits) AS log_waits, " + " (SUM(page_requests_direct_return) + " + " SUM(page_requests_wait_queue) + " + " SUM(page_requests_wait_io) " + " ) AS `page_requests_total =`, " + " SUM(page_requests_direct_return) AS `(PR_direct_return`, " + " SUM(page_requests_wait_queue) AS ` + PR_wait_queue`, " + " SUM(page_requests_wait_io) AS ` + PR_wait_IO)` " + "FROM .diskpagebuffer " + "GROUP BY node_id" } }; --===============1707998047== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/maitrayi.sabaratnam@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: maitrayi.sabaratnam@stripped\ # 1gwmkoxi1aljsquu # target_branch: file:///export/tmp/maitrayi/mysql-src/repo-7.1/mysql-\ # 5.1-telco-7.1-ndbinfo/ # testament_sha1: 1d9aec171c5b01235c771f07efc347cf3935fc24 # timestamp: 2010-11-03 10:07:01 +0100 # base_revision_id: jonas@stripped # # Begin bundle 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 ZX4v/F3JFOFCQ8N8FGA= --===============1707998047==--