Commit e90a57aa authored by heikki@hundin.mysql.fi's avatar heikki@hundin.mysql.fi
Browse files

Many files:

  Merge InnoDB-3.23.50
parent 254df5fd
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -570,6 +570,19 @@ btr_page_get_father_for_rec(

	node_ptr = btr_cur_get_rec(&cursor);

	if (btr_node_ptr_get_child_page_no(node_ptr) !=
                                                buf_frame_get_page_no(page)) {
      		fprintf(stderr,
"InnoDB: Corruption of an index tree: table %s, index %s,\n"
"InnoDB: father ptr page no %lu, child page no %lu\n",
                    (UT_LIST_GET_FIRST(tree->tree_indexes))->table_name,
                    (UT_LIST_GET_FIRST(tree->tree_indexes))->name,
                    btr_node_ptr_get_child_page_no(node_ptr),
                    buf_frame_get_page_no(page));
     		page_rec_print(page_rec_get_next(page_get_infimum_rec(page)));
     		page_rec_print(node_ptr);
	}

	ut_a(btr_node_ptr_get_child_page_no(node_ptr) ==
						buf_frame_get_page_no(page));
	mem_heap_free(heap);
+1 −1
Original line number Diff line number Diff line
@@ -743,7 +743,7 @@ btr_search_guess_on_hash(
	
#ifdef notdefined
	/* These lines of code can be used in a debug version to check
	correctness of the searched cursor position: */
	the correctness of the searched cursor position: */
	
	info->last_hash_succ = FALSE;

+64 −18
Original line number Diff line number Diff line
@@ -220,6 +220,10 @@ buf_calc_page_checksum(
{
  	ulint checksum;

	/* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO
	are written outside the buffer pool to the first pages of data
	files, we have to skip them in page checksum calculation */
  	
  	checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
  		+ ut_fold_binary(page + FIL_PAGE_DATA,
				UNIV_PAGE_SIZE - FIL_PAGE_DATA
@@ -279,6 +283,7 @@ buf_page_print(

	ut_sprintf_buf(buf, read_buf, UNIV_PAGE_SIZE);

	ut_print_timestamp(stderr);
	fprintf(stderr,
	"  InnoDB: Page dump in ascii and hex (%lu bytes):\n%s",
					UNIV_PAGE_SIZE, buf);
@@ -288,6 +293,7 @@ buf_page_print(

	checksum = buf_calc_page_checksum(read_buf);

	ut_print_timestamp(stderr);
	fprintf(stderr, "  InnoDB: Page checksum %lu stored checksum %lu\n",
			checksum, mach_read_from_4(read_buf
                                        + UNIV_PAGE_SIZE
@@ -1358,21 +1364,51 @@ buf_page_io_complete(
/*=================*/
	buf_block_t*	block)	/* in: pointer to the block in question */
{
	dulint		id;
	dict_index_t*	index;
	dulint		id;
	ulint		io_type;
	ulint		read_page_no;
	
	ut_ad(block);

	io_type = block->io_fix;

	if (io_type == BUF_IO_READ) {
		/* If this page is not uninitialized and not in the
		doublewrite buffer, then the page number should be the
		same as in block */

		read_page_no = mach_read_from_4((block->frame)
						+ FIL_PAGE_OFFSET);
		if (read_page_no != 0
			&& !trx_doublewrite_page_inside(read_page_no)
	    		&& read_page_no != block->offset) {

			fprintf(stderr,
"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n",
				read_page_no, block->offset);
		}
#ifdef notdefined
		if (block->offset != 0 && read_page_no == 0) {
			/* Check that the page is really uninited */

			for (i = 0; i < UNIV_PAGE_SIZE; i++) {

				if (*((block->frame) + i) != '\0') {
					fprintf(stderr,
"InnoDB: Error: page n:o in the page read in is 0, but page %lu is inited!\n",
						block->offset);
					break;
				}
			}
		}
#endif
		/* From version 3.23.38 up we store the page checksum
		   to the 4 upper bytes of the page end lsn field */
		   to the 4 first bytes of the page end lsn field */

		if (buf_page_is_corrupted(block->frame)) {
		  	fprintf(stderr,
			  "InnoDB: Database page corruption or a failed\n"
		"InnoDB: Database page corruption on disk or a failed\n"
		"InnoDB: file read of page %lu.\n", block->offset);
			  
		  	fprintf(stderr,
@@ -1381,7 +1417,7 @@ buf_page_io_complete(
			buf_page_print(block->frame);

		  	fprintf(stderr,
			  "InnoDB: Database page corruption or a failed\n"
		"InnoDB: Database page corruption on disk or a failed\n"
		"InnoDB: file read of page %lu.\n", block->offset);
		  	fprintf(stderr,
		"InnoDB: You may have to recover from a backup.\n");
@@ -1389,16 +1425,26 @@ buf_page_io_complete(
		"InnoDB: It is also possible that your operating\n"
		"InnoDB: system has corrupted its own file cache\n"
		"InnoDB: and rebooting your computer removes the\n"
			  "InnoDB: error.\n");
		"InnoDB: error.\n"
		"InnoDB: If the corrupt page is an index page\n"
		"InnoDB: you can also try to fix the corruption\n"
		"InnoDB: by dumping, dropping, and reimporting\n"
		"InnoDB: the corrupt table. You can use CHECK\n"
		"InnoDB: TABLE to scan your table for corruption.\n"
		"InnoDB: Look also at section 6.1 of\n"
		"InnoDB: http://www.innodb.com/ibman.html about\n"
		"InnoDB: forcing recovery.\n");
			  
			if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
				fprintf(stderr,
	"InnoDB: Ending processing because of a corrupt database page.\n");
		  		exit(1);
		  	}
		}

		if (recv_recovery_is_on()) {
			recv_recover_page(TRUE, block->frame, block->space,
								block->offset);
			recv_recover_page(FALSE, TRUE, block->frame,
						block->space, block->offset);
		}

		if (!recv_no_ibuf_operations) {
+30 −17
Original line number Diff line number Diff line
@@ -327,6 +327,34 @@ buf_flush_post_to_doublewrite_buf(
	mutex_exit(&(trx_doublewrite->mutex));
}

/************************************************************************
Initializes a page for writing to the tablespace. */

void
buf_flush_init_for_writing(
/*=======================*/
	byte*	page,		/* in: page */
	dulint	newest_lsn,	/* in: newest modification lsn to the page */
	ulint	space,		/* in: space id */
	ulint	page_no)	/* in: page number */
{	
	/* Write the newest modification lsn to the page */
	mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn);

	mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, newest_lsn);

	/* Write to the page the space id and page number */

	mach_write_to_4(page + FIL_PAGE_SPACE, space);
	mach_write_to_4(page + FIL_PAGE_OFFSET, page_no);

	/* We overwrite the first 4 bytes of the end lsn field to store
	a page checksum */

	mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
					buf_calc_page_checksum(page));
}

/************************************************************************
Does an asynchronous write of a buffer page. NOTE: in simulated aio and
also when the doublewrite buffer is used, we must call
@@ -349,23 +377,8 @@ buf_flush_write_block_low(
	/* Force the log to the disk before writing the modified block */
	log_flush_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS);
#endif	
	/* Write the newest modification lsn to the page */
	mach_write_to_8(block->frame + FIL_PAGE_LSN,
						block->newest_modification);
	mach_write_to_8(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
						block->newest_modification);

	/* Write to the page the space id and page number */

	mach_write_to_4(block->frame + FIL_PAGE_SPACE, block->space);
	mach_write_to_4(block->frame + FIL_PAGE_OFFSET, block->offset);

	/* We overwrite the first 4 bytes of the end lsn field to store
	a page checksum */

	mach_write_to_4(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
			buf_calc_page_checksum(block->frame));

	buf_flush_init_for_writing(block->frame, block->newest_modification,
						block->space, block->offset);
	if (!trx_doublewrite) {
		fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
			FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
+185 −14
Original line number Diff line number Diff line
@@ -281,7 +281,8 @@ dict_table_autoinc_initialize(
}

/************************************************************************
Gets the next autoinc value, 0 if not yet initialized. */
Gets the next autoinc value, 0 if not yet initialized. If initialized,
increments the counter by 1. */

ib_longlong
dict_table_autoinc_get(
@@ -306,6 +307,32 @@ dict_table_autoinc_get(
	return(value);
}

/************************************************************************
Reads the autoinc counter value, 0 if not yet initialized. Does not
increment the counter. */

ib_longlong
dict_table_autoinc_read(
/*====================*/
				/* out: value of the counter */
	dict_table_t*	table)	/* in: table */
{
	ib_longlong	value;

	mutex_enter(&(table->autoinc_mutex));

	if (!table->autoinc_inited) {

		value = 0;
	} else {
		value = table->autoinc;
	}
	
	mutex_exit(&(table->autoinc_mutex));

	return(value);
}

/************************************************************************
Updates the autoinc counter if the value supplied is bigger than the
current value. If not inited, does nothing. */
@@ -644,7 +671,10 @@ dict_table_rename_in_cache(
/*=======================*/
					/* out: TRUE if success */
	dict_table_t*	table,		/* in: table */
	char*		new_name)	/* in: new name */
	char*		new_name,	/* in: new name */
	ibool		rename_also_foreigns)/* in: in ALTER TABLE we want
					to preserve the original table name
					in constraints which reference it */
{
	dict_foreign_t*	foreign;
	dict_index_t*	index;
@@ -702,6 +732,41 @@ dict_table_rename_in_cache(
		index = dict_table_get_next_index(index);
	}

	if (!rename_also_foreigns) {
		/* In ALTER TABLE we think of the rename table operation
		in the direction table -> temporary table (#sql...)
		as dropping the table with the old name and creating
		a new with the new name. Thus we kind of drop the
		constraints from the dictionary cache here. The foreign key
		constraints will be inherited to the new table from the
		system tables through a call of dict_load_foreigns. */
	
		/* Remove the foreign constraints from the cache */
		foreign = UT_LIST_GET_LAST(table->foreign_list);

		while (foreign != NULL) {
			dict_foreign_remove_from_cache(foreign);
			foreign = UT_LIST_GET_LAST(table->foreign_list);
		}

		/* Reset table field in referencing constraints */

		foreign = UT_LIST_GET_FIRST(table->referenced_list);

		while (foreign != NULL) {
			foreign->referenced_table = NULL;
			foreign->referenced_index = NULL;
		
			foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
		}

		/* Make the list of referencing constraints empty */

		UT_LIST_INIT(table->referenced_list);
		
		return(TRUE);
	}

	/* Update the table name fields in foreign constraints */

	foreign = UT_LIST_GET_FIRST(table->foreign_list);
@@ -768,8 +833,6 @@ dict_table_remove_from_cache(
	foreign = UT_LIST_GET_LAST(table->foreign_list);

	while (foreign != NULL) {
		ut_a(0 == ut_strcmp(foreign->foreign_table_name, table->name));

		dict_foreign_remove_from_cache(foreign);
		foreign = UT_LIST_GET_LAST(table->foreign_list);
	}
@@ -779,8 +842,6 @@ dict_table_remove_from_cache(
	foreign = UT_LIST_GET_FIRST(table->referenced_list);

	while (foreign != NULL) {
		ut_a(0 == ut_strcmp(foreign->referenced_table_name,
								table->name));
		foreign->referenced_table = NULL;
		foreign->referenced_index = NULL;
		
@@ -1630,6 +1691,7 @@ dict_foreign_add_to_cache(
	dict_table_t*	ref_table;
	dict_foreign_t*	for_in_cache			= NULL;
	dict_index_t*	index;
	ibool		added_to_referenced_list	= FALSE;

	ut_ad(mutex_own(&(dict_sys->mutex)));

@@ -1673,6 +1735,7 @@ dict_foreign_add_to_cache(
		UT_LIST_ADD_LAST(referenced_list,
					ref_table->referenced_list,
					for_in_cache);
		added_to_referenced_list = TRUE;
	}

	if (for_in_cache->foreign_table == NULL && for_table) {
@@ -1683,6 +1746,12 @@ dict_foreign_add_to_cache(

		if (index == NULL) {
			if (for_in_cache == foreign) {
				if (added_to_referenced_list) {
					UT_LIST_REMOVE(referenced_list,
						ref_table->referenced_list,
						for_in_cache);
				}
			
				mem_heap_free(foreign->heap);
			}

@@ -1802,9 +1871,14 @@ dict_scan_col(
		return(ptr);
	}

	if (*ptr == '`') {
		ptr++;
	}

	old_ptr = ptr;
	
	while (!isspace(*ptr) && *ptr != ',' && *ptr != ')') {
	while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && 	*ptr != '`') {

		ptr++;
	}

@@ -1825,6 +1899,10 @@ dict_scan_col(
		}
	}
	
	if (*ptr == '`') {
		ptr++;
	}

	return(ptr);
}

@@ -1855,9 +1933,13 @@ dict_scan_table_name(
		return(ptr);
	}

	if (*ptr == '`') {
		ptr++;
	}

	old_ptr = ptr;
	
	while (!isspace(*ptr) && *ptr != '(') {
	while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
		if (*ptr == '.') {
			dot_ptr = ptr;
		}
@@ -1898,6 +1980,10 @@ dict_scan_table_name(

	*table = dict_table_get_low(second_table_name);

	if (*ptr == '`') {
		ptr++;
	}

	return(ptr);
}

@@ -1940,8 +2026,8 @@ dict_create_foreign_constraints(
/*============================*/
				/* out: error code or DB_SUCCESS */
	trx_t*	trx,		/* in: transaction */
	char*	sql_string,	/* in: table create statement where
				foreign keys are declared like:
	char*	sql_string,	/* in: table create or ALTER TABLE
				statement where foreign keys are declared like:
				FOREIGN KEY (a, b) REFERENCES table2(c, d),
				table2 can be written also with the database
				name before it: test.table2; the default
@@ -1967,10 +2053,11 @@ dict_create_foreign_constraints(
	if (table == NULL) {
		return(DB_ERROR);
	}

loop:
	ptr = dict_scan_to(ptr, "FOREIGN");

	if (*ptr == '\0' || dict_bracket_count(sql_string, ptr) != 1) {
	if (*ptr == '\0') {

		/* The following call adds the foreign key constraints
		to the data dictionary system tables on disk */
@@ -2883,12 +2970,89 @@ dict_field_print_low(
	printf(" %s", field->name);
}

/**************************************************************************
Sprintfs to a string info on foreign keys of a table in a format suitable
for CREATE TABLE. */
static
void
dict_print_info_on_foreign_keys_in_create_format(
/*=============================================*/
	char*		buf,	/* in: auxiliary buffer of 10000 chars */
	char*		str,	/* in/out: pointer to a string */
	ulint		len,	/* in: space in str available for info */
	dict_table_t*	table)	/* in: table */
{

	dict_foreign_t*	foreign;
	ulint		i;
	char*		buf2;

	buf2 = buf;

	mutex_enter(&(dict_sys->mutex));

	foreign = UT_LIST_GET_FIRST(table->foreign_list);

	if (foreign == NULL) {
		mutex_exit(&(dict_sys->mutex));

		return;
	}

	while (foreign != NULL) {
		buf2 += sprintf(buf2, ",\n  FOREIGN KEY (");

		for (i = 0; i < foreign->n_fields; i++) {
			buf2 += sprintf(buf2, "`%s`",
					foreign->foreign_col_names[i]);
			
			if (i + 1 < foreign->n_fields) {
				buf2 += sprintf(buf2, ", ");
			}
		}

		buf2 += sprintf(buf2, ") REFERENCES `%s` (",
					foreign->referenced_table_name);
		/* Change the '/' in the table name to '.' */

		for (i = ut_strlen(buf); i > 0; i--) {
			if (buf[i] == '/') {

				buf[i] = '.';

				break;
			}
		}
	
		for (i = 0; i < foreign->n_fields; i++) {
			buf2 += sprintf(buf2, "`%s`",
					foreign->referenced_col_names[i]);
			if (i + 1 < foreign->n_fields) {
				buf2 += sprintf(buf2, ", ");
			}
		}

		buf2 += sprintf(buf2, ")");

		foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
	}

	mutex_exit(&(dict_sys->mutex));

	buf[len - 1] = '\0';
	ut_memcpy(str, buf, len);
}

/**************************************************************************
Sprintfs to a string info on foreign keys of a table. */

void
dict_print_info_on_foreign_keys(
/*============================*/
	ibool		create_table_format, /* in: if TRUE then print in
				a format suitable to be inserted into
				a CREATE TABLE, otherwise in the format
				of SHOW TABLE STATUS */
	char*		str,	/* in/out: pointer to a string */
	ulint		len,	/* in: space in str available for info */
	dict_table_t*	table)	/* in: table */
@@ -2898,6 +3062,12 @@ dict_print_info_on_foreign_keys(
	char*		buf2;
	char		buf[10000];

	if (create_table_format) {
		dict_print_info_on_foreign_keys_in_create_format(
						buf, str, len, table);
		return;
	}

	buf2 = buf;

	mutex_enter(&(dict_sys->mutex));
@@ -2916,6 +3086,7 @@ dict_print_info_on_foreign_keys(
		for (i = 0; i < foreign->n_fields; i++) {
			buf2 += sprintf(buf2, "%s",
					foreign->foreign_col_names[i]);
			
			if (i + 1 < foreign->n_fields) {
				buf2 += sprintf(buf2, " ");
			}
Loading