maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #02995
bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (knielsen:2854)
#At lp:maria
2854 knielsen@xxxxxxxxxxxxxxx 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@xxxxxxxxxxx>
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@xxxxxxxxxxx>
+
+XtraDB Release 10
+
* Thu Feb 11 2010 Aleksandr Kuzminsky <aleksandr.kuzminsky@xxxxxxxxxxx>
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,