MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Jimmy Yang Date:February 9 2011 7:38am
Subject:bzr commit into mysql-trunk-innodb branch (jimmy.yang:3489) Bug#59048
View as plain text  
#At file:///home/jy/work2/mysql-trunk-innodb2/ based on revid:marko.makela@stripped

 3489 Jimmy Yang	2011-02-08
      Fix Bug #59048 truncate table or create index could leave index->page
      to be FIL_NULL
      
      rb://545, approved by Sunny Bains

    modified:
      storage/innobase/dict/dict0dict.c
      storage/innobase/dict/dict0load.c
      storage/innobase/dict/dict0stats.c
      storage/innobase/handler/i_s.cc
      storage/innobase/include/dict0dict.h
      storage/innobase/include/dict0load.h
      storage/innobase/include/dict0mem.h
      storage/innobase/include/dict0priv.ic
      storage/innobase/include/dict0types.h
      storage/innobase/row/row0merge.c
      storage/innobase/row/row0mysql.c
=== modified file 'storage/innobase/dict/dict0dict.c'
--- a/storage/innobase/dict/dict0dict.c	revid:marko.makela@stripped
+++ b/storage/innobase/dict/dict0dict.c	revid:jimmy.yang@stripped
@@ -812,7 +812,10 @@ dict_table_t*
 dict_table_open_on_name_low(
 /*========================*/
 	const char*	table_name,	/*!< in: table name */
-	ibool		dict_locked)	/*!< in: TRUE=data dictionary locked */
+	ibool		dict_locked,	/*!< in: TRUE=data dictionary locked */
+	dict_err_ignore_t
+			ignore_err)	/*!< in: error to be ignored when
+					loading a table definition */
 {
 	dict_table_t*	table;
 
@@ -820,12 +823,22 @@ dict_table_open_on_name_low(
 		mutex_enter(&(dict_sys->mutex));
 	}
 
+	ut_ad(table_name);
 	ut_ad(mutex_own(&dict_sys->mutex));
 
-	table = dict_table_get_low(table_name);
+	table = dict_table_check_if_in_cache_low(table_name);
+
+	if (table == NULL) {
+		table = dict_load_table(table_name, TRUE, ignore_err);
+	}
+
+	ut_ad(!table || table->cached);
 
 	if (table != NULL) {
 
+		ut_ad(ignore_err != DICT_ERR_IGNORE_NONE
+		      || table->corrupted == FALSE);
+
 		if (table->can_be_evicted) {
 			dict_move_to_mru(table);
 		}
@@ -857,7 +870,8 @@ dict_table_open_on_name(
 {
 	dict_table_t*	table;
 
-	table = dict_table_open_on_name_low(table_name, dict_locked);
+	table = dict_table_open_on_name_low(table_name, dict_locked,
+					    DICT_ERR_IGNORE_NONE);
 
 	if (table != NULL) {
 		/* If table->ibd_file_missing == TRUE, this will
@@ -881,9 +895,13 @@ dict_table_t*
 dict_table_open_on_name_no_stats(
 /*=============================*/
 	const char*	table_name,	/*!< in: table name */
-	ibool		dict_locked)	/*!< in: TRUE=data dictionary locked */
+	ibool		dict_locked,	/*!< in: TRUE=data dictionary locked */
+	dict_err_ignore_t
+			ignore_err)	/*!< in: error to be ignored during
+					table open */
 {
-	return(dict_table_open_on_name_low(table_name, dict_locked));
+	return(dict_table_open_on_name_low(table_name, dict_locked,
+					   ignore_err));
 }
 
 #endif /* !UNIV_HOTBACKUP */

=== modified file 'storage/innobase/dict/dict0load.c'
--- a/storage/innobase/dict/dict0load.c	revid:marko.makela@stripped
+++ b/storage/innobase/dict/dict0load.c	revid:jimmy.yang@stripped
@@ -1320,7 +1320,10 @@ ulint
 dict_load_indexes(
 /*==============*/
 	dict_table_t*	table,	/*!< in/out: table */
-	mem_heap_t*	heap)	/*!< in: memory heap for temporary storage */
+	mem_heap_t*	heap,	/*!< in: memory heap for temporary storage */
+	dict_err_ignore_t ignore_err)
+				/*!< in: error to be ignored when
+				loading the index definition */
 {
 	dict_table_t*	sys_indexes;
 	dict_index_t*	sys_index;
@@ -1404,10 +1407,22 @@ dict_load_indexes(
 				"InnoDB: but the index tree has been freed!\n",
 				index->name, table->name);
 
+			if (ignore_err & DICT_ERR_IGNORE_INDEX_ROOT) {
+				/* If caller can tolerate this error,
+				we will continue to load the index and
+				let caller deal with this error. However
+				mark the index and table corrupted */
+				index->corrupted = TRUE;
+				table->corrupted = TRUE;
+				fprintf(stderr,
+					"InnoDB: Index is corrupt but forcing"
+					" load into data dictionary\n");
+			} else {
 corrupted:
-			dict_mem_index_free(index);
-			error = DB_CORRUPTION;
-			goto func_exit;
+				dict_mem_index_free(index);
+				error = DB_CORRUPTION;
+				goto func_exit;
+			}
 		} else if (!dict_index_is_clust(index)
 			   && NULL == dict_table_get_first_index(table)) {
 
@@ -1616,7 +1631,10 @@ dict_load_table(
 /*============*/
 	const char*	name,	/*!< in: table name in the
 				databasename/tablename format */
-	ibool		cached)	/*!< in: TRUE=add to cache, FALSE=do not */
+	ibool		cached,	/*!< in: TRUE=add to cache, FALSE=do not */
+	dict_err_ignore_t ignore_err)
+				/*!< in: error to be ignored when loading
+				table and its indexes' definition */
 {
 	dict_table_t*	table;
 	dict_table_t*	sys_tables;
@@ -1731,7 +1749,7 @@ err_exit:
 
 	mem_heap_empty(heap);
 
-	err = dict_load_indexes(table, heap);
+	err = dict_load_indexes(table, heap, ignore_err);
 
 	/* Initialize table foreign_child value. Its value could be
 	changed when dict_load_foreigns() is called below */
@@ -1781,6 +1799,8 @@ err_exit:
 #endif /* 0 */
 	mem_heap_free(heap);
 
+	ut_ad(ignore_err != DICT_ERR_IGNORE_NONE || table->corrupted == FALSE);
+
 	return(table);
 }
 
@@ -1867,7 +1887,7 @@ dict_load_table_on_id(
 	field = rec_get_nth_field_old(rec, 1, &len);
 	/* Load the table definition to memory */
 	table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
-				TRUE);
+				TRUE, DICT_ERR_IGNORE_NONE);
 
 	btr_pcur_close(&pcur);
 	mtr_commit(&mtr);
@@ -1892,7 +1912,7 @@ dict_load_sys_table(
 
 	heap = mem_heap_create(1000);
 
-	dict_load_indexes(table, heap);
+	dict_load_indexes(table, heap, DICT_ERR_IGNORE_NONE);
 
 	mem_heap_free(heap);
 }

=== modified file 'storage/innobase/dict/dict0stats.c'
--- a/storage/innobase/dict/dict0stats.c	revid:marko.makela@stripped
+++ b/storage/innobase/dict/dict0stats.c	revid:jimmy.yang@stripped
@@ -2326,10 +2326,10 @@ dict_stats_open(void)
 	dict_stats = mem_zalloc(sizeof(*dict_stats));
 
 	dict_stats->table_stats = dict_table_open_on_name_no_stats(
-		TABLE_STATS_NAME, FALSE);
+		TABLE_STATS_NAME, FALSE, DICT_ERR_IGNORE_NONE);
 
 	dict_stats->index_stats = dict_table_open_on_name_no_stats(
-		INDEX_STATS_NAME, FALSE);
+		INDEX_STATS_NAME, FALSE, DICT_ERR_IGNORE_NONE);
 
 	/* Check if the tables have the correct structure, if yes then
 	after this function we can safely DELETE from them without worrying

=== modified file 'storage/innobase/handler/i_s.cc'
--- a/storage/innobase/handler/i_s.cc	revid:marko.makela@stripped
+++ b/storage/innobase/handler/i_s.cc	revid:jimmy.yang@stripped
@@ -4638,7 +4638,12 @@ i_s_dict_fill_sys_indexes(
 
 	OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
 
-	OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
+	/* FIL_NULL is ULINT32_UNDEFINED */
+	if (index->page == FIL_NULL) {
+		OK(fields[SYS_INDEX_PAGE_NO]->store(-1));
+	} else {
+		OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
+	}
 
 	OK(fields[SYS_INDEX_SPACE]->store(index->space));
 

=== modified file 'storage/innobase/include/dict0dict.h'
--- a/storage/innobase/include/dict0dict.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/dict0dict.h	revid:jimmy.yang@stripped
@@ -427,7 +427,10 @@ dict_table_t*
 dict_table_open_on_name_no_stats(
 /*=============================*/
 	const char*	table_name,	/*!< in: table name */
-	ibool		dict_locked);	/*!< in: TRUE=data dictionary locked */
+	ibool		dict_locked,	/*!< in: TRUE=data dictionary locked */
+	dict_err_ignore_t
+			ignore_err);	/*!< in: error to be ignored when
+					loading the table */
 /**********************************************************************//**
 Find an index that is equivalent to the one passed in and is not marked
 for deletion.

=== modified file 'storage/innobase/include/dict0load.h'
--- a/storage/innobase/include/dict0load.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/dict0load.h	revid:jimmy.yang@stripped
@@ -170,7 +170,10 @@ dict_load_table(
 /*============*/
 	const char*	name,	/*!< in: table name in the
 				databasename/tablename format */
-	ibool		cached);/*!< in: TRUE=add to cache, FALSE=do not */
+	ibool		cached,	/*!< in: TRUE=add to cache, FALSE=do not */
+	dict_err_ignore_t ignore_err);
+				/*!< in: error to be ignored when loading
+				table and its indexes' definition */
 /***********************************************************************//**
 Loads a table object based on the table id.
 @return	table; NULL if table does not exist */

=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/dict0mem.h	revid:jimmy.yang@stripped
@@ -361,6 +361,8 @@ struct dict_index_struct{
 				/*!< TRUE if this index is marked to be
 				dropped in ha_innobase::prepare_drop_index(),
 				otherwise FALSE */
+	unsigned	corrupted:1;
+				/*!< TRUE if the index object is corrupted */
 	dict_field_t*	fields;	/*!< array of field descriptions */
 #ifndef UNIV_HOTBACKUP
 	UT_LIST_NODE_T(dict_index_t)
@@ -502,6 +504,8 @@ struct dict_table_struct{
 	unsigned	can_be_evicted:1;
 				/*!< TRUE if it's not an InnoDB system table
 				or a table that has no FK relationships */
+	unsigned	corrupted:1;
+				/*!< TRUE if table is corrupted */
 	dict_col_t*	cols;	/*!< array of column descriptions */
 	const char*	col_names;
 				/*!< Column names packed in a character string

=== modified file 'storage/innobase/include/dict0priv.ic'
--- a/storage/innobase/include/dict0priv.ic	revid:marko.makela@stripped
+++ b/storage/innobase/include/dict0priv.ic	revid:jimmy.yang@stripped
@@ -45,7 +45,7 @@ dict_table_get_low(
 	table = dict_table_check_if_in_cache_low(table_name);
 
 	if (table == NULL) {
-		table = dict_load_table(table_name, TRUE);
+		table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
 	}
 
 	ut_ad(!table || table->cached);

=== modified file 'storage/innobase/include/dict0types.h'
--- a/storage/innobase/include/dict0types.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/dict0types.h	revid:jimmy.yang@stripped
@@ -47,4 +47,18 @@ DICT_IBUF_ID_MIN plus the space id */
 typedef ib_id_t		table_id_t;
 typedef ib_id_t		index_id_t;
 
+/** Error to ignore when we load table dictionary into memory. However,
+the table and index will be marked as "corrupted", and caller will
+be responsible to deal with corrupted table or index.
+Note: please define the IGNORE_ERR_* as bits, so their value can
+be or-ed together */
+enum dict_err_ignore {
+        DICT_ERR_IGNORE_NONE = 0,        /*!< no error to ignore */
+        DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
+					page is FIL_NUL or incorrect value */
+        DICT_ERR_IGNORE_ALL = 0xFFFF	/*!< ignore all errors */
+};
+
+typedef enum dict_err_ignore		dict_err_ignore_t;
+
 #endif

=== modified file 'storage/innobase/row/row0merge.c'
--- a/storage/innobase/row/row0merge.c	revid:marko.makela@stripped
+++ b/storage/innobase/row/row0merge.c	revid:jimmy.yang@stripped
@@ -2323,7 +2323,7 @@ row_merge_create_temporary_table(
 		use it we need to open the table. */
 
 		temp_table = dict_table_open_on_name_no_stats(
-			new_table->name, TRUE);
+			new_table->name, TRUE, DICT_ERR_IGNORE_NONE);
 
 		ut_a(new_table == temp_table);
 	}

=== modified file 'storage/innobase/row/row0mysql.c'
--- a/storage/innobase/row/row0mysql.c	revid:marko.makela@stripped
+++ b/storage/innobase/row/row0mysql.c	revid:jimmy.yang@stripped
@@ -1951,7 +1951,8 @@ err_exit:
 		ut_print_name(stderr, trx, TRUE, table->name);
 		fputs(" because tablespace full\n", stderr);
 
-		if (dict_table_open_on_name_no_stats(table->name, FALSE)) {
+		if (dict_table_open_on_name_no_stats(
+			table->name, FALSE, DICT_ERR_IGNORE_NONE)) {
 
 			/* Make things easy for the drop table code. */
 
@@ -2254,7 +2255,8 @@ loop:
 		return(n_tables + n_tables_dropped);
 	}
 
-	table = dict_table_open_on_name_no_stats(drop->table_name, FALSE);
+	table = dict_table_open_on_name_no_stats(drop->table_name, FALSE,
+						 DICT_ERR_IGNORE_NONE);
 
 	if (table == NULL) {
 		/* If for some reason the table has already been dropped
@@ -2425,7 +2427,8 @@ row_discard_tablespace_for_mysql(
 
 	row_mysql_lock_data_dictionary(trx);
 
-	table = dict_table_open_on_name_no_stats(name, TRUE);
+	table = dict_table_open_on_name_no_stats(name, TRUE,
+						 DICT_ERR_IGNORE_NONE);
 
 	if (!table) {
 		err = DB_TABLE_NOT_FOUND;
@@ -2624,7 +2627,8 @@ row_import_tablespace_for_mysql(
 
 	row_mysql_lock_data_dictionary(trx);
 
-	table = dict_table_open_on_name_no_stats(name, TRUE);
+	table = dict_table_open_on_name_no_stats(name, TRUE,
+						 DICT_ERR_IGNORE_NONE);
 
 	if (!table) {
 		ut_print_timestamp(stderr);
@@ -3152,7 +3156,8 @@ row_drop_table_for_mysql(
 	ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
 #endif /* UNIV_SYNC_DEBUG */
 
-	table = dict_table_open_on_name_no_stats(name, TRUE);
+	table = dict_table_open_on_name_no_stats(name, TRUE,
+						 DICT_ERR_IGNORE_INDEX_ROOT);
 
 	if (!table) {
 		err = DB_TABLE_NOT_FOUND;
@@ -3415,7 +3420,7 @@ check_next_foreign:
 
 		dict_table_remove_from_cache(table);
 
-		if (dict_load_table(name, TRUE) != NULL) {
+		if (dict_load_table(name, TRUE, DICT_ERR_IGNORE_NONE) != NULL) {
 			ut_print_timestamp(stderr);
 			fputs("  InnoDB: Error: not able to remove table ",
 			      stderr);
@@ -3572,7 +3577,7 @@ row_mysql_drop_temp_tables(void)
 		btr_pcur_store_position(&pcur, &mtr);
 		btr_pcur_commit_specify_mtr(&pcur, &mtr);
 
-		table = dict_load_table(table_name, TRUE);
+		table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
 
 		if (table) {
 			row_drop_table_for_mysql(table_name, trx, FALSE);
@@ -3680,7 +3685,8 @@ loop:
 	while ((table_name = dict_get_first_table_name_in_db(name))) {
 		ut_a(memcmp(table_name, name, namelen) == 0);
 
-		table = dict_table_open_on_name_no_stats(table_name, TRUE);
+		table = dict_table_open_on_name_no_stats(table_name, TRUE,
+							 DICT_ERR_IGNORE_NONE);
 
 		ut_a(table);
 		ut_a(!table->can_be_evicted);
@@ -3874,7 +3880,8 @@ row_rename_table_for_mysql(
 
 	dict_locked = trx->dict_operation_lock_mode == RW_X_LATCH;
 
-	table = dict_table_open_on_name_no_stats(old_name, dict_locked);
+	table = dict_table_open_on_name_no_stats(old_name, dict_locked,
+						 DICT_ERR_IGNORE_NONE);
 
 	if (!table) {
 		err = DB_TABLE_NOT_FOUND;


Attachment: [text/bzr-bundle] bzr/jimmy.yang@oracle.com-20110209073757-wfa798f6qh33f6q0.bundle
Thread
bzr commit into mysql-trunk-innodb branch (jimmy.yang:3489) Bug#59048Jimmy Yang9 Feb