[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (knielsen:2854)
#At lp:maria 2854 knielsen@knielsen-hq.org 2010-04-28 [merge] Merge XtraDB 10 into MariaDB. modified: mysql-test/r/information_schema.result mysql-test/r/information_schema_all_engines.result storage/xtradb/btr/btr0btr.c storage/xtradb/btr/btr0cur.c storage/xtradb/btr/btr0pcur.c storage/xtradb/btr/btr0sea.c storage/xtradb/buf/buf0buddy.c storage/xtradb/buf/buf0buf.c storage/xtradb/buf/buf0flu.c storage/xtradb/buf/buf0rea.c storage/xtradb/build/debian/control storage/xtradb/build/debian/patches/60_percona_support.dpatch storage/xtradb/build/debian/rules storage/xtradb/build/percona-sql.spec storage/xtradb/dict/dict0dict.c storage/xtradb/dict/dict0mem.c storage/xtradb/fil/fil0fil.c storage/xtradb/fsp/fsp0fsp.c storage/xtradb/handler/ha_innodb.cc storage/xtradb/handler/ha_innodb.h storage/xtradb/handler/i_s.cc storage/xtradb/handler/i_s.h storage/xtradb/handler/innodb_patch_info.h storage/xtradb/include/btr0btr.ic storage/xtradb/include/buf0buddy.h storage/xtradb/include/buf0buf.h storage/xtradb/include/buf0buf.ic storage/xtradb/include/buf0types.h storage/xtradb/include/dict0dict.h storage/xtradb/include/dict0mem.h storage/xtradb/include/fil0fil.h storage/xtradb/include/fut0fut.ic storage/xtradb/include/page0cur.h storage/xtradb/include/page0types.h storage/xtradb/include/srv0srv.h storage/xtradb/include/trx0sys.h storage/xtradb/include/univ.i storage/xtradb/include/ut0rnd.h storage/xtradb/include/ut0rnd.ic storage/xtradb/lock/lock0lock.c storage/xtradb/log/log0log.c storage/xtradb/log/log0recv.c storage/xtradb/page/page0cur.c storage/xtradb/page/page0zip.c storage/xtradb/row/row0ins.c storage/xtradb/row/row0merge.c storage/xtradb/row/row0sel.c storage/xtradb/srv/srv0srv.c storage/xtradb/srv/srv0start.c === modified file 'mysql-test/r/information_schema.result' --- a/mysql-test/r/information_schema.result 2010-03-10 09:12:23 +0000 +++ b/mysql-test/r/information_schema.result 2010-04-28 14:35:00 +0000 @@ -65,6 +65,8 @@ INNODB_INDEX_STATS INNODB_LOCKS INNODB_LOCK_WAITS INNODB_RSEG +INNODB_SYS_INDEXES +INNODB_SYS_TABLES INNODB_TABLE_STATS INNODB_TRX KEY_COLUMN_USAGE === modified file 'mysql-test/r/information_schema_all_engines.result' --- a/mysql-test/r/information_schema_all_engines.result 2010-01-15 15:58:25 +0000 +++ b/mysql-test/r/information_schema_all_engines.result 2010-04-28 14:35:00 +0000 @@ -37,12 +37,14 @@ XTRADB_ENHANCEMENTS INNODB_BUFFER_POOL_PAGES_INDEX XTRADB_ADMIN_COMMAND INNODB_TRX -INNODB_CMP_RESET +INNODB_SYS_TABLES INNODB_LOCK_WAITS INNODB_CMPMEM_RESET INNODB_LOCKS INNODB_CMPMEM INNODB_TABLE_STATS +INNODB_SYS_INDEXES +INNODB_CMP_RESET INNODB_BUFFER_POOL_PAGES_BLOB INNODB_INDEX_STATS SELECT t.table_name, c1.column_name @@ -96,14 +98,16 @@ XTRADB_ENHANCEMENTS name INNODB_BUFFER_POOL_PAGES_INDEX schema_name XTRADB_ADMIN_COMMAND result_message INNODB_TRX trx_id -INNODB_CMP_RESET page_size +INNODB_SYS_TABLES NAME INNODB_LOCK_WAITS requesting_trx_id INNODB_CMPMEM_RESET page_size INNODB_LOCKS lock_id INNODB_CMPMEM page_size -INNODB_TABLE_STATS table_name +INNODB_TABLE_STATS table_schema +INNODB_SYS_INDEXES TABLE_ID +INNODB_CMP_RESET page_size INNODB_BUFFER_POOL_PAGES_BLOB space_id -INNODB_INDEX_STATS table_name +INNODB_INDEX_STATS table_schema SELECT t.table_name, c1.column_name FROM information_schema.tables t INNER JOIN @@ -155,14 +159,16 @@ XTRADB_ENHANCEMENTS name INNODB_BUFFER_POOL_PAGES_INDEX schema_name XTRADB_ADMIN_COMMAND result_message INNODB_TRX trx_id -INNODB_CMP_RESET page_size +INNODB_SYS_TABLES NAME INNODB_LOCK_WAITS requesting_trx_id INNODB_CMPMEM_RESET page_size INNODB_LOCKS lock_id INNODB_CMPMEM page_size -INNODB_TABLE_STATS table_name +INNODB_TABLE_STATS table_schema +INNODB_SYS_INDEXES TABLE_ID +INNODB_CMP_RESET page_size INNODB_BUFFER_POOL_PAGES_BLOB space_id -INNODB_INDEX_STATS table_name +INNODB_INDEX_STATS table_schema select 1 as f1 from information_schema.tables where "CHARACTER_SETS"= (select cast(table_name as char) from information_schema.tables order by table_name limit 1) limit 1; @@ -205,6 +211,8 @@ INNODB_INDEX_STATS information_schema.IN INNODB_LOCKS information_schema.INNODB_LOCKS 1 INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1 INNODB_RSEG information_schema.INNODB_RSEG 1 +INNODB_SYS_INDEXES information_schema.INNODB_SYS_INDEXES 1 +INNODB_SYS_TABLES information_schema.INNODB_SYS_TABLES 1 INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1 INNODB_TRX information_schema.INNODB_TRX 1 KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1 @@ -267,12 +275,14 @@ Database: information_schema | INNODB_BUFFER_POOL_PAGES_INDEX | | XTRADB_ADMIN_COMMAND | | INNODB_TRX | -| INNODB_CMP_RESET | +| INNODB_SYS_TABLES | | INNODB_LOCK_WAITS | | INNODB_CMPMEM_RESET | | INNODB_LOCKS | | INNODB_CMPMEM | | INNODB_TABLE_STATS | +| INNODB_SYS_INDEXES | +| INNODB_CMP_RESET | | INNODB_BUFFER_POOL_PAGES_BLOB | | INNODB_INDEX_STATS | +---------------------------------------+ @@ -316,12 +326,14 @@ Database: INFORMATION_SCHEMA | INNODB_BUFFER_POOL_PAGES_INDEX | | XTRADB_ADMIN_COMMAND | | INNODB_TRX | -| INNODB_CMP_RESET | +| INNODB_SYS_TABLES | | INNODB_LOCK_WAITS | | INNODB_CMPMEM_RESET | | INNODB_LOCKS | | INNODB_CMPMEM | | INNODB_TABLE_STATS | +| INNODB_SYS_INDEXES | +| INNODB_CMP_RESET | | INNODB_BUFFER_POOL_PAGES_BLOB | | INNODB_INDEX_STATS | +---------------------------------------+ @@ -333,5 +345,5 @@ Wildcard: inf_rmation_schema +--------------------+ SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA; table_schema count(*) -information_schema 44 +information_schema 46 mysql 22 === modified file 'storage/xtradb/btr/btr0btr.c' --- a/storage/xtradb/btr/btr0btr.c 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/btr/btr0btr.c 2010-03-22 20:42:52 +0000 @@ -137,6 +137,12 @@ btr_root_block_get( root_page_no = dict_index_get_page(index); block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr); + + if (srv_pass_corrupt_table && !block) { + return(0); + } + ut_a(block); + ut_a((ibool)!!page_is_comp(buf_block_get_frame(block)) == dict_table_is_comp(index->table)); #ifdef UNIV_BTR_DEBUG @@ -422,6 +428,12 @@ btr_get_size( root = btr_root_get(index, &mtr); + if (srv_pass_corrupt_table && !root) { + mtr_commit(&mtr); + return(0); + } + ut_a(root); + if (flag == BTR_N_LEAF_PAGES) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; @@ -862,6 +874,13 @@ leaf_loop: mtr_start(&mtr); root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr); + + if (srv_pass_corrupt_table && !root) { + mtr_commit(&mtr); + return; + } + ut_a(root); + #ifdef UNIV_BTR_DEBUG ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF + root, space)); @@ -884,6 +903,12 @@ top_loop: mtr_start(&mtr); root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr); + + if (srv_pass_corrupt_table && !root) { + mtr_commit(&mtr); + return; + } + ut_a(root); #ifdef UNIV_BTR_DEBUG ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP + root, space)); @@ -917,6 +942,11 @@ btr_free_root( block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr); + if (srv_pass_corrupt_table && !block) { + return; + } + ut_a(block); + btr_search_drop_page_hash_index(block); header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP; === modified file 'storage/xtradb/btr/btr0cur.c' --- a/storage/xtradb/btr/btr0cur.c 2010-03-10 10:32:14 +0000 +++ b/storage/xtradb/btr/btr0cur.c 2010-04-28 14:35:00 +0000 @@ -227,6 +227,11 @@ btr_cur_latch_leaves( case BTR_MODIFY_LEAF: mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH; get_block = btr_block_get(space, zip_size, page_no, mode, mtr); + + if (srv_pass_corrupt_table && !get_block) { + return; + } + ut_a(get_block); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); #endif /* UNIV_BTR_DEBUG */ @@ -240,6 +245,11 @@ btr_cur_latch_leaves( get_block = btr_block_get(space, zip_size, left_page_no, RW_X_LATCH, mtr); + + if (srv_pass_corrupt_table && !get_block) { + return; + } + ut_a(get_block); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); @@ -251,6 +261,11 @@ btr_cur_latch_leaves( get_block = btr_block_get(space, zip_size, page_no, RW_X_LATCH, mtr); + + if (srv_pass_corrupt_table && !get_block) { + return; + } + ut_a(get_block); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); #endif /* UNIV_BTR_DEBUG */ @@ -262,6 +277,11 @@ btr_cur_latch_leaves( get_block = btr_block_get(space, zip_size, right_page_no, RW_X_LATCH, mtr); + + if (srv_pass_corrupt_table && !get_block) { + return; + } + ut_a(get_block); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); @@ -283,6 +303,11 @@ btr_cur_latch_leaves( get_block = btr_block_get(space, zip_size, left_page_no, mode, mtr); cursor->left_block = get_block; + + if (srv_pass_corrupt_table && !get_block) { + return; + } + ut_a(get_block); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); @@ -293,6 +318,11 @@ btr_cur_latch_leaves( } get_block = btr_block_get(space, zip_size, page_no, mode, mtr); + + if (srv_pass_corrupt_table && !get_block) { + return; + } + ut_a(get_block); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); #endif /* UNIV_BTR_DEBUG */ @@ -522,6 +552,16 @@ retry_page_get: rw_latch, guess, buf_mode, __FILE__, __LINE__, mtr); if (block == NULL) { + if (srv_pass_corrupt_table && buf_mode != BUF_GET_IF_IN_POOL) { + page_cursor->block = 0; + page_cursor->rec = 0; + if (estimate) { + cursor->path_arr->nth_rec = ULINT_UNDEFINED; + } + break; + } + ut_a(buf_mode == BUF_GET_IF_IN_POOL); + /* This must be a search to perform an insert; try insert to the insert buffer */ @@ -549,6 +589,16 @@ retry_page_get: page = buf_block_get_frame(block); + if (srv_pass_corrupt_table && !page) { + page_cursor->block = 0; + page_cursor->rec = 0; + if (estimate) { + cursor->path_arr->nth_rec = ULINT_UNDEFINED; + } + break; + } + ut_a(page); + block->check_index_page_at_flush = TRUE; if (rw_latch != RW_NO_LATCH) { @@ -730,6 +780,17 @@ btr_cur_open_at_index_side( RW_NO_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr); page = buf_block_get_frame(block); + + if (srv_pass_corrupt_table && !page) { + page_cursor->block = 0; + page_cursor->rec = 0; + if (estimate) { + cursor->path_arr->nth_rec = ULINT_UNDEFINED; + } + break; + } + ut_a(page); + ut_ad(0 == ut_dulint_cmp(index->id, btr_page_get_index_id(page))); @@ -849,6 +910,14 @@ btr_cur_open_at_rnd_pos( RW_NO_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr); page = buf_block_get_frame(block); + + if (srv_pass_corrupt_table && !page) { + page_cursor->block = 0; + page_cursor->rec = 0; + break; + } + ut_a(page); + ut_ad(0 == ut_dulint_cmp(index->id, btr_page_get_index_id(page))); @@ -886,6 +955,108 @@ btr_cur_open_at_rnd_pos( } } +/**********************************************************************//** +Positions a cursor at a randomly chosen position within a B-tree +after the given path +@return TRUE if the position is at the first page, and cursor must point + the first record for used by the caller.*/ +UNIV_INTERN +ibool +btr_cur_open_at_rnd_pos_after_path( +/*====================*/ + dict_index_t* index, /*!< in: index */ + ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ + btr_path_t* first_rec_path, + btr_cur_t* cursor, /*!< in/out: B-tree cursor */ + mtr_t* mtr) /*!< in: mtr */ +{ + page_cur_t* page_cursor; + btr_path_t* slot; + ibool is_first_rec = TRUE; + ulint page_no; + ulint space; + ulint zip_size; + ulint height; + rec_t* node_ptr; + mem_heap_t* heap = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + ulint* offsets = offsets_; + rec_offs_init(offsets_); + + if (latch_mode == BTR_MODIFY_TREE) { + mtr_x_lock(dict_index_get_lock(index), mtr); + } else { + mtr_s_lock(dict_index_get_lock(index), mtr); + } + + page_cursor = btr_cur_get_page_cur(cursor); + cursor->index = index; + + space = dict_index_get_space(index); + zip_size = dict_table_zip_size(index->table); + page_no = dict_index_get_page(index); + + height = ULINT_UNDEFINED; + slot = first_rec_path; + + for (;;) { + buf_block_t* block; + page_t* page; + + block = buf_page_get_gen(space, zip_size, page_no, + RW_NO_LATCH, NULL, BUF_GET, + __FILE__, __LINE__, mtr); + page = buf_block_get_frame(block); + ut_ad(0 == ut_dulint_cmp(index->id, + btr_page_get_index_id(page))); + + if (height == ULINT_UNDEFINED) { + /* We are in the root node */ + + height = btr_page_get_level(page, mtr); + } + + if (height == 0) { + btr_cur_latch_leaves(page, space, zip_size, page_no, + latch_mode, cursor, mtr); + } + + if (is_first_rec && slot->nth_rec != ULINT_UNDEFINED) { + if (height == 0) { + /* must open the first rec */ + page_cur_open_on_nth_user_rec(block, page_cursor, slot->nth_rec); + } else { + is_first_rec = page_cur_open_on_rnd_user_rec_after_nth(block, + page_cursor, slot->nth_rec); + } + } else { + is_first_rec = FALSE; + page_cur_open_on_rnd_user_rec(block, page_cursor); + } + + if (height == 0) { + break; + } + + ut_ad(height > 0); + + height--; + slot++; + + node_ptr = page_cur_get_rec(page_cursor); + offsets = rec_get_offsets(node_ptr, cursor->index, offsets, + ULINT_UNDEFINED, &heap); + /* Go to the child node */ + page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); + } + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + return (is_first_rec); +} + /*==================== B-TREE INSERT =========================*/ /*************************************************************//** @@ -1064,6 +1235,12 @@ btr_cur_optimistic_insert( *big_rec = NULL; block = btr_cur_get_block(cursor); + + if (srv_pass_corrupt_table && !block) { + return(DB_CORRUPTION); + } + ut_a(block); + page = buf_block_get_frame(block); index = cursor->index; zip_size = buf_block_get_zip_size(block); @@ -2810,6 +2987,11 @@ btr_cur_optimistic_delete( block = btr_cur_get_block(cursor); + if (srv_pass_corrupt_table && !block) { + return(DB_CORRUPTION); + } + ut_a(block); + ut_ad(page_is_leaf(buf_block_get_frame(block))); rec = btr_cur_get_rec(cursor); @@ -3216,6 +3398,154 @@ btr_estimate_n_rows_in_range( } /*******************************************************************//** +Estimates the number of pages which have not null value of the key of n_cols. +@return estimated number of pages */ +UNIV_INTERN +ulint +btr_estimate_n_pages_not_null( +/*=========================*/ + dict_index_t* index, /*!< in: index */ + ulint n_cols, /*!< in: The cols should be not null */ + btr_path_t* path1) /*!< in: path1[BTR_PATH_ARRAY_N_SLOTS] */ +{ + dtuple_t* tuple1; + btr_path_t path2[BTR_PATH_ARRAY_N_SLOTS]; + btr_cur_t cursor; + btr_path_t* slot1; + btr_path_t* slot2; + ibool diverged; + ibool diverged_lot; + ulint divergence_level; + ulint n_pages; + ulint i,j; + mtr_t mtr; + mem_heap_t* heap; + + heap = mem_heap_create(n_cols * sizeof(dfield_t) + + sizeof(dtuple_t)); + + /* make tuple1 (NULL,NULL,,,) from n_cols */ + tuple1 = dtuple_create(heap, n_cols); + dict_index_copy_types(tuple1, index, n_cols); + + for (i = 0; i < n_cols; i++) { + dfield_set_null(dtuple_get_nth_field(tuple1, i)); + } + + mtr_start(&mtr); + + cursor.path_arr = path1; + + btr_cur_search_to_nth_level(index, 0, tuple1, PAGE_CUR_G, + BTR_SEARCH_LEAF | BTR_ESTIMATE, + &cursor, 0, &mtr); + + mtr_commit(&mtr); + + + + mtr_start(&mtr); + + cursor.path_arr = path2; + + btr_cur_open_at_index_side(FALSE, index, + BTR_SEARCH_LEAF | BTR_ESTIMATE, + &cursor, &mtr); + + mtr_commit(&mtr); + + mem_heap_free(heap); + + /* We have the path information for the range in path1 and path2 */ + + n_pages = 1; + diverged = FALSE; /* This becomes true when the path is not + the same any more */ + diverged_lot = FALSE; /* This becomes true when the paths are + not the same or adjacent any more */ + divergence_level = 1000000; /* This is the level where paths diverged + a lot */ + for (i = 0; ; i++) { + ut_ad(i < BTR_PATH_ARRAY_N_SLOTS); + + slot1 = path1 + i; + slot2 = path2 + i; + + if ((slot1 + 1)->nth_rec == ULINT_UNDEFINED + || (slot2 + 1)->nth_rec == ULINT_UNDEFINED) { + + if (i > divergence_level + 1) { + /* In trees whose height is > 1 our algorithm + tends to underestimate: multiply the estimate + by 2: */ + + n_pages = n_pages * 2; + } + + /* Do not estimate the number of rows in the range + to over 1 / 2 of the estimated rows in the whole + table */ + + if (n_pages > index->stat_n_leaf_pages / 2) { + n_pages = index->stat_n_leaf_pages / 2; + + /* If there are just 0 or 1 rows in the table, + then we estimate all rows are in the range */ + + if (n_pages == 0) { + n_pages = index->stat_n_leaf_pages; + } + } + + return(n_pages); + } + + if (!diverged && slot1->nth_rec != slot2->nth_rec) { + + diverged = TRUE; + + if (slot1->nth_rec < slot2->nth_rec) { + n_pages = slot2->nth_rec - slot1->nth_rec; + + if (n_pages > 1) { + diverged_lot = TRUE; + divergence_level = i; + } + } else { + /* Maybe the tree has changed between + searches */ + + return(10); + } + + } else if (diverged && !diverged_lot) { + + if (slot1->nth_rec < slot1->n_recs + || slot2->nth_rec > 1) { + + diverged_lot = TRUE; + divergence_level = i; + + n_pages = 0; + + if (slot1->nth_rec < slot1->n_recs) { + n_pages += slot1->n_recs + - slot1->nth_rec; + } + + if (slot2->nth_rec > 1) { + n_pages += slot2->nth_rec - 1; + } + } + } else if (diverged_lot) { + + n_pages = (n_pages * (slot1->n_recs + slot2->n_recs)) + / 2; + } + } +} + +/*******************************************************************//** Estimates the number of different key values in a given index, for each n-column prefix of the index where n <= dict_index_get_n_unique(index). The estimates are stored in the array index->stat_n_diff_key_vals. */ @@ -3231,9 +3561,7 @@ btr_estimate_number_of_different_key_val ulint n_cols; ulint matched_fields; ulint matched_bytes; - ib_int64_t n_recs = 0; ib_int64_t* n_diff; - ib_int64_t* n_not_nulls= 0; ullint n_sample_pages; /* number of pages to sample */ ulint not_empty_flag = 0; ulint total_external_size = 0; @@ -3247,22 +3575,37 @@ btr_estimate_number_of_different_key_val ulint* offsets_rec = offsets_rec_; ulint* offsets_next_rec= offsets_next_rec_; ulint stats_method = srv_stats_method; + btr_path_t first_rec_path[BTR_PATH_ARRAY_N_SLOTS]; + ulint effective_pages; /* effective leaf pages */ rec_offs_init(offsets_rec_); rec_offs_init(offsets_next_rec_); n_cols = dict_index_get_n_unique(index); - n_diff = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t)); - if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) { - n_not_nulls = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t)); + /* estimate effective pages and path for the first effective record */ + /* TODO: make it work also for n_cols > 1. */ + effective_pages = btr_estimate_n_pages_not_null(index, 1 /*k*/, first_rec_path); + + if (!effective_pages) { + for (j = 0; j <= n_cols; j++) { + index->stat_n_diff_key_vals[j] = (ib_int64_t)index->stat_n_leaf_pages; + } + return; + } else if (effective_pages > index->stat_n_leaf_pages) { + effective_pages = index->stat_n_leaf_pages; + } + } else { + effective_pages = index->stat_n_leaf_pages; } + n_diff = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t)); + /* It makes no sense to test more pages than are contained in the index, thus we lower the number if it is too high */ - if (srv_stats_sample_pages > index->stat_index_size) { - if (index->stat_index_size > 0) { - n_sample_pages = index->stat_index_size; + if (srv_stats_sample_pages > effective_pages) { + if (effective_pages > 0) { + n_sample_pages = effective_pages; } else { n_sample_pages = 1; } @@ -3274,9 +3617,15 @@ btr_estimate_number_of_different_key_val for (i = 0; i < n_sample_pages; i++) { rec_t* supremum; + ibool is_first_page = TRUE; mtr_start(&mtr); + if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) { + is_first_page = btr_cur_open_at_rnd_pos_after_path(index, BTR_SEARCH_LEAF, + first_rec_path, &cursor, &mtr); + } else { btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); + } /* Count the number of different key values for each prefix of the key on this index page. If the prefix does not determine @@ -3286,8 +3635,19 @@ btr_estimate_number_of_different_key_val page = btr_cur_get_page(&cursor); + if (srv_pass_corrupt_table && !page) { + break; + } + ut_a(page); + supremum = page_get_supremum_rec(page); + if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS && is_first_page) { + /* the cursor should be the first record of the page. */ + /* Counting should be started from here. */ + rec = btr_cur_get_rec(&cursor); + } else { rec = page_rec_get_next(page_get_infimum_rec(page)); + } if (rec != supremum) { not_empty_flag = 1; @@ -3297,19 +3657,6 @@ btr_estimate_number_of_different_key_val while (rec != supremum) { rec_t* next_rec; - /* count recs */ - if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) { - n_recs++; - for (j = 0; j <= n_cols; j++) { - ulint f_len; - rec_get_nth_field(rec, offsets_rec, - j, &f_len); - if (f_len == UNIV_SQL_NULL) - break; - - n_not_nulls[j]++; - } - } next_rec = page_rec_get_next(rec); if (next_rec == supremum) { break; @@ -3324,7 +3671,10 @@ btr_estimate_number_of_different_key_val cmp_rec_rec_with_match(rec, next_rec, offsets_rec, offsets_next_rec, index, &matched_fields, - &matched_bytes, srv_stats_method); + &matched_bytes, + (stats_method==SRV_STATS_METHOD_NULLS_NOT_EQUAL) ? + SRV_STATS_METHOD_NULLS_NOT_EQUAL : + SRV_STATS_METHOD_NULLS_EQUAL); for (j = matched_fields + 1; j <= n_cols; j++) { /* We add one if this index record has @@ -3385,7 +3735,7 @@ btr_estimate_number_of_different_key_val for (j = 0; j <= n_cols; j++) { index->stat_n_diff_key_vals[j] = ((n_diff[j] - * (ib_int64_t)index->stat_n_leaf_pages + * (ib_int64_t)effective_pages + n_sample_pages - 1 + total_external_size + not_empty_flag) @@ -3400,7 +3750,7 @@ btr_estimate_number_of_different_key_val different key values, or even more. Let us try to approximate that: */ - add_on = index->stat_n_leaf_pages + add_on = effective_pages / (10 * (n_sample_pages + total_external_size)); @@ -3410,20 +3760,18 @@ btr_estimate_number_of_different_key_val index->stat_n_diff_key_vals[j] += add_on; - /* revision for 'nulls_ignored' */ if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) { - if (!n_not_nulls[j]) - n_not_nulls[j] = 1; + /* index->stat_n_diff_key_vals[k] is used for calc rec_per_key, + as "stats.records / index->stat_n_diff_key_vals[x]". + So it should be adjusted to the value which is based on whole of the index. */ index->stat_n_diff_key_vals[j] = - index->stat_n_diff_key_vals[j] * n_recs - / n_not_nulls[j]; + index->stat_n_diff_key_vals[j] * (ib_int64_t)index->stat_n_leaf_pages + / (ib_int64_t)effective_pages; } } mem_free(n_diff); - if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) { - mem_free(n_not_nulls); - } + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } === modified file 'storage/xtradb/btr/btr0pcur.c' --- a/storage/xtradb/btr/btr0pcur.c 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/btr/btr0pcur.c 2010-03-22 20:42:52 +0000 @@ -32,7 +32,7 @@ Created 2/23/1996 Heikki Tuuri #include "ut0byte.h" #include "rem0cmp.h" #include "trx0trx.h" - +#include "srv0srv.h" /**************************************************************//** Allocates memory for a persistent cursor object and initializes the cursor. @return own: persistent cursor */ @@ -102,6 +102,12 @@ btr_pcur_store_position( ut_ad(cursor->latch_mode != BTR_NO_LATCHES); block = btr_pcur_get_block(cursor); + + if (srv_pass_corrupt_table && !block) { + return; + } + ut_a(block); + index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor)); page_cursor = btr_pcur_get_page_cur(cursor); @@ -413,6 +419,15 @@ btr_pcur_move_to_next_page( next_block = btr_block_get(space, zip_size, next_page_no, cursor->latch_mode, mtr); next_page = buf_block_get_frame(next_block); + + if (srv_pass_corrupt_table && !next_page) { + btr_leaf_page_release(btr_pcur_get_block(cursor), + cursor->latch_mode, mtr); + btr_pcur_get_page_cur(cursor)->block = 0; + btr_pcur_get_page_cur(cursor)->rec = 0; + return; + } + ut_a(next_page); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(next_page) == page_is_comp(page)); ut_a(btr_page_get_prev(next_page, mtr) === modified file 'storage/xtradb/btr/btr0sea.c' --- a/storage/xtradb/btr/btr0sea.c 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/btr/btr0sea.c 2010-03-22 20:42:52 +0000 @@ -42,7 +42,7 @@ Created 2/17/1996 Heikki Tuuri #include "btr0pcur.h" #include "btr0btr.h" #include "ha0ha.h" - +#include "srv0srv.h" /** Flag: has the search system been enabled? Protected by btr_search_latch and btr_search_enabled_mutex. */ UNIV_INTERN char btr_search_enabled = TRUE; @@ -585,6 +585,11 @@ btr_search_info_update_slow( block = btr_cur_get_block(cursor); + if (srv_pass_corrupt_table && !block) { + return; + } + ut_a(block); + /* NOTE that the following two function calls do NOT protect info or block->n_fields etc. with any semaphore, to save CPU time! We cannot assume the fields are consistent when we return from === modified file 'storage/xtradb/buf/buf0buddy.c' --- a/storage/xtradb/buf/buf0buddy.c 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/buf/buf0buddy.c 2010-04-28 14:35:00 +0000 @@ -43,7 +43,7 @@ static ulint buf_buddy_n_frames; #endif /* UNIV_DEBUG */ /** Statistics of the buddy system, indexed by block size. Protected by buf_pool_mutex. */ -UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1]; +UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES_MAX + 1]; /**********************************************************************//** Get the offset of the buddy of a compressed page frame. === modified file 'storage/xtradb/buf/buf0buf.c' --- a/storage/xtradb/buf/buf0buf.c 2010-01-28 11:35:10 +0000 +++ b/storage/xtradb/buf/buf0buf.c 2010-04-28 14:35:00 +0000 @@ -52,6 +52,7 @@ Created 11/5/1995 Heikki Tuuri #include "log0recv.h" #include "page0zip.h" #include "trx0trx.h" +#include "srv0start.h" /* prototypes for new functions added to ha_innodb.cc */ trx_t* innobase_get_trx(); @@ -348,6 +349,27 @@ buf_calc_page_new_checksum( return(checksum); } +UNIV_INTERN +ulint +buf_calc_page_new_checksum_32( +/*==========================*/ + const byte* page) /*!< in: buffer page */ +{ + ulint checksum; + + checksum = ut_fold_binary(page + FIL_PAGE_OFFSET, + FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET) + + ut_fold_binary(page + FIL_PAGE_DATA, + FIL_PAGE_DATA_ALIGN_32 - FIL_PAGE_DATA) + + ut_fold_binary_32(page + FIL_PAGE_DATA_ALIGN_32, + UNIV_PAGE_SIZE - FIL_PAGE_DATA_ALIGN_32 + - FIL_PAGE_END_LSN_OLD_CHKSUM); + + checksum = checksum & 0xFFFFFFFFUL; + + return(checksum); +} + /********************************************************************//** In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only looked at the first few bytes of the page. This calculates that old @@ -462,13 +484,25 @@ buf_page_is_corrupted( /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */ - if (checksum_field != 0 + if (!srv_fast_checksum + && checksum_field != 0 && checksum_field != BUF_NO_CHECKSUM_MAGIC && checksum_field != buf_calc_page_new_checksum(read_buf)) { return(TRUE); } + + if (srv_fast_checksum + && checksum_field != 0 + && checksum_field != BUF_NO_CHECKSUM_MAGIC + && checksum_field + != buf_calc_page_new_checksum_32(read_buf) + && checksum_field + != buf_calc_page_new_checksum(read_buf)) { + + return(TRUE); + } } return(FALSE); @@ -488,6 +522,7 @@ buf_page_print( dict_index_t* index; #endif /* !UNIV_HOTBACKUP */ ulint checksum; + ulint checksum_32; ulint old_checksum; ulint size = zip_size; @@ -574,12 +609,14 @@ buf_page_print( checksum = srv_use_checksums ? buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; + checksum_32 = srv_use_checksums + ? buf_calc_page_new_checksum_32(read_buf) : BUF_NO_CHECKSUM_MAGIC; old_checksum = srv_use_checksums ? buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC; ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Page checksum %lu, prior-to-4.0.14-form" + " InnoDB: Page checksum %lu (32bit_calc: %lu), prior-to-4.0.14-form" " checksum %lu\n" "InnoDB: stored checksum %lu, prior-to-4.0.14-form" " stored checksum %lu\n" @@ -588,7 +625,7 @@ buf_page_print( "InnoDB: Page number (if stored to page already) %lu,\n" "InnoDB: space id (if created with >= MySQL-4.1.1" " and stored already) %lu\n", - (ulong) checksum, (ulong) old_checksum, + (ulong) checksum, (ulong) checksum_32, (ulong) old_checksum, (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM), (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM), @@ -1809,6 +1846,14 @@ err_exit: return(NULL); } + if (srv_pass_corrupt_table) { + if (bpage->is_corrupt) { + rw_lock_s_unlock(&page_hash_latch); + return(NULL); + } + } + ut_a(!(bpage->is_corrupt)); + block_mutex = buf_page_get_mutex_enter(bpage); rw_lock_s_unlock(&page_hash_latch); @@ -2246,6 +2291,14 @@ loop2: return(NULL); } + if (srv_pass_corrupt_table) { + if (block->page.is_corrupt) { + mutex_exit(block_mutex); + return(NULL); + } + } + ut_a(!(block->page.is_corrupt)); + switch (buf_block_get_state(block)) { buf_page_t* bpage; ibool success; @@ -2874,6 +2927,7 @@ buf_page_init_low( bpage->newest_modification = 0; bpage->oldest_modification = 0; HASH_INVALIDATE(bpage, hash); + bpage->is_corrupt = FALSE; #ifdef UNIV_DEBUG_FILE_ACCESSES bpage->file_page_was_freed = FALSE; #endif /* UNIV_DEBUG_FILE_ACCESSES */ @@ -3329,7 +3383,8 @@ UNIV_INTERN void buf_page_io_complete( /*=================*/ - buf_page_t* bpage) /*!< in: pointer to the block in question */ + buf_page_t* bpage, /*!< in: pointer to the block in question */ + trx_t* trx) { enum buf_io_fix io_type; const ibool uncompressed = (buf_page_get_state(bpage) @@ -3406,6 +3461,7 @@ buf_page_io_complete( (ulong) bpage->offset); } + if (!srv_pass_corrupt_table || !bpage->is_corrupt) { /* From version 3.23.38 up we store the page checksum to the 4 first bytes of the page end lsn field */ @@ -3447,6 +3503,19 @@ corrupt: REFMAN "forcing-recovery.html\n" "InnoDB: about forcing recovery.\n", stderr); + if (srv_pass_corrupt_table && bpage->space > 0 + && bpage->space < SRV_LOG_SPACE_FIRST_ID) { + fprintf(stderr, + "InnoDB: space %lu will be treated as corrupt.\n", + bpage->space); + fil_space_set_corrupt(bpage->space); + if (trx && trx->dict_operation_lock_mode == 0) { + dict_table_set_corrupt_by_space(bpage->space, TRUE); + } else { + dict_table_set_corrupt_by_space(bpage->space, FALSE); + } + bpage->is_corrupt = TRUE; + } else if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { fputs("InnoDB: Ending processing because of" " a corrupt database page.\n", @@ -3454,6 +3523,7 @@ corrupt: exit(1); } } + } /**/ if (recv_recovery_is_on()) { /* Pages must be uncompressed for crash recovery. */ @@ -3463,8 +3533,11 @@ corrupt: if (uncompressed && !recv_no_ibuf_operations) { ibuf_merge_or_delete_for_page( + /* Delete possible entries, if bpage is_corrupt */ + (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL : (buf_block_t*) bpage, bpage->space, bpage->offset, buf_page_get_zip_size(bpage), + (srv_pass_corrupt_table && bpage->is_corrupt) ? FALSE : TRUE); } } === modified file 'storage/xtradb/buf/buf0flu.c' --- a/storage/xtradb/buf/buf0flu.c 2010-04-28 13:53:04 +0000 +++ b/storage/xtradb/buf/buf0flu.c 2010-04-28 14:35:00 +0000 @@ -711,7 +711,9 @@ buf_flush_init_for_writing( mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, srv_use_checksums - ? buf_calc_page_new_checksum(page) + ? (!srv_fast_checksum + ? buf_calc_page_new_checksum(page) + : buf_calc_page_new_checksum_32(page)) : BUF_NO_CHECKSUM_MAGIC); /* We overwrite the first 4 bytes of the end lsn field to store === modified file 'storage/xtradb/buf/buf0rea.c' --- a/storage/xtradb/buf/buf0rea.c 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/buf/buf0rea.c 2010-04-28 14:35:00 +0000 @@ -187,12 +187,19 @@ not_to_recover: sync, space, 0, offset, 0, UNIV_PAGE_SIZE, ((buf_block_t*) bpage)->frame, bpage, trx); } + + if (srv_pass_corrupt_table) { + if (*err != DB_SUCCESS) { + bpage->is_corrupt = TRUE; + } + } else { ut_a(*err == DB_SUCCESS); + } if (sync) { /* The i/o is already completed when we arrive from fil_read */ - buf_page_io_complete(bpage); + buf_page_io_complete(bpage, trx); } return(1); === modified file 'storage/xtradb/build/debian/control' --- a/storage/xtradb/build/debian/control 2010-02-22 19:53:53 +0000 +++ b/storage/xtradb/build/debian/control 2010-04-06 08:23:16 +0000 @@ -47,9 +47,9 @@ Package: percona-xtradb-common Section: database Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends} -Conflicts: mysql-common-4.1, mysql-common-5.0, mysql-common-5.1 -Provides: mysql-common-4.1, percona-xtradb-common -Replaces: mysql-common-4.1, mysql-common-5.0, mysql-common-5.1 +Conflicts: mysql-common-4.1, mysql-common-5.0, mysql-common-5.1, mysql-common +Provides: mysql-common +Replaces: mysql-common-4.1, mysql-common-5.0, mysql-common-5.1, mysql-common Description: Percona SQL database common files (e.g. /etc/mysql/my.cnf) Percona SQL is a fast, stable and true multi-user, multi-threaded SQL database server. SQL (Structured Query Language) is the most popular database query === modified file 'storage/xtradb/build/debian/patches/60_percona_support.dpatch' --- a/storage/xtradb/build/debian/patches/60_percona_support.dpatch 2010-01-26 18:02:46 +0000 +++ b/storage/xtradb/build/debian/patches/60_percona_support.dpatch 2010-03-25 12:25:33 +0000 @@ -4,12 +4,13 @@ --- a/scripts/mysql_install_db.sh 2009-08-08 09:20:07.000000000 +0000 +++ b/scripts/mysql_install_db.sh 2009-08-08 09:29:23.000000000 +0000 -@@ -471,7 +471,7 @@ +@@ -469,6 +469,9 @@ + echo echo "Please report any problems with the $scriptdir/mysqlbug script!" echo - echo "The latest information about MySQL is available at http://www.mysql.com/" -- echo "Support MySQL by buying support/licenses from http://shop.mysql.com/" + echo "For commercial support please contact Percona at http://www.percona.com/contacts.html" - echo ++ echo ++ fi - + + exit 0 === modified file 'storage/xtradb/build/debian/rules' --- a/storage/xtradb/build/debian/rules 2010-02-18 23:51:40 +0000 +++ b/storage/xtradb/build/debian/rules 2010-03-29 15:30:32 +0000 @@ -20,7 +20,7 @@ DEB_NOEPOCH_VERSION ?= $(shell echo $(DE DEB_UPSTREAM_VERSION ?= $(shell echo $(DEB_NOEPOCH_VERSION) | sed 's/-[^-]*$$//') DEB_UPSTREAM_VERSION_MAJOR_MINOR := $(shell echo $(DEB_UPSTREAM_VERSION) | sed -r -n 's/^([0-9]+\.[0-9]+).*/\1/p') -DISTRIBUTION = $(shell echo "Percona SQL Server (GPL), XtraDB $(BB_PERCONA_VERSION), Revision $(BB_PERCONA_REVISION)") +DISTRIBUTION = $(shell echo "Percona SQL Server (GPL), XtraDB 10") MAKE_J = -j$(shell if [ -f /proc/cpuinfo ] ; then grep -c processor.* /proc/cpuinfo ; else echo 1 ; fi) ifeq (${MAKE_J}, -j0) === modified file 'storage/xtradb/build/percona-sql.spec' --- a/storage/xtradb/build/percona-sql.spec 2010-02-18 18:47:04 +0000 +++ b/storage/xtradb/build/percona-sql.spec 2010-04-09 05:18:19 +0000 @@ -13,10 +13,13 @@ # pluginversion - Version of InnoDB plugin taken as the basis, e.g. 1.0.3 # redhatversion - 5 or 4 # xtradbversion - The XtraDB release, eg. 6 -# gotrevision - bzr revision of the sources the package is built of %define mysql_vendor Percona, Inc -%{!?redhatversion:%define redhatversion 5} +%define redhatversion %(cat /etc/redhat-release | awk '{ print $3}' | awk -F. '{ print $1}') +%define community 1 +%define mysqlversion 5.1.45 +%define pluginversion 1.0.6 +%define xtradbversion 10 %define distribution rhel%{redhatversion} %define release %{xtradbversion}.%{distribution} @@ -106,8 +109,8 @@ %define server_suffix -51 %define package_suffix -51 -%define ndbug_comment Percona SQL Server (GPL), XtraDB %{xtradbversion}, Revision %{gotrevision} -%define debug_comment Percona SQL Server - Debug (GPL), XtraDB %{xtradbversion}, Revision %{gotrevision} +%define ndbug_comment Percona SQL Server (GPL), XtraDB %{xtradbversion} +%define debug_comment Percona SQL Server - Debug (GPL), XtraDB %{xtradbversion} %define commercial 0 %define YASSL_BUILD 1 %define EMBEDDED_BUILD 0 @@ -143,6 +146,7 @@ Patch04: microsec_process.patch Patch05: userstat.patch Patch06: optimizer_fix.patch Patch07: mysql-test_for_xtradb.diff +Patch08: show_temp_51.patch %define perconaxtradbplugin percona-xtradb-%{pluginversion}-%{xtradbversion}.tar.gz @@ -162,8 +166,8 @@ Source: %{src_dir}.tar.gz URL: http://www.percona.com/ Packager: %{mysql_vendor} MySQL Development Team <mysql-dev@percona.com> Vendor: %{mysql_vendor} -Provides: msqlormysql MySQL-server mysql Percona-XtraDB-server -BuildRequires: gperf perl readline-devel gcc-c++ ncurses-devel zlib-devel libtool automake autoconf time ccache +Provides: msqlormysql MySQL-server Percona-XtraDB-server +BuildRequires: gperf perl readline-devel gcc-c++ ncurses-devel zlib-devel libtool automake autoconf time ccache bison # Think about what you use here since the first step is to # run a rm -rf @@ -187,7 +191,7 @@ For more information visist our web site Summary: %{ndbug_comment} for Red Hat Enterprise Linux %{redhatversion} Group: Applications/Databases Requires: chkconfig coreutils shadow-utils grep procps -Provides: msqlormysql mysql-server mysql MySQL MySQL-server Percona-XtraDB-server +Provides: msqlormysql mysql-server MySQL-server Percona-XtraDB-server Obsoletes: MySQL mysql mysql-server MySQL-server MySQL-server-community MySQL-server-percona %description -n Percona-XtraDB-server%{package_suffix} @@ -214,7 +218,7 @@ package "Percona-XtraDB-client%{package_ Summary: Percona-XtraDB - Client Group: Applications/Databases Obsoletes: mysql-client MySQL-client MySQL-client-community MySQL-client-percona -Provides: mysql-client MySQL-client Percona-XtraDB-client +Provides: mysql-client MySQL-client Percona-XtraDB-client mysql MySQL %description -n Percona-XtraDB-client%{package_suffix} This package contains the standard Percona-XtraDB clients and administration tools. @@ -308,6 +312,7 @@ judgment as a high-performance consultin %patch05 -p1 %patch06 -p1 %patch07 -p1 +%patch08 -p1 if [ "%{redhatversion}" = "5" ] ; then tar xfz $RPM_SOURCE_DIR/%{perconaxtradbplugin} -C storage/innobase --strip-components=1 @@ -1018,6 +1023,10 @@ fi # merging BK trees) ############################################################################## %changelog +* Mon Mar 22 2010 Aleksandr Kuzminsky <aleksandr.kuzminsky@percona.com> + +XtraDB Release 10 + * Thu Feb 11 2010 Aleksandr Kuzminsky <aleksandr.kuzminsky@percona.com> Package name changed to Percona-XtraDB === modified file 'storage/xtradb/dict/dict0dict.c' --- a/storage/xtradb/dict/dict0dict.c 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/dict/dict0dict.c 2010-04-28 14:35:00 +0000 @@ -54,6 +54,7 @@ UNIV_INTERN dict_index_t* dict_ind_compa #include "row0merge.h" #include "m_ctype.h" /* my_isspace() */ #include "ha_prototypes.h" /* innobase_strcasecmp() */ +#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */ #include <ctype.h> @@ -658,7 +659,7 @@ dict_table_get( mutex_exit(&(dict_sys->mutex)); if (table != NULL) { - if (!table->stat_initialized) { + if (!table->stat_initialized && !table->is_corrupt) { /* If table->ibd_file_missing == TRUE, this will print an error message and return without doing anything. */ @@ -1181,7 +1182,7 @@ retry: + dict_sys->size) > srv_dict_size_limit ) { prev_table = UT_LIST_GET_PREV(table_LRU, table); - if (table == self || table->n_mysql_handles_opened) + if (table == self || table->n_mysql_handles_opened || table->is_corrupt) goto next_loop; cached_foreign_tables = 0; @@ -4219,6 +4220,11 @@ dict_update_statistics_low( } while (index) { + if (table->is_corrupt) { + ut_a(srv_pass_corrupt_table); + return; + } + size = btr_get_size(index, BTR_TOTAL_SIZE); index->stat_index_size = size; @@ -4920,4 +4926,42 @@ dict_close(void) mem_free(dict_sys); dict_sys = NULL; } + +/************************************************************************* +set is_corrupt flag by space_id*/ + +void +dict_table_set_corrupt_by_space( +/*============================*/ + ulint space_id, + ibool need_mutex) +{ + dict_table_t* table; + ibool found = FALSE; + + ut_a(space_id != 0 && space_id < SRV_LOG_SPACE_FIRST_ID); + + if (need_mutex) + mutex_enter(&(dict_sys->mutex)); + + table = UT_LIST_GET_FIRST(dict_sys->table_LRU); + + while (table) { + if (table->space == space_id) { + table->is_corrupt = TRUE; + found = TRUE; + } + + table = UT_LIST_GET_NEXT(table_LRU, table); + } + + if (need_mutex) + mutex_exit(&(dict_sys->mutex)); + + if (!found) { + fprintf(stderr, "InnoDB: space to be marked as " + "crashed was not found for id %lu.\n", + (ulong) space_id); + } +} #endif /* !UNIV_HOTBACKUP */ === modified file 'storage/xtradb/dict/dict0mem.c' --- a/storage/xtradb/dict/dict0mem.c 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/dict/dict0mem.c 2010-03-22 20:42:52 +0000 @@ -85,6 +85,8 @@ dict_mem_table_create( /* The number of transactions that are either waiting on the AUTOINC lock or have been granted the lock. */ table->n_waiting_or_granted_auto_inc_locks = 0; + + table->is_corrupt = FALSE; #endif /* !UNIV_HOTBACKUP */ ut_d(table->magic_n = DICT_TABLE_MAGIC_N); === modified file 'storage/xtradb/fil/fil0fil.c' --- a/storage/xtradb/fil/fil0fil.c 2010-03-28 18:10:00 +0000 +++ b/storage/xtradb/fil/fil0fil.c 2010-04-28 14:35:00 +0000 @@ -222,6 +222,7 @@ struct fil_space_struct { file we have written to */ ibool is_in_unflushed_spaces; /*!< TRUE if this space is currently in unflushed_spaces */ + ibool is_corrupt; UT_LIST_NODE_T(fil_space_t) space_list; /*!< list of all spaces */ ulint magic_n;/*!< FIL_SPACE_MAGIC_N */ @@ -1222,6 +1223,8 @@ try_again: ut_fold_string(name), space); space->is_in_unflushed_spaces = FALSE; + space->is_corrupt = FALSE; + UT_LIST_ADD_LAST(space_list, fil_system->space_list, space); mutex_exit(&fil_system->mutex); @@ -3044,7 +3047,9 @@ fil_open_single_table_tablespace( mach_write_ull(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn); mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, srv_use_checksums - ? buf_calc_page_new_checksum(page) + ? (!srv_fast_checksum + ? buf_calc_page_new_checksum(page) + : buf_calc_page_new_checksum_32(page)) : BUF_NO_CHECKSUM_MAGIC); mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, srv_use_checksums @@ -3156,7 +3161,8 @@ skip_info: goto skip_write; } - if (checksum_field != 0 + if (!srv_fast_checksum + && checksum_field != 0 && checksum_field != BUF_NO_CHECKSUM_MAGIC && checksum_field != buf_calc_page_new_checksum(page)) { @@ -3164,6 +3170,17 @@ skip_info: goto skip_write; } + if (srv_fast_checksum + && checksum_field != 0 + && checksum_field != BUF_NO_CHECKSUM_MAGIC + && checksum_field + != buf_calc_page_new_checksum_32(page) + && checksum_field + != buf_calc_page_new_checksum(page)) { + + goto skip_write; + } + if (mach_read_from_4(page + FIL_PAGE_OFFSET) || !offset) { mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id); @@ -3238,7 +3255,9 @@ skip_info: mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, srv_use_checksums - ? buf_calc_page_new_checksum(page) + ? (!srv_fast_checksum + ? buf_calc_page_new_checksum(page) + : buf_calc_page_new_checksum_32(page)) : BUF_NO_CHECKSUM_MAGIC); mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, srv_use_checksums @@ -4577,9 +4596,9 @@ _fil_io( ut_ad(ut_is_2pow(zip_size)); ut_ad(buf); ut_ad(len > 0); -#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE -# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE" -#endif +//#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE +//# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE" +//#endif ut_ad(fil_validate()); #ifndef UNIV_HOTBACKUP # ifndef UNIV_LOG_DEBUG @@ -4713,6 +4732,22 @@ _fil_io( ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0); + if (srv_pass_corrupt_table && space->is_corrupt) { + /* should ignore i/o for the crashed space */ + mutex_enter(&fil_system->mutex); + fil_node_complete_io(node, fil_system, type); + mutex_exit(&fil_system->mutex); + if (mode == OS_AIO_NORMAL) { + ut_a(space->purpose == FIL_TABLESPACE); + buf_page_io_complete(message, trx); + } + if (type == OS_FILE_READ) { + return(DB_TABLESPACE_DELETED); + } else { + return(DB_SUCCESS); + } + } else { + ut_a(!space->is_corrupt); #ifdef UNIV_HOTBACKUP /* In ibbackup do normal i/o, not aio */ if (type == OS_FILE_READ) { @@ -4727,6 +4762,8 @@ _fil_io( ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, offset_low, offset_high, len, node, message, trx); #endif + } /**/ + ut_a(ret); if (mode == OS_AIO_SYNC) { @@ -4873,7 +4910,7 @@ fil_aio_wait( if (fil_node->space->purpose == FIL_TABLESPACE) { srv_set_io_thread_op_info(segment, "complete io for buf page"); - buf_page_io_complete(message); + buf_page_io_complete(message, NULL); } else { srv_set_io_thread_op_info(segment, "complete io for log"); log_io_complete(message); @@ -5225,3 +5262,46 @@ fil_system_hash_nodes(void) return 0; } } + +/************************************************************************* +functions to access is_corrupt flag of fil_space_t*/ + +ibool +fil_space_is_corrupt( +/*=================*/ + ulint space_id) +{ + fil_space_t* space; + ibool ret = FALSE; + + mutex_enter(&fil_system->mutex); + + space = fil_space_get_by_id(space_id); + + if (space && space->is_corrupt) { + ret = TRUE; + } + + mutex_exit(&fil_system->mutex); + + return(ret); +} + +void +fil_space_set_corrupt( +/*==================*/ + ulint space_id) +{ + fil_space_t* space; + + mutex_enter(&fil_system->mutex); + + space = fil_space_get_by_id(space_id); + + if (space) { + space->is_corrupt = TRUE; + } + + mutex_exit(&fil_system->mutex); +} + === modified file 'storage/xtradb/fsp/fsp0fsp.c' --- a/storage/xtradb/fsp/fsp0fsp.c 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/fsp/fsp0fsp.c 2010-03-22 20:42:52 +0000 @@ -370,6 +370,12 @@ fsp_get_space_header( ut_ad(id || !zip_size); block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr); + + if (srv_pass_corrupt_table && !block) { + return(0); + } + ut_a(block); + header = FSP_HEADER_OFFSET + buf_block_get_frame(block); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -652,15 +658,16 @@ xdes_calc_descriptor_page( ulint offset) /*!< in: page offset */ { #ifndef DOXYGEN /* Doxygen gets confused of these */ -# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \ - + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE -# error -# endif +//# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \ +// + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE +//# error +//# endif # if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \ + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE # error # endif #endif /* !DOXYGEN */ + ut_a(UNIV_PAGE_SIZE > XDES_ARR_OFFSET + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE); ut_ad(ut_is_2pow(zip_size)); if (!zip_size) { @@ -788,6 +795,12 @@ xdes_get_descriptor( fsp_header_t* sp_header; block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr); + + if (srv_pass_corrupt_table && !block) { + return(0); + } + ut_a(block); + buf_block_dbg_add_level(block, SYNC_FSP_PAGE); sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block); @@ -1457,12 +1470,12 @@ fsp_fill_free_list( mtr); xdes_init(descr, mtr); -#if UNIV_PAGE_SIZE % FSP_EXTENT_SIZE -# error "UNIV_PAGE_SIZE % FSP_EXTENT_SIZE != 0" -#endif -#if PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE -# error "PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE != 0" -#endif +//#if UNIV_PAGE_SIZE % FSP_EXTENT_SIZE +//# error "UNIV_PAGE_SIZE % FSP_EXTENT_SIZE != 0" +//#endif +//#if PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE +//# error "PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE != 0" +//#endif if (UNIV_UNLIKELY(init_xdes)) { @@ -1871,6 +1884,11 @@ fsp_seg_inode_page_find_free( { fseg_inode_t* inode; + if (srv_pass_corrupt_table && !page) { + return(ULINT_UNDEFINED); + } + ut_a(page); + for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) { inode = fsp_seg_inode_page_get_nth_inode( @@ -1984,6 +2002,11 @@ fsp_alloc_seg_inode( page = buf_block_get_frame(block); + if (srv_pass_corrupt_table && !page) { + return(0); + } + ut_a(page); + n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr); ut_a(n != ULINT_UNDEFINED); @@ -2077,6 +2100,11 @@ fseg_inode_try_get( inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr); + if (srv_pass_corrupt_table && !inode) { + return(0); + } + ut_a(inode); + if (UNIV_UNLIKELY (ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID)))) { @@ -2104,7 +2132,7 @@ fseg_inode_get( { fseg_inode_t* inode = fseg_inode_try_get(header, space, zip_size, mtr); - ut_a(inode); + ut_a(srv_pass_corrupt_table || inode); return(inode); } @@ -3263,6 +3291,11 @@ fseg_free_page_low( descr = xdes_get_descriptor(space, zip_size, page, mtr); + if (srv_pass_corrupt_table && !descr) { + /* The page may be corrupt. pass it. */ + return; + } + ut_a(descr); if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) { fputs("InnoDB: Dump of the tablespace extent descriptor: ", @@ -3515,6 +3548,11 @@ fseg_free_step( descr = xdes_get_descriptor(space, zip_size, header_page, mtr); + if (srv_pass_corrupt_table && !descr) { + /* The page may be corrupt. pass it. */ + return(TRUE); + } + /* Check that the header resides on a page which has not been freed yet */ @@ -3599,6 +3637,12 @@ fseg_free_step_not_header( inode = fseg_inode_get(header, space, zip_size, mtr); + if (srv_pass_corrupt_table && !inode) { + /* ignore the corruption */ + return(TRUE); + } + ut_a(inode); + descr = fseg_get_first_extent(inode, space, zip_size, mtr); if (descr != NULL) { === modified file 'storage/xtradb/handler/ha_innodb.cc' --- a/storage/xtradb/handler/ha_innodb.cc 2010-04-28 13:53:04 +0000 +++ b/storage/xtradb/handler/ha_innodb.cc 2010-04-28 14:35:00 +0000 @@ -167,6 +167,8 @@ static ulong innobase_commit_concurrency static ulong innobase_read_io_threads; static ulong innobase_write_io_threads; +static ulong innobase_page_size; + static my_bool innobase_thread_concurrency_timer_based; static long long innobase_buffer_pool_size, innobase_log_file_size; @@ -200,6 +202,7 @@ static char* innobase_log_arch_dir = N #endif /* UNIV_LOG_ARCHIVE */ static my_bool innobase_use_doublewrite = TRUE; static my_bool innobase_use_checksums = TRUE; +static my_bool innobase_fast_checksum = FALSE; static my_bool innobase_extra_undoslots = FALSE; static my_bool innobase_fast_recovery = FALSE; static my_bool innobase_recovery_stats = TRUE; @@ -2030,6 +2033,36 @@ innobase_init( } #endif /* UNIV_DEBUG */ + srv_page_size = 0; + srv_page_size_shift = 0; + + if (innobase_page_size != (1 << 14)) { + int n_shift; + + fprintf(stderr, + "InnoDB: Warning: innodb_page_size has been changed from default value 16384. (###EXPERIMENTAL### operation)\n"); + for (n_shift = 12; n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX; n_shift++) { + if (innobase_page_size == (1 << n_shift)) { + srv_page_size_shift = n_shift; + srv_page_size = (1 << srv_page_size_shift); + fprintf(stderr, + "InnoDB: The universal page size of the database is set to %lu.\n", + srv_page_size); + break; + } + } + } else { + srv_page_size_shift = 14; + srv_page_size = (1 << srv_page_size_shift); + } + + if (!srv_page_size_shift) { + fprintf(stderr, + "InnoDB: Error: %lu is not valid value for innodb_page_size.\n", + innobase_page_size); + goto error; + } + #ifndef MYSQL_SERVER innodb_overwrite_relay_log_info = FALSE; #endif @@ -2338,6 +2371,7 @@ innobase_change_buffering_inited_ok: srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; srv_use_checksums = (ibool) innobase_use_checksums; + srv_fast_checksum = (ibool) innobase_fast_checksum; #ifdef HAVE_LARGE_PAGES if ((os_use_large_pages = (ibool) my_use_large_pages)) @@ -3348,6 +3382,12 @@ ha_innobase::open( DBUG_RETURN(1); } + if (share->ib_table && share->ib_table->is_corrupt) { + free_share(share); + + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + } + /* Create buffers for packing the fields of a record. Why table->reclength did not work here? Obviously, because char fields when packed actually became 1 byte longer, when we also @@ -3375,6 +3415,19 @@ retry: /* Get pointer to a table object in InnoDB dictionary cache */ ib_table = dict_table_get(norm_name, TRUE); + if (ib_table && ib_table->is_corrupt) { + free_share(share); + my_free(upd_buff, MYF(0)); + + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + } + + if (share->ib_table) { + ut_a(share->ib_table == ib_table); + } else { + share->ib_table = ib_table; + } + if (NULL == ib_table) { if (is_part && retries < 10) { ++retries; @@ -4541,6 +4594,10 @@ ha_innobase::write_row( ha_statistic_increment(&SSV::ha_write_count); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); @@ -4653,6 +4710,10 @@ no_commit: error = row_insert_for_mysql((byte*) record, prebuilt); +#ifdef EXTENDED_FOR_USERSTAT + if (error == DB_SUCCESS) rows_changed++; +#endif + /* Handle duplicate key errors */ if (auto_inc_used) { ulint err; @@ -4748,6 +4809,10 @@ report_error: func_exit: innobase_active_small(); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + DBUG_RETURN(error_result); } @@ -4924,6 +4989,10 @@ ha_innobase::update_row( ha_statistic_increment(&SSV::ha_update_count); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); @@ -4989,6 +5058,10 @@ ha_innobase::update_row( } } +#ifdef EXTENDED_FOR_USERSTAT + if (error == DB_SUCCESS) rows_changed++; +#endif + innodb_srv_conc_exit_innodb(trx); error = convert_error_code_to_mysql(error, @@ -5009,6 +5082,10 @@ ha_innobase::update_row( innobase_active_small(); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + DBUG_RETURN(error); } @@ -5030,6 +5107,10 @@ ha_innobase::delete_row( ha_statistic_increment(&SSV::ha_delete_count); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + if (!prebuilt->upd_node) { row_get_prebuilt_update_vector(prebuilt); } @@ -5042,6 +5123,10 @@ ha_innobase::delete_row( error = row_update_for_mysql((byte*) record, prebuilt); +#ifdef EXTENDED_FOR_USERSTAT + if (error == DB_SUCCESS) rows_changed++; +#endif + innodb_srv_conc_exit_innodb(trx); error = convert_error_code_to_mysql( @@ -5052,6 +5137,10 @@ ha_innobase::delete_row( innobase_active_small(); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + DBUG_RETURN(error); } @@ -5291,6 +5380,10 @@ ha_innobase::index_read( ha_statistic_increment(&SSV::ha_read_key_count); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + index = prebuilt->index; if (UNIV_UNLIKELY(index == NULL)) { @@ -5353,6 +5446,10 @@ ha_innobase::index_read( ret = DB_UNSUPPORTED; } + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + switch (ret) { case DB_SUCCESS: error = 0; @@ -5447,6 +5544,10 @@ ha_innobase::change_active_index( { DBUG_ENTER("change_active_index"); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + ut_ad(user_thd == ha_thd()); ut_a(prebuilt->trx == thd_to_trx(user_thd)); @@ -5538,6 +5639,10 @@ ha_innobase::general_fetch( DBUG_ENTER("general_fetch"); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + ut_a(prebuilt->trx == thd_to_trx(user_thd)); innodb_srv_conc_enter_innodb(prebuilt->trx); @@ -5547,10 +5652,19 @@ ha_innobase::general_fetch( innodb_srv_conc_exit_innodb(prebuilt->trx); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + switch (ret) { case DB_SUCCESS: error = 0; table->status = 0; +#ifdef EXTENDED_FOR_USERSTAT + rows_read++; + if (active_index >= 0 && active_index < MAX_KEY) + index_rows_read[active_index]++; +#endif break; case DB_RECORD_NOT_FOUND: error = HA_ERR_END_OF_FILE; @@ -6506,9 +6620,9 @@ ha_innobase::create( | DICT_TF_COMPACT | DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT; -#if DICT_TF_ZSSIZE_MAX < 1 -# error "DICT_TF_ZSSIZE_MAX < 1" -#endif +//#if DICT_TF_ZSSIZE_MAX < 1 +//# error "DICT_TF_ZSSIZE_MAX < 1" +//#endif } } @@ -6768,6 +6882,10 @@ ha_innobase::delete_all_rows(void) DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND); } + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + /* Truncate the table in InnoDB */ error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx); @@ -6776,6 +6894,10 @@ ha_innobase::delete_all_rows(void) goto fallback; } + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + error = convert_error_code_to_mysql(error, prebuilt->table->flags, NULL); @@ -7279,6 +7401,16 @@ ha_innobase::read_time( return(ranges + (double) rows / (double) total_rows * time_for_scan); } +UNIV_INTERN +bool +ha_innobase::is_corrupt() const +{ + if (share->ib_table) + return ((bool)share->ib_table->is_corrupt); + else + return (FALSE); +} + /*********************************************************************//** Returns statistics information of the table to the MySQL interpreter, in various fields of the handle object. */ @@ -7329,9 +7461,9 @@ ha_innobase::info( ib_table = prebuilt->table; if (flag & HA_STATUS_TIME) { - if (innobase_stats_on_metadata - && (thd_sql_command(user_thd) == SQLCOM_ANALYZE - || srv_stats_auto_update)) { + if ((innobase_stats_on_metadata + || thd_sql_command(user_thd) == SQLCOM_ANALYZE) + && !share->ib_table->is_corrupt) { /* In sql_show we call with this flag: update then statistics so that they are up-to-date */ @@ -7558,6 +7690,10 @@ ha_innobase::analyze( THD* thd, /*!< in: connection thread handle */ HA_CHECK_OPT* check_opt) /*!< in: currently ignored */ { + if (share->ib_table->is_corrupt) { + return(HA_ADMIN_CORRUPT); + } + /* Serialize ANALYZE TABLE inside InnoDB, see Bug#38996 Race condition in ANALYZE TABLE */ pthread_mutex_lock(&analyze_mutex); @@ -7567,6 +7703,10 @@ ha_innobase::analyze( pthread_mutex_unlock(&analyze_mutex); + if (share->ib_table->is_corrupt) { + return(HA_ADMIN_CORRUPT); + } + return(0); } @@ -7612,6 +7752,10 @@ ha_innobase::check( ret = row_check_table_for_mysql(prebuilt); + if (ret != DB_INTERRUPTED && share->ib_table->is_corrupt) { + return(HA_ADMIN_CORRUPT); + } + switch (ret) { case DB_SUCCESS: return(HA_ADMIN_OK); @@ -8345,6 +8489,10 @@ ha_innobase::transactional_table_lock( update_thd(thd); + if (share->ib_table->is_corrupt) { + DBUG_RETURN(HA_ERR_CRASHED); + } + if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) { ut_print_timestamp(stderr); fprintf(stderr, @@ -10209,6 +10357,20 @@ static MYSQL_SYSVAR_BOOL(checksums, inno "Disable with --skip-innodb-checksums.", NULL, NULL, TRUE); +static MYSQL_SYSVAR_BOOL(fast_checksum, innobase_fast_checksum, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Change the algorithm of checksum for the whole of datapage to 4-bytes word based. " + "The original checksum is checked after the new one. It may be slow for reading page" + " which has orginal checksum. Overwrite the page or recreate the InnoDB database, " + "if you want the entire benefit for performance at once. " + "#### Attention: The checksum is not compatible for normal or disabled version! ####", + NULL, NULL, FALSE); + +static MYSQL_SYSVAR_ULONG(page_size, innobase_page_size, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "###EXPERIMENTAL###: The universal page size of the database. Changing for created database is not supported. Use on your own risk!", + NULL, NULL, (1 << 14), (1 << 12), (1 << UNIV_PAGE_SIZE_SHIFT_MAX), 0); + static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir, PLUGIN_VAR_READONLY, "The common part for InnoDB table spaces.", @@ -10665,11 +10827,21 @@ static MYSQL_SYSVAR_ULONG(relax_table_cr "Relax limitation of column size at table creation as builtin InnoDB.", NULL, NULL, 0, 0, 1, 0); +static MYSQL_SYSVAR_ULONG(pass_corrupt_table, srv_pass_corrupt_table, + PLUGIN_VAR_RQCMDARG, + "Pass corruptions of user tables as 'corrupt table' instead of not crashing itself, " + "when used with file_per_table. " + "All file io for the datafile after detected as corrupt are disabled, " + "except for the deletion.", + NULL, NULL, 0, 0, 1, 0); + static struct st_mysql_sys_var* innobase_system_variables[]= { + MYSQL_SYSVAR(page_size), MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), MYSQL_SYSVAR(buffer_pool_size), MYSQL_SYSVAR(checksums), + MYSQL_SYSVAR(fast_checksum), MYSQL_SYSVAR(commit_concurrency), MYSQL_SYSVAR(concurrency_tickets), MYSQL_SYSVAR(data_file_path), @@ -10744,6 +10916,7 @@ static struct st_mysql_sys_var* innobase MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(use_purge_thread), MYSQL_SYSVAR(relax_table_creation), + MYSQL_SYSVAR(pass_corrupt_table), NULL }; @@ -10776,6 +10949,8 @@ i_s_innodb_cmpmem_reset, i_s_innodb_table_stats, i_s_innodb_index_stats, i_s_innodb_admin_command, +i_s_innodb_sys_tables, +i_s_innodb_sys_indexes, i_s_innodb_patches mysql_declare_plugin_end; === modified file 'storage/xtradb/handler/ha_innodb.h' --- a/storage/xtradb/handler/ha_innodb.h 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/handler/ha_innodb.h 2010-04-28 14:35:00 +0000 @@ -36,6 +36,7 @@ typedef struct st_innobase_share { incremented in get_share() and decremented in free_share() */ void* table_name_hash;/*!< hash table chain node */ + dict_table_t* ib_table; } INNOBASE_SHARE; @@ -119,6 +120,7 @@ class ha_innobase: public handler int close(void); double scan_time(); double read_time(uint index, uint ranges, ha_rows rows); + bool is_corrupt() const; int write_row(uchar * buf); int update_row(const uchar * old_data, uchar * new_data); === modified file 'storage/xtradb/handler/i_s.cc' --- a/storage/xtradb/handler/i_s.cc 2010-03-31 20:50:54 +0000 +++ b/storage/xtradb/handler/i_s.cc 2010-04-28 14:35:00 +0000 @@ -47,6 +47,7 @@ extern "C" { #include "trx0rseg.h" /* for trx_rseg_struct */ #include "trx0sys.h" /* for trx_sys */ #include "dict0dict.h" /* for dict_sys */ +#include "btr0pcur.h" #include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */ /* from buf0buf.c */ struct buf_chunk_struct{ @@ -807,7 +808,7 @@ i_s_innodb_buffer_pool_pages_index_fill( p++; } else { field_store_string(table->field[0], NULL); - p = (char *)index->table_name; + p = index->table_name; } strcpy(table_name_raw, (const char*)p); filename_to_tablename(table_name_raw, table_name, sizeof(table_name)); @@ -2664,6 +2665,14 @@ UNIV_INTERN struct st_mysql_plugin i_s_i */ static ST_FIELD_INFO i_s_innodb_table_stats_info[] = { + {STRUCT_FLD(field_name, "table_schema"), + STRUCT_FLD(field_length, NAME_LEN), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + {STRUCT_FLD(field_name, "table_name"), STRUCT_FLD(field_length, NAME_LEN), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -2709,6 +2718,14 @@ static ST_FIELD_INFO i_s_innodb_table_st static ST_FIELD_INFO i_s_innodb_index_stats_info[] = { + {STRUCT_FLD(field_name, "table_schema"), + STRUCT_FLD(field_length, NAME_LEN), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + {STRUCT_FLD(field_name, "table_name"), STRUCT_FLD(field_length, NAME_LEN), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -2784,16 +2801,30 @@ i_s_innodb_table_stats_fill( table = UT_LIST_GET_FIRST(dict_sys->table_LRU); while (table) { + char buf[NAME_LEN * 2 + 2]; + char* ptr; + if (table->stat_clustered_index_size == 0) { table = UT_LIST_GET_NEXT(table_LRU, table); continue; } - field_store_string(i_s_table->field[0], table->name); - i_s_table->field[1]->store(table->stat_n_rows); - i_s_table->field[2]->store(table->stat_clustered_index_size); - i_s_table->field[3]->store(table->stat_sum_of_other_index_sizes); - i_s_table->field[4]->store(table->stat_modified_counter); + buf[NAME_LEN * 2 + 1] = 0; + strncpy(buf, table->name, NAME_LEN * 2 + 1); + ptr = strchr(buf, '/'); + if (ptr) { + *ptr = '\0'; + ++ptr; + } else { + ptr = buf; + } + + field_store_string(i_s_table->field[0], buf); + field_store_string(i_s_table->field[1], ptr); + i_s_table->field[2]->store(table->stat_n_rows); + i_s_table->field[3]->store(table->stat_clustered_index_size); + i_s_table->field[4]->store(table->stat_sum_of_other_index_sizes); + i_s_table->field[5]->store(table->stat_modified_counter); if (schema_table_store_record(thd, i_s_table)) { status = 1; @@ -2849,11 +2880,24 @@ i_s_innodb_index_stats_fill( while (index) { char buff[256+1]; char row_per_keys[256+1]; + char buf[NAME_LEN * 2 + 2]; + char* ptr; ulint i; - field_store_string(i_s_table->field[0], table->name); - field_store_string(i_s_table->field[1], index->name); - i_s_table->field[2]->store(index->n_uniq); + buf[NAME_LEN * 2 + 1] = 0; + strncpy(buf, table->name, NAME_LEN * 2 + 1); + ptr = strchr(buf, '/'); + if (ptr) { + *ptr = '\0'; + ++ptr; + } else { + ptr = buf; + } + + field_store_string(i_s_table->field[0], buf); + field_store_string(i_s_table->field[1], ptr); + field_store_string(i_s_table->field[2], index->name); + i_s_table->field[3]->store(index->n_uniq); row_per_keys[0] = '\0'; if (index->stat_n_diff_key_vals) { @@ -2869,10 +2913,10 @@ i_s_innodb_index_stats_fill( strncat(row_per_keys, buff, 256 - strlen(row_per_keys)); } } - field_store_string(i_s_table->field[3], row_per_keys); + field_store_string(i_s_table->field[4], row_per_keys); - i_s_table->field[4]->store(index->stat_index_size); - i_s_table->field[5]->store(index->stat_n_leaf_pages); + i_s_table->field[5]->store(index->stat_index_size); + i_s_table->field[6]->store(index->stat_n_leaf_pages); if (schema_table_store_record(thd, i_s_table)) { status = 1; @@ -3121,3 +3165,505 @@ UNIV_INTERN struct st_mysql_plugin i_s_i STRUCT_FLD(system_vars, NULL), STRUCT_FLD(__reserved1, NULL) }; + +static ST_FIELD_INFO i_s_innodb_sys_tables_info[] = +{ + {STRUCT_FLD(field_name, "NAME"), + STRUCT_FLD(field_length, NAME_LEN), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "N_COLS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "MIX_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "MIX_LEN"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "CLUSTER_NAME"), + STRUCT_FLD(field_length, NAME_LEN), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +static ST_FIELD_INFO i_s_innodb_sys_indexes_info[] = +{ + {STRUCT_FLD(field_name, "TABLE_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "NAME"), + STRUCT_FLD(field_length, NAME_LEN), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "N_FIELDS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + {STRUCT_FLD(field_name, "PAGE_NO"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +static +int +copy_string_field( +/*==============*/ + TABLE* table, + int table_field, + const rec_t* rec, + int rec_field) +{ + int status; + const byte* data; + ulint len; + + /*fprintf(stderr, "copy_string_field %d %d\n", table_field, rec_field);*/ + + data = rec_get_nth_field_old(rec, rec_field, &len); + if (len == UNIV_SQL_NULL) { + table->field[table_field]->set_null(); + status = 0; /* success */ + } else { + table->field[table_field]->set_notnull(); + status = table->field[table_field]->store( + (char *) data, len, system_charset_info); + } + + return status; +} + +static +int +copy_int_field( +/*===========*/ + TABLE* table, + int table_field, + const rec_t* rec, + int rec_field) +{ + int status; + const byte* data; + ulint len; + + /*fprintf(stderr, "copy_int_field %d %d\n", table_field, rec_field);*/ + + data = rec_get_nth_field_old(rec, rec_field, &len); + if (len == UNIV_SQL_NULL) { + table->field[table_field]->set_null(); + status = 0; /* success */ + } else { + table->field[table_field]->set_notnull(); + status = table->field[table_field]->store( + mach_read_from_4(data), true); + } + + return status; +} + +static +int +copy_id_field( +/*==========*/ + TABLE* table, + int table_field, + const rec_t* rec, + int rec_field) +{ + int status; + const byte* data; + ulint len; + + /*fprintf(stderr, "copy_id_field %d %d\n", table_field, rec_field);*/ + + data = rec_get_nth_field_old(rec, rec_field, &len); + if (len == UNIV_SQL_NULL) { + table->field[table_field]->set_null(); + status = 0; /* success */ + } else { + table->field[table_field]->set_notnull(); + status = table->field[table_field]->store( + ut_conv_dulint_to_longlong(mach_read_from_8(data)), true); + } + + return status; +} + +static +int +copy_sys_tables_rec( +/*================*/ + TABLE* table, + const dict_index_t* index, + const rec_t* rec +) +{ + int status; + int field; + + /* NAME */ + field = dict_index_get_nth_col_pos(index, 0); + status = copy_string_field(table, 0, rec, field); + if (status) { + return status; + } + /* ID */ + field = dict_index_get_nth_col_pos(index, 1); + status = copy_id_field(table, 1, rec, field); + if (status) { + return status; + } + /* N_COLS */ + field = dict_index_get_nth_col_pos(index, 2); + status = copy_int_field(table, 2, rec, field); + if (status) { + return status; + } + /* TYPE */ + field = dict_index_get_nth_col_pos(index, 3); + status = copy_int_field(table, 3, rec, field); + if (status) { + return status; + } + /* MIX_ID */ + field = dict_index_get_nth_col_pos(index, 4); + status = copy_id_field(table, 4, rec, field); + if (status) { + return status; + } + /* MIX_LEN */ + field = dict_index_get_nth_col_pos(index, 5); + status = copy_int_field(table, 5, rec, field); + if (status) { + return status; + } + /* CLUSTER_NAME */ + field = dict_index_get_nth_col_pos(index, 6); + status = copy_string_field(table, 6, rec, field); + if (status) { + return status; + } + /* SPACE */ + field = dict_index_get_nth_col_pos(index, 7); + status = copy_int_field(table, 7, rec, field); + if (status) { + return status; + } + + return 0; +} + +static +int +copy_sys_indexes_rec( +/*=================*/ + TABLE* table, + const dict_index_t* index, + const rec_t* rec +) +{ + int status; + int field; + + /* TABLE_ID */ + field = dict_index_get_nth_col_pos(index, 0); + status = copy_id_field(table, 0, rec, field); + if (status) { + return status; + } + /* ID */ + field = dict_index_get_nth_col_pos(index, 1); + status = copy_id_field(table, 1, rec, field); + if (status) { + return status; + } + /* NAME */ + field = dict_index_get_nth_col_pos(index, 2); + status = copy_string_field(table, 2, rec, field); + if (status) { + return status; + } + /* N_FIELDS */ + field = dict_index_get_nth_col_pos(index, 3); + status = copy_int_field(table, 3, rec, field); + if (status) { + return status; + } + /* TYPE */ + field = dict_index_get_nth_col_pos(index, 4); + status = copy_int_field(table, 4, rec, field); + if (status) { + return status; + } + /* SPACE */ + field = dict_index_get_nth_col_pos(index, 5); + status = copy_int_field(table, 5, rec, field); + if (status) { + return status; + } + /* PAGE_NO */ + field = dict_index_get_nth_col_pos(index, 6); + status = copy_int_field(table, 6, rec, field); + if (status) { + return status; + } + + return 0; +} + +static +int +i_s_innodb_schema_table_fill( +/*=========================*/ + THD* thd, + TABLE_LIST* tables, + COND* cond) +{ + int status = 0; + TABLE* table = (TABLE *) tables->table; + const char* table_name = tables->schema_table_name; + dict_table_t* innodb_table; + dict_index_t* index; + btr_pcur_t pcur; + const rec_t* rec; + mtr_t mtr; + int id; + + DBUG_ENTER("i_s_innodb_schema_table_fill"); + + /* deny access to non-superusers */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + if (innobase_strcasecmp(table_name, "innodb_sys_tables") == 0) { + id = 0; + } else if (innobase_strcasecmp(table_name, "innodb_sys_indexes") == 0) { + id = 1; + } else { + DBUG_RETURN(1); + } + + + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); + + mutex_enter(&(dict_sys->mutex)); + + mtr_start(&mtr); + + if (id == 0) { + innodb_table = dict_table_get_low("SYS_TABLES"); + } else { + innodb_table = dict_table_get_low("SYS_INDEXES"); + } + index = UT_LIST_GET_FIRST(innodb_table->indexes); + + btr_pcur_open_at_index_side(TRUE, index, BTR_SEARCH_LEAF, &pcur, + TRUE, &mtr); + for (;;) { + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + + rec = btr_pcur_get_rec(&pcur); + if (!btr_pcur_is_on_user_rec(&pcur)) { + /* end of index */ + btr_pcur_close(&pcur); + mtr_commit(&mtr); + break; + } + if (rec_get_deleted_flag(rec, 0)) { + /* record marked as deleted */ + btr_pcur_close(&pcur); + mtr_commit(&mtr); + continue; + } + + if (id == 0) { + status = copy_sys_tables_rec(table, index, rec); + } else { + status = copy_sys_indexes_rec(table, index, rec); + } + if (status) { + btr_pcur_close(&pcur); + mtr_commit(&mtr); + break; + } + +#if 0 + btr_pcur_store_position(&pcur, &mtr); + mtr_commit(&mtr); + + status = schema_table_store_record(thd, table); + if (status) { + btr_pcur_close(&pcur); + break; + } + + mtr_start(&mtr); + btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr); +#else + status = schema_table_store_record(thd, table); + if (status) { + btr_pcur_close(&pcur); + mtr_commit(&mtr); + break; + } +#endif + } + + mutex_exit(&(dict_sys->mutex)); + + DBUG_RETURN(status); +} + +static +int +i_s_innodb_sys_tables_init( +/*=======================*/ + void* p) +{ + DBUG_ENTER("i_s_innodb_sys_tables_init"); + ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p; + + schema->fields_info = i_s_innodb_sys_tables_info; + schema->fill_table = i_s_innodb_schema_table_fill; + + DBUG_RETURN(0); +} + +static +int +i_s_innodb_sys_indexes_init( +/*========================*/ + void* p) +{ + DBUG_ENTER("i_s_innodb_sys_indexes_init"); + ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p; + + schema->fields_info = i_s_innodb_sys_indexes_info; + schema->fill_table = i_s_innodb_schema_table_fill; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables = +{ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + STRUCT_FLD(info, &i_s_info), + STRUCT_FLD(name, "INNODB_SYS_TABLES"), + STRUCT_FLD(author, plugin_author), + STRUCT_FLD(descr, "InnoDB SYS_TABLES table"), + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + STRUCT_FLD(init, i_s_innodb_sys_tables_init), + STRUCT_FLD(deinit, i_s_common_deinit), + STRUCT_FLD(version, 0x0100 /* 1.0 */), + STRUCT_FLD(status_vars, NULL), + STRUCT_FLD(system_vars, NULL), + STRUCT_FLD(__reserved1, NULL) +}; + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes = +{ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + STRUCT_FLD(info, &i_s_info), + STRUCT_FLD(name, "INNODB_SYS_INDEXES"), + STRUCT_FLD(author, plugin_author), + STRUCT_FLD(descr, "InnoDB SYS_INDEXES table"), + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + STRUCT_FLD(init, i_s_innodb_sys_indexes_init), + STRUCT_FLD(deinit, i_s_common_deinit), + STRUCT_FLD(version, 0x0100 /* 1.0 */), + STRUCT_FLD(status_vars, NULL), + STRUCT_FLD(system_vars, NULL), + STRUCT_FLD(__reserved1, NULL) +}; === modified file 'storage/xtradb/handler/i_s.h' --- a/storage/xtradb/handler/i_s.h 2009-11-04 20:11:12 +0000 +++ b/storage/xtradb/handler/i_s.h 2010-03-22 20:42:52 +0000 @@ -41,5 +41,7 @@ extern struct st_mysql_plugin i_s_innodb extern struct st_mysql_plugin i_s_innodb_table_stats; extern struct st_mysql_plugin i_s_innodb_index_stats; extern struct st_mysql_plugin i_s_innodb_admin_command; +extern struct st_mysql_plugin i_s_innodb_sys_tables; +extern struct st_mysql_plugin i_s_innodb_sys_indexes; #endif /* i_s_h */ === modified file 'storage/xtradb/handler/innodb_patch_info.h' --- a/storage/xtradb/handler/innodb_patch_info.h 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/handler/innodb_patch_info.h 2010-04-28 14:35:00 +0000 @@ -43,5 +43,9 @@ struct innodb_enhancement { {"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_relax_table_creation","Relax limitation of column size at table creation as builtin InnoDB.","","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_pass_corrupt_table","Treat tables as corrupt instead of crash, when meet corrupt blocks","","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_files_extend","allow >4GB transaction log files, and can vary universal page size of datafiles","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"}, +{"innodb_sys_tables_sys_indexes","Expose InnoDB SYS_TABLES and SYS_INDEXES schema tables","","http://www.percona.com/docs/wiki/percona-xtradb"}, {NULL, NULL, NULL, NULL} }; === modified file 'storage/xtradb/include/btr0btr.ic' --- a/storage/xtradb/include/btr0btr.ic 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/include/btr0btr.ic 2010-03-22 20:42:52 +0000 @@ -28,7 +28,7 @@ Created 6/2/1994 Heikki Tuuri #include "mtr0mtr.h" #include "mtr0log.h" #include "page0zip.h" - +#include "srv0srv.h" #define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level (not really a hard limit). Used in debug assertions @@ -52,7 +52,9 @@ btr_block_get( block = buf_page_get(space, zip_size, page_no, mode, mtr); - if (mode != RW_NO_LATCH) { + ut_a(srv_pass_corrupt_table || block); + + if (block && mode != RW_NO_LATCH) { buf_block_dbg_add_level(block, SYNC_TREE_NODE); } === modified file 'storage/xtradb/include/buf0buddy.h' --- a/storage/xtradb/include/buf0buddy.h 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/include/buf0buddy.h 2010-03-22 20:42:52 +0000 @@ -83,7 +83,7 @@ typedef struct buf_buddy_stat_struct buf /** Statistics of the buddy system, indexed by block size. Protected by buf_pool_mutex. */ -extern buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1]; +extern buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES_MAX + 1]; #ifndef UNIV_NONINL # include "buf0buddy.ic" === modified file 'storage/xtradb/include/buf0buf.h' --- a/storage/xtradb/include/buf0buf.h 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/include/buf0buf.h 2010-03-22 20:42:52 +0000 @@ -482,6 +482,11 @@ ulint buf_calc_page_new_checksum( /*=======================*/ const byte* page); /*!< in: buffer page */ +UNIV_INTERN +ulint +buf_calc_page_new_checksum_32( +/*==========================*/ + const byte* page); /*!< in: buffer page */ /********************************************************************//** In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only looked at the first few bytes of the page. This calculates that old @@ -855,7 +860,7 @@ buf_block_get_frame( const buf_block_t* block) /*!< in: pointer to the control block */ __attribute__((pure)); #else /* UNIV_DEBUG */ -# define buf_block_get_frame(block) (block)->frame +# define buf_block_get_frame(block) (block ? (block)->frame : 0) #endif /* UNIV_DEBUG */ /*********************************************************************//** Gets the space id of a block. @@ -987,7 +992,8 @@ UNIV_INTERN void buf_page_io_complete( /*=================*/ - buf_page_t* bpage); /*!< in: pointer to the block in question */ + buf_page_t* bpage, /*!< in: pointer to the block in question */ + trx_t* trx); /********************************************************************//** Calculates a folded value of a file page address to use in the page hash table. @@ -1155,6 +1161,7 @@ struct buf_page_struct{ 0 if the block was never accessed in the buffer pool */ /* @} */ + ibool is_corrupt; # ifdef UNIV_DEBUG_FILE_ACCESSES ibool file_page_was_freed; /*!< this is set to TRUE when fsp @@ -1422,11 +1429,11 @@ struct buf_pool_struct{ /* @{ */ UT_LIST_BASE_NODE_T(buf_page_t) zip_clean; /*!< unmodified compressed pages */ - UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES]; + UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX]; /*!< buddy free lists */ -#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE -# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE" -#endif +//#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE +//# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE" +//#endif #if BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE # error "BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE" #endif === modified file 'storage/xtradb/include/buf0buf.ic' --- a/storage/xtradb/include/buf0buf.ic 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/include/buf0buf.ic 2010-04-28 14:35:00 +0000 @@ -35,7 +35,7 @@ Created 11/5/1995 Heikki Tuuri #include "buf0flu.h" #include "buf0lru.h" #include "buf0rea.h" - +#include "srv0srv.h" /********************************************************************//** Reads the freed_page_clock of a buffer block. @return freed_page_clock */ @@ -581,6 +581,12 @@ buf_block_get_frame( /*================*/ const buf_block_t* block) /*!< in: pointer to the control block */ { + ut_a(srv_pass_corrupt_table || block); + + if (srv_pass_corrupt_table && !block) { + return(0); + } + ut_ad(block); switch (buf_block_get_state(block)) { === modified file 'storage/xtradb/include/buf0types.h' --- a/storage/xtradb/include/buf0types.h 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/include/buf0types.h 2010-03-22 20:42:52 +0000 @@ -70,6 +70,7 @@ enum buf_io_fix { buddy system; must be at least sizeof(buf_page_t) */ #define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT) +#define BUF_BUDDY_SIZES_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - BUF_BUDDY_LOW_SHIFT) /*!< number of buddy sizes */ /** twice the maximum block size of the buddy system; === modified file 'storage/xtradb/include/dict0dict.h' --- a/storage/xtradb/include/dict0dict.h 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/include/dict0dict.h 2010-03-22 20:42:52 +0000 @@ -1164,6 +1164,15 @@ void dict_close(void); /*============*/ +/************************************************************************* +set is_corrupt flag by space_id*/ + +void +dict_table_set_corrupt_by_space( +/*============================*/ + ulint space_id, + ibool need_mutex); + #ifndef UNIV_NONINL #include "dict0dict.ic" #endif === modified file 'storage/xtradb/include/dict0mem.h' --- a/storage/xtradb/include/dict0mem.h 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/include/dict0mem.h 2010-03-22 20:42:52 +0000 @@ -521,6 +521,7 @@ struct dict_table_struct{ the AUTOINC lock on this table. */ /* @} */ /*----------------------*/ + ibool is_corrupt; #endif /* !UNIV_HOTBACKUP */ #ifdef UNIV_DEBUG === modified file 'storage/xtradb/include/fil0fil.h' --- a/storage/xtradb/include/fil0fil.h 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/include/fil0fil.h 2010-03-22 20:42:52 +0000 @@ -116,6 +116,7 @@ extern fil_addr_t fil_addr_null; #define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34 /*!< starting from 4.1.x this contains the space id of the page */ #define FIL_PAGE_DATA 38 /*!< start of the data on the page */ +#define FIL_PAGE_DATA_ALIGN_32 40 /* @} */ /** File page trailer @{ */ #define FIL_PAGE_END_LSN_OLD_CHKSUM 8 /*!< the low 4 bytes of this are used @@ -748,6 +749,19 @@ ulint fil_system_hash_nodes(void); /*========================*/ +/************************************************************************* +functions to access is_corrupt flag of fil_space_t*/ + +ibool +fil_space_is_corrupt( +/*=================*/ + ulint space_id); + +void +fil_space_set_corrupt( +/*==================*/ + ulint space_id); + typedef struct fil_space_struct fil_space_t; #endif === modified file 'storage/xtradb/include/fut0fut.ic' --- a/storage/xtradb/include/fut0fut.ic 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/include/fut0fut.ic 2010-03-22 20:42:52 +0000 @@ -23,6 +23,7 @@ File-based utilities Created 12/13/1995 Heikki Tuuri ***********************************************************************/ +#include "srv0srv.h" #include "sync0rw.h" #include "buf0buf.h" @@ -48,6 +49,12 @@ fut_get_ptr( ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr); + + if (srv_pass_corrupt_table && !block) { + return(0); + } + ut_a(block); + ptr = buf_block_get_frame(block) + addr.boffset; buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); === modified file 'storage/xtradb/include/page0cur.h' --- a/storage/xtradb/include/page0cur.h 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/include/page0cur.h 2010-03-22 20:42:52 +0000 @@ -293,6 +293,22 @@ page_cur_open_on_rnd_user_rec( /*==========================*/ buf_block_t* block, /*!< in: page */ page_cur_t* cursor);/*!< out: page cursor */ + +UNIV_INTERN +void +page_cur_open_on_nth_user_rec( +/*==========================*/ + buf_block_t* block, /*!< in: page */ + page_cur_t* cursor, /*!< out: page cursor */ + ulint nth); + +UNIV_INTERN +ibool +page_cur_open_on_rnd_user_rec_after_nth( +/*==========================*/ + buf_block_t* block, /*!< in: page */ + page_cur_t* cursor, /*!< out: page cursor */ + ulint nth); #endif /* !UNIV_HOTBACKUP */ /***********************************************************//** Parses a log record of a record insert on a page. === modified file 'storage/xtradb/include/page0types.h' --- a/storage/xtradb/include/page0types.h 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/include/page0types.h 2010-03-22 20:42:52 +0000 @@ -56,8 +56,9 @@ page0*.h includes rem0rec.h and may incl /** Number of supported compressed page sizes */ #define PAGE_ZIP_NUM_SSIZE (UNIV_PAGE_SIZE_SHIFT - PAGE_ZIP_MIN_SIZE_SHIFT + 2) -#if PAGE_ZIP_NUM_SSIZE > (1 << PAGE_ZIP_SSIZE_BITS) -# error "PAGE_ZIP_NUM_SSIZE > (1 << PAGE_ZIP_SSIZE_BITS)" +#define PAGE_ZIP_NUM_SSIZE_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - PAGE_ZIP_MIN_SIZE_SHIFT + 2) +#if PAGE_ZIP_NUM_SSIZE_MAX > (1 << PAGE_ZIP_SSIZE_BITS) +# error "PAGE_ZIP_NUM_SSIZE_MAX > (1 << PAGE_ZIP_SSIZE_BITS)" #endif /** Compressed page descriptor */ @@ -98,7 +99,7 @@ struct page_zip_stat_struct { typedef struct page_zip_stat_struct page_zip_stat_t; /** Statistics on compression, indexed by page_zip_des_struct::ssize - 1 */ -extern page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1]; +extern page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE_MAX - 1]; /**********************************************************************//** Write the "deleted" flag of a record on a compressed page. The flag must === modified file 'storage/xtradb/include/srv0srv.h' --- a/storage/xtradb/include/srv0srv.h 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/include/srv0srv.h 2010-04-28 14:35:00 +0000 @@ -227,6 +227,7 @@ extern ulint srv_stats_update_need_lock; extern ibool srv_use_doublewrite_buf; extern ibool srv_use_checksums; +extern ibool srv_fast_checksum; extern ibool srv_set_thread_priorities; extern int srv_query_thread_priority; @@ -247,6 +248,7 @@ extern ulong srv_adaptive_checkpoint; extern ulong srv_expand_import; extern ulint srv_relax_table_creation; +extern ulint srv_pass_corrupt_table; extern ulong srv_extra_rsegments; extern ulong srv_dict_size_limit; === modified file 'storage/xtradb/include/trx0sys.h' --- a/storage/xtradb/include/trx0sys.h 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/include/trx0sys.h 2010-03-22 20:42:52 +0000 @@ -487,9 +487,9 @@ in size */ /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */ #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344 -#if UNIV_PAGE_SIZE < 4096 -# error "UNIV_PAGE_SIZE < 4096" -#endif +//#if UNIV_PAGE_SIZE < 4096 +//# error "UNIV_PAGE_SIZE < 4096" +//#endif /** The offset of the MySQL replication info in the trx system header; this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */ #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000) === modified file 'storage/xtradb/include/univ.i' --- a/storage/xtradb/include/univ.i 2010-04-28 13:53:04 +0000 +++ b/storage/xtradb/include/univ.i 2010-04-28 14:35:00 +0000 @@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 #define INNODB_VERSION_BUGFIX 6 -#define PERCONA_INNODB_VERSION 9.1 +#define PERCONA_INNODB_VERSION 10 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; @@ -288,9 +288,13 @@ management to ensure correct alignment f */ /* The 2-logarithm of UNIV_PAGE_SIZE: */ -#define UNIV_PAGE_SIZE_SHIFT 14 +/* #define UNIV_PAGE_SIZE_SHIFT 14 */ +#define UNIV_PAGE_SIZE_SHIFT_MAX 14 +#define UNIV_PAGE_SIZE_SHIFT srv_page_size_shift /* The universal page size of the database */ -#define UNIV_PAGE_SIZE (1u << UNIV_PAGE_SIZE_SHIFT) +/* #define UNIV_PAGE_SIZE (1u << UNIV_PAGE_SIZE_SHIFT) */ +#define UNIV_PAGE_SIZE srv_page_size +#define UNIV_PAGE_SIZE_MAX (1u << UNIV_PAGE_SIZE_SHIFT_MAX) /* Maximum number of parallel threads in a parallelized operation */ #define UNIV_MAX_PARALLELISM 32 @@ -383,7 +387,7 @@ number indicate that a field contains a stored part of the field in the tablespace. The length field then contains the sum of the following flag and the locally stored len. */ -#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE) +#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_MAX) /* Some macros to improve branch prediction and reduce cache misses */ #if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER) @@ -486,4 +490,6 @@ typedef void* os_thread_ret_t; UNIV_MEM_ALLOC(addr, size); \ } while (0) +extern ulint srv_page_size_shift; +extern ulint srv_page_size; #endif === modified file 'storage/xtradb/include/ut0rnd.h' --- a/storage/xtradb/include/ut0rnd.h 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/include/ut0rnd.h 2010-03-22 20:42:52 +0000 @@ -124,6 +124,13 @@ ut_fold_binary( const byte* str, /*!< in: string of bytes */ ulint len) /*!< in: length */ __attribute__((pure)); +UNIV_INLINE +ulint +ut_fold_binary_32( +/*==============*/ + const byte* str, /*!< in: string of bytes */ + ulint len) /*!< in: length */ + __attribute__((pure)); /***********************************************************//** Looks for a prime number slightly greater than the given argument. The prime is chosen so that it is not near any power of 2. === modified file 'storage/xtradb/include/ut0rnd.ic' --- a/storage/xtradb/include/ut0rnd.ic 2009-09-07 10:22:53 +0000 +++ b/storage/xtradb/include/ut0rnd.ic 2010-03-22 20:42:52 +0000 @@ -228,3 +228,28 @@ ut_fold_binary( return(fold); } + +UNIV_INLINE +ulint +ut_fold_binary_32( +/*==============*/ + const byte* str, /*!< in: string of bytes */ + ulint len) /*!< in: length */ +{ + const ib_uint32_t* str_end = (const ib_uint32_t*) (str + len); + const ib_uint32_t* str_32 = (const ib_uint32_t*) str; + ulint fold = 0; + + ut_ad(str); + /* This function is only for word-aligned data */ + ut_ad(len % 4 == 0); + ut_ad((ulint)str % 4 == 0); + + while (str_32 < str_end) { + fold = ut_fold_ulint_pair(fold, (ulint)(*str_32)); + + str_32++; + } + + return(fold); +} === modified file 'storage/xtradb/lock/lock0lock.c' --- a/storage/xtradb/lock/lock0lock.c 2010-03-18 15:25:47 +0000 +++ b/storage/xtradb/lock/lock0lock.c 2010-03-22 20:42:52 +0000 @@ -3364,26 +3364,23 @@ lock_deadlock_recursive( bit_no = lock_rec_find_set_bit(wait_lock); ut_a(bit_no != ULINT_UNDEFINED); - - /* get the starting point for the search for row level locks - since we are scanning from the front of the list */ - lock = lock_rec_get_first_on_page_addr(wait_lock->un_member.rec_lock.space, - wait_lock->un_member.rec_lock.page_no); - } - else { - /* table level locks use a two-way linked list so scanning backwards is OK */ - lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, - lock); - } + } /* Look at the locks ahead of wait_lock in the lock queue */ for (;;) { + if (lock_get_type_low(lock) & LOCK_TABLE) { + lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, + lock); + } else { + ut_ad(lock_get_type_low(lock) == LOCK_REC); + ut_a(bit_no != ULINT_UNDEFINED); + + lock = (lock_t*) lock_rec_get_prev(lock, bit_no); + } - /* reached the original lock in the queue for row level locks - or past beginning of the list for table level locks */ - if (lock == NULL || lock == wait_lock) { + if (lock == NULL) { /* We can mark this subtree as searched */ trx->deadlock_mark = 1; @@ -3508,17 +3505,6 @@ lock_deadlock_recursive( } } } - - /* next lock to check */ - if (lock_get_type_low(lock) & LOCK_TABLE) { - lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, - lock); - } else { - ut_ad(lock_get_type_low(lock) == LOCK_REC); - ut_a(bit_no != ULINT_UNDEFINED); - - lock = (lock_t*) lock_rec_get_next(bit_no, lock); - } }/* end of the 'for (;;)'-loop */ } === modified file 'storage/xtradb/log/log0log.c' --- a/storage/xtradb/log/log0log.c 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/log/log0log.c 2010-03-22 20:42:52 +0000 @@ -608,7 +608,9 @@ log_group_calc_lsn_offset( offset = (gr_lsn_size_offset + difference) % group_size; + if (sizeof(ulint) == 4) { ut_a(offset < (((ib_int64_t) 1) << 32)); /* offset must be < 4 GB */ + } /* fprintf(stderr, "Offset is %lu gr_lsn_offset is %lu difference is %lu\n", @@ -1805,6 +1807,7 @@ log_group_checkpoint( mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size); #ifdef UNIV_LOG_ARCHIVE +#error "UNIV_LOG_ARCHIVE could not be enabled" if (log_sys->archiving_state == LOG_ARCH_OFF) { archived_lsn = IB_ULONGLONG_MAX; } else { @@ -1818,7 +1821,9 @@ log_group_checkpoint( mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn); #else /* UNIV_LOG_ARCHIVE */ - mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, IB_ULONGLONG_MAX); + mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, + (ib_uint64_t)log_group_calc_lsn_offset( + log_sys->next_checkpoint_lsn, group)); #endif /* UNIV_LOG_ARCHIVE */ for (i = 0; i < LOG_MAX_N_GROUPS; i++) { === modified file 'storage/xtradb/log/log0recv.c' --- a/storage/xtradb/log/log0recv.c 2010-03-31 20:50:54 +0000 +++ b/storage/xtradb/log/log0recv.c 2010-04-28 14:35:00 +0000 @@ -680,8 +680,22 @@ recv_find_max_checkpoint( group->lsn = mach_read_ull( buf + LOG_CHECKPOINT_LSN); + +#ifdef UNIV_LOG_ARCHIVE +#error "UNIV_LOG_ARCHIVE could not be enabled" +#endif + { + ib_uint64_t tmp_lsn_offset = mach_read_ull( + buf + LOG_CHECKPOINT_ARCHIVED_LSN); + if (sizeof(ulint) != 4 + && tmp_lsn_offset != IB_ULONGLONG_MAX) { + group->lsn_offset = (ulint) tmp_lsn_offset; + } else { group->lsn_offset = mach_read_from_4( buf + LOG_CHECKPOINT_OFFSET); + } + } + checkpoint_no = mach_read_ull( buf + LOG_CHECKPOINT_NO); === modified file 'storage/xtradb/page/page0cur.c' --- a/storage/xtradb/page/page0cur.c 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/page/page0cur.c 2010-03-22 20:42:52 +0000 @@ -564,6 +564,74 @@ page_cur_open_on_rnd_user_rec( } while (rnd--); } +UNIV_INTERN +void +page_cur_open_on_nth_user_rec( +/*==========================*/ + buf_block_t* block, /*!< in: page */ + page_cur_t* cursor, /*!< out: page cursor */ + ulint nth) +{ + ulint n_recs = page_get_n_recs(buf_block_get_frame(block)); + + page_cur_set_before_first(block, cursor); + + if (UNIV_UNLIKELY(n_recs == 0)) { + + return; + } + + nth--; + + if (nth >= n_recs) { + nth = n_recs - 1; + } + + do { + page_cur_move_to_next(cursor); + } while (nth--); +} + +UNIV_INTERN +ibool +page_cur_open_on_rnd_user_rec_after_nth( +/*==========================*/ + buf_block_t* block, /*!< in: page */ + page_cur_t* cursor, /*!< out: page cursor */ + ulint nth) +{ + ulint rnd; + ulint n_recs = page_get_n_recs(buf_block_get_frame(block)); + ibool ret; + + page_cur_set_before_first(block, cursor); + + if (UNIV_UNLIKELY(n_recs == 0)) { + + return (FALSE); + } + + nth--; + + if (nth >= n_recs) { + nth = n_recs - 1; + } + + rnd = (ulint) (nth + page_cur_lcg_prng() % (n_recs - nth)); + + if (rnd == nth) { + ret = TRUE; + } else { + ret = FALSE; + } + + do { + page_cur_move_to_next(cursor); + } while (rnd--); + + return (ret); +} + /***********************************************************//** Writes the log record of a record insert on a page. */ static === modified file 'storage/xtradb/page/page0zip.c' --- a/storage/xtradb/page/page0zip.c 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/page/page0zip.c 2010-03-22 20:42:52 +0000 @@ -49,7 +49,7 @@ Created June 2005 by Marko Makela #ifndef UNIV_HOTBACKUP /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */ -UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1]; +UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE_MAX - 1]; #endif /* !UNIV_HOTBACKUP */ /* Please refer to ../include/page0zip.ic for a description of the === modified file 'storage/xtradb/row/row0ins.c' --- a/storage/xtradb/row/row0ins.c 2010-01-15 15:58:25 +0000 +++ b/storage/xtradb/row/row0ins.c 2010-04-28 14:35:00 +0000 @@ -1340,6 +1340,12 @@ run_again: const rec_t* rec = btr_pcur_get_rec(&pcur); const buf_block_t* block = btr_pcur_get_block(&pcur); + if (srv_pass_corrupt_table && !block) { + err = DB_CORRUPTION; + break; + } + ut_a(block); + if (page_rec_is_infimum(rec)) { goto next_rec; === modified file 'storage/xtradb/row/row0merge.c' --- a/storage/xtradb/row/row0merge.c 2010-01-06 12:00:14 +0000 +++ b/storage/xtradb/row/row0merge.c 2010-03-22 20:42:52 +0000 @@ -92,7 +92,7 @@ This buffer is used for writing or readi row_merge_block_t. Thus, it must be able to hold one merge record, whose maximum size is the same as the minimum size of row_merge_block_t. */ -typedef byte mrec_buf_t[UNIV_PAGE_SIZE]; +typedef byte mrec_buf_t[UNIV_PAGE_SIZE_MAX]; /** @brief Merge record in row_merge_block_t. @@ -1216,6 +1216,13 @@ row_merge_read_clustered_index( if (UNIV_LIKELY(has_next)) { rec = btr_pcur_get_rec(&pcur); + + if (srv_pass_corrupt_table && !rec) { + err = DB_CORRUPTION; + goto err_exit; + } + ut_a(rec); + offsets = rec_get_offsets(rec, clust_index, NULL, ULINT_UNDEFINED, &row_heap); === modified file 'storage/xtradb/row/row0sel.c' --- a/storage/xtradb/row/row0sel.c 2010-01-15 21:12:30 +0000 +++ b/storage/xtradb/row/row0sel.c 2010-04-28 14:35:00 +0000 @@ -3766,6 +3766,13 @@ rec_loop: /* PHASE 4: Look for matching records in a loop */ rec = btr_pcur_get_rec(pcur); + + if (srv_pass_corrupt_table && !rec) { + err = DB_CORRUPTION; + goto lock_wait_or_error; + } + ut_a(rec); + ut_ad(!!page_rec_is_comp(rec) == comp); #ifdef UNIV_SEARCH_DEBUG /* === modified file 'storage/xtradb/srv/srv0srv.c' --- a/storage/xtradb/srv/srv0srv.c 2010-01-15 19:48:33 +0000 +++ b/storage/xtradb/srv/srv0srv.c 2010-04-28 14:35:00 +0000 @@ -224,6 +224,10 @@ UNIV_INTERN ulint srv_n_file_io_threads UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX; UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX; +/* The universal page size of the database */ +UNIV_INTERN ulint srv_page_size_shift = 0; +UNIV_INTERN ulint srv_page_size = 0; + /* User settable value of the number of pages that must be present in the buffer cache and accessed sequentially for InnoDB to trigger a readahead request. */ @@ -386,6 +390,7 @@ UNIV_INTERN ulint srv_stats_update_need_ UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE; UNIV_INTERN ibool srv_use_checksums = TRUE; +UNIV_INTERN ibool srv_fast_checksum = FALSE; UNIV_INTERN ibool srv_set_thread_priorities = TRUE; UNIV_INTERN int srv_query_thread_priority = 0; @@ -406,6 +411,7 @@ UNIV_INTERN ulong srv_adaptive_checkpoin UNIV_INTERN ulong srv_expand_import = 0; /* 0:disable 1:enable */ UNIV_INTERN ulint srv_relax_table_creation = 0; /* 0:disable 1:enable */ +UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */ UNIV_INTERN ulong srv_extra_rsegments = 0; /* extra rseg for users */ UNIV_INTERN ulong srv_dict_size_limit = 0; @@ -2559,6 +2565,7 @@ srv_master_thread( srv_main_thread_process_no = os_proc_get_number(); srv_main_thread_id = os_thread_pf(os_thread_get_curr_id()); + mutex_enter(&kernel_mutex); srv_table_reserve_slot(SRV_MASTER); === modified file 'storage/xtradb/srv/srv0start.c' --- a/storage/xtradb/srv/srv0start.c 2010-01-17 08:41:43 +0000 +++ b/storage/xtradb/srv/srv0start.c 2010-04-28 14:35:00 +0000 @@ -1352,10 +1352,12 @@ innobase_start_or_create_for_mysql(void) } #endif /* UNIV_LOG_ARCHIVE */ - if (srv_n_log_files * srv_log_file_size >= 262144) { + if (sizeof(ulint) == 4 + && srv_n_log_files * srv_log_file_size + >= ((ulint)1 << (32 - UNIV_PAGE_SIZE_SHIFT))) { fprintf(stderr, "InnoDB: Error: combined size of log files" - " must be < 4 GB\n"); + " must be < 4 GB on 32-bit systems\n"); return(DB_ERROR); } @@ -1364,7 +1366,7 @@ innobase_start_or_create_for_mysql(void) for (i = 0; i < srv_n_data_files; i++) { #ifndef __WIN__ - if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= 262144) { + if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= ((ulint)1 << (32 - UNIV_PAGE_SIZE_SHIFT))) { fprintf(stderr, "InnoDB: Error: file size must be < 4 GB" " with this MySQL binary\n" @@ -1809,6 +1811,13 @@ innobase_start_or_create_for_mysql(void) os_fast_mutex_free(&srv_os_test_mutex); + if (!srv_file_per_table_original_value + && srv_pass_corrupt_table) { + fprintf(stderr, "InnoDB: Warning:" + " innodb_file_per_table is diabled." + " So innodb_pass_corrupt_table doesn't make sence\n"); + } + if (srv_print_verbose_log) { ut_print_timestamp(stderr); fprintf(stderr,
participants (1)
-
knielsen@knielsen-hq.org