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

ha_innobase.cc:

  Merge 3.23.52
parent 94e926ac
Loading
Loading
Loading
Loading
+149 −39
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ InnoDB */
#endif

#include "mysql_priv.h"
#include "slave.h"
#ifdef HAVE_INNOBASE_DB
#include <m_ctype.h>
#include <assert.h>
@@ -53,10 +54,12 @@ typedef byte mysql_byte;
/* Include necessary InnoDB headers */
extern "C" {
#include "../innobase/include/univ.i"
#include "../innobase/include/os0file.h"
#include "../innobase/include/srv0start.h"
#include "../innobase/include/srv0srv.h"
#include "../innobase/include/trx0roll.h"
#include "../innobase/include/trx0trx.h"
#include "../innobase/include/trx0sys.h"
#include "../innobase/include/row0ins.h"
#include "../innobase/include/row0mysql.h"
#include "../innobase/include/row0sel.h"
@@ -180,7 +183,8 @@ int
convert_error_code_to_mysql(
/*========================*/
			/* out: MySQL error code */
	int	error)	/* in: InnoDB error code */
	int	error,	/* in: InnoDB error code */
	THD*	thd)	/* in: user thread handle or NULL */
{
	if (error == DB_SUCCESS) {

@@ -199,11 +203,27 @@ convert_error_code_to_mysql(
    		return(HA_ERR_NO_ACTIVE_RECORD);

 	} else if (error == (int) DB_DEADLOCK) {
 		/* Since we roll back the whole transaction, we must
 		tell it also to MySQL so that MySQL knows to empty the
 		cached binlog for this transaction */

 		if (thd) {
 			ha_rollback(thd);
 		}

    		return(HA_ERR_LOCK_DEADLOCK);

 	} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {

 		/* Since we roll back the whole transaction, we must
 		tell it also to MySQL so that MySQL knows to empty the
 		cached binlog for this transaction */


 		if (thd) {
 			ha_rollback(thd);
 		}

    		return(HA_ERR_LOCK_WAIT_TIMEOUT);

 	} else if (error == (int) DB_NO_REFERENCED_ROW) {
@@ -313,7 +333,23 @@ check_trx_exists(
		thd->transaction.stmt.innobase_tid =
		                  (void*)&innodb_dummy_stmt_trx_handle;
	} else {
		ut_a(trx->magic_n == TRX_MAGIC_N);
		if (trx->magic_n != TRX_MAGIC_N) {
			mem_analyze_corruption((byte*)trx);

			ut_a(0);
		}
	}

	if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
		trx->check_foreigns = FALSE;
	} else {
		trx->check_foreigns = TRUE;
	}

	if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
		trx->check_unique_secondary = FALSE;
	} else {
		trx->check_unique_secondary = TRUE;
	}

	return(trx);
@@ -359,6 +395,8 @@ innobase_init(void)
	
  	DBUG_ENTER("innobase_init");
  
	os_innodb_umask = (ulint)my_umask;

	if (specialflag & SPECIAL_NO_PRIOR) {
	        srv_set_thread_priorities = FALSE;
	} else {
@@ -435,7 +473,7 @@ innobase_init(void)

	srv_log_archive_on = (ulint) innobase_log_archive;
	srv_log_buffer_size = (ulint) innobase_log_buffer_size;
	srv_flush_log_at_trx_commit = (ibool) innobase_flush_log_at_trx_commit;
	srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;

	srv_use_native_aio = 0;

@@ -470,6 +508,22 @@ innobase_init(void)
	(void) hash_init(&innobase_open_tables,32,0,0,
			 		(hash_get_key) innobase_get_key,0,0);
	pthread_mutex_init(&innobase_mutex,MY_MUTEX_INIT_FAST);

	/* If this is a replication slave and we needed to do a crash recovery,
	set the master binlog position to what InnoDB internally knew about
	how far we got transactions durable inside InnoDB. There is a
	problem here: if the user used also MyISAM tables, InnoDB might not
	know the right position for them.

	THIS DOES NOT WORK CURRENTLY because replication seems to initialize
	glob_mi also after innobase_init. */
	
/*	if (trx_sys_mysql_master_log_pos != -1) {
		ut_memcpy(glob_mi.log_file_name, trx_sys_mysql_master_log_name,
				1 + ut_strlen(trx_sys_mysql_master_log_name));
		glob_mi.pos = trx_sys_mysql_master_log_pos;
	}
*/
  	DBUG_RETURN(0);
}

@@ -528,6 +582,17 @@ innobase_get_free_space(void)
/*********************************************************************
Commits a transaction in an InnoDB database. */

void
innobase_commit_low(
/*================*/
	trx_t*	trx)	/* in: transaction handle */
{
	trx_commit_for_mysql(trx);
}

/*********************************************************************
Commits a transaction in an InnoDB database. */

int
innobase_commit(
/*============*/
@@ -547,8 +612,21 @@ innobase_commit(
	trx = check_trx_exists(thd);

	if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
		if (thd->slave_thread) {

		trx_commit_for_mysql(trx);
			/* Update the replication position info inside
			InnoDB. Note that we cannot presently do this for
			CREATE TABLE etc. because MySQL does not tell us the
			thd associated with those operations! */
	
			trx->mysql_master_log_file_name =
						glob_mi.log_file_name;
			trx->mysql_master_log_pos = (ib_longlong)
					(glob_mi.pos + glob_mi.event_len
					+ glob_mi.pending);
		}

		innobase_commit_low(trx);
	}

	/* Release possible statement level resources */
@@ -589,6 +667,8 @@ innobase_report_binlog_offset_and_commit(

	trx = (trx_t*)trx_handle;

	ut_a(trx != NULL);

	trx->mysql_log_file_name = log_file_name;  	
	trx->mysql_log_offset = (ib_longlong)end_offset;
	
@@ -629,7 +709,7 @@ innobase_rollback(

	trx_mark_sql_stat_end(trx);

	DBUG_RETURN(convert_error_code_to_mysql(error));
	DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}

/*********************************************************************
@@ -791,7 +871,6 @@ ha_innobase::open(

	ib_table = dict_table_get_and_increment_handle_count(
				      		     norm_name, NULL);

 	if (NULL == ib_table) {

	  	fprintf(stderr,
@@ -846,6 +925,9 @@ ha_innobase::open(

	auto_inc_counter_for_this_stat = 0;

	block_size = 16 * 1024;	/* Index block size in InnoDB: used by MySQL
				in query optimization */

	/* Init table lock structure */
	thr_lock_data_init(&share->lock,&lock,(void*) 0);

@@ -1365,7 +1447,8 @@ ha_innobase::write_row(

			if (error != DB_SUCCESS) {
			
				error = convert_error_code_to_mysql(error);
				error = convert_error_code_to_mysql(error,
								user_thd);
				goto func_exit;
			}	
			
@@ -1381,7 +1464,7 @@ ha_innobase::write_row(
					srv_conc_exit_innodb(prebuilt->trx);
			
					error = convert_error_code_to_mysql(
								error);
							error, user_thd);
					goto func_exit;
				}
			}	
@@ -1412,7 +1495,8 @@ ha_innobase::write_row(

			if (error != DB_SUCCESS) {
			
				error = convert_error_code_to_mysql(error);
				error = convert_error_code_to_mysql(error,
								user_thd);
				goto func_exit;
			}	
			
@@ -1452,7 +1536,7 @@ ha_innobase::write_row(

	prebuilt->trx->ignore_duplicates_in_insert = FALSE;

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, user_thd);

	/* Tell InnoDB server that there might be work for
	utility threads: */
@@ -1669,7 +1753,7 @@ ha_innobase::update_row(

	srv_conc_exit_innodb(prebuilt->trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, user_thd);

	/* Tell InnoDB server that there might be work for
	utility threads: */
@@ -1714,7 +1798,7 @@ ha_innobase::delete_row(

	srv_conc_exit_innodb(prebuilt->trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, user_thd);

	/* Tell the InnoDB server that there might be work for
	utility threads: */
@@ -1872,7 +1956,7 @@ ha_innobase::index_read(
		error = HA_ERR_KEY_NOT_FOUND;
		table->status = STATUS_NOT_FOUND;
	} else {
		error = convert_error_code_to_mysql(ret);
		error = convert_error_code_to_mysql(ret, user_thd);
		table->status = STATUS_NOT_FOUND;
	}

@@ -1891,7 +1975,7 @@ ha_innobase::change_active_index(
			InnoDB */
{
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
	KEY*		key=0;
	KEY*		key;

  	statistic_increment(ha_read_key_count, &LOCK_status);

@@ -1912,10 +1996,9 @@ ha_innobase::change_active_index(
	if (!prebuilt->index) {
		fprintf(stderr,
	"InnoDB: Could not find key n:o %u with name %s from dict cache\n"
	"InnoDB: for table %s\n", keynr, key ? key->name : "NULL",
			prebuilt->table->name);
	"InnoDB: for table %s\n", keynr, key->name, prebuilt->table->name);

		DBUG_RETURN(1);
		return(1);
	}
	
	assert(prebuilt->search_tuple);
@@ -1931,7 +2014,7 @@ ha_innobase::change_active_index(

	build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW);

	DBUG_RETURN(0);
	return(0);
}

/**************************************************************************
@@ -1999,7 +2082,7 @@ ha_innobase::general_fetch(
		error = HA_ERR_END_OF_FILE;
		table->status = STATUS_NOT_FOUND;
	} else {
		error = convert_error_code_to_mysql(ret);
		error = convert_error_code_to_mysql(ret, user_thd);
		table->status = STATUS_NOT_FOUND;
	}

@@ -2301,7 +2384,7 @@ create_table_def(

	error = row_create_table_for_mysql(table, trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, NULL);

	DBUG_RETURN(error);
}
@@ -2358,7 +2441,7 @@ create_index(

	error = row_create_index_for_mysql(index, trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, NULL);

	DBUG_RETURN(error);
}
@@ -2384,7 +2467,7 @@ create_clustered_index_when_no_primary(
				      0, DICT_CLUSTERED, 0);
	error = row_create_index_for_mysql(index, trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, NULL);

	return(error);
}
@@ -2414,19 +2497,36 @@ ha_innobase::create(

  	DBUG_ENTER("ha_innobase::create");

	assert(current_thd != NULL);

	trx = trx_allocate_for_mysql();

	if (current_thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
		trx->check_foreigns = FALSE;
	}

	if (current_thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
		trx->check_unique_secondary = FALSE;
	}

	fn_format(name2, name, "", "",2);	// Remove the .frm extension

	normalize_table_name(norm_name, name2);

	/* Latch the InnoDB data dictionary exclusive so that no deadlocks
	or lock waits can happen in it during a table create operation.
	(Drop table etc. do this latching in row0mysql.c.) */

	row_mysql_lock_data_dictionary();

	/* Create the table definition in InnoDB */

  	error = create_table_def(trx, form, norm_name);
  	
  	if (error) {
		innobase_commit_low(trx);

		trx_commit_for_mysql(trx);
		row_mysql_unlock_data_dictionary();

  		trx_free_for_mysql(trx);

@@ -2458,7 +2558,9 @@ ha_innobase::create(
		error = create_clustered_index_when_no_primary(trx,
							norm_name);
  		if (error) {
			trx_commit_for_mysql(trx);
			innobase_commit_low(trx);

			row_mysql_unlock_data_dictionary();

			trx_free_for_mysql(trx);

@@ -2471,7 +2573,9 @@ ha_innobase::create(
		first */
	    	if ((error = create_index(trx, form, norm_name,
					  (uint) primary_key_no))) {
			trx_commit_for_mysql(trx);
			innobase_commit_low(trx);

			row_mysql_unlock_data_dictionary();

  			trx_free_for_mysql(trx);

@@ -2485,7 +2589,9 @@ ha_innobase::create(

    			if ((error = create_index(trx, form, norm_name, i))) {

				trx_commit_for_mysql(trx);
				innobase_commit_low(trx);

				row_mysql_unlock_data_dictionary();

				trx_free_for_mysql(trx);

@@ -2497,17 +2603,21 @@ ha_innobase::create(
	error = row_table_add_foreign_constraints(trx,
				create_info->create_statement, norm_name);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, NULL);

	if (error) {
		trx_commit_for_mysql(trx);
		innobase_commit_low(trx);

		row_mysql_unlock_data_dictionary();

  		trx_free_for_mysql(trx);

		DBUG_RETURN(error);
	}

  	trx_commit_for_mysql(trx);
  	innobase_commit_low(trx);

	row_mysql_unlock_data_dictionary();

	/* Flush the log to reduce probability that the .frm files and
	the InnoDB data dictionary get out-of-sync if the user runs
@@ -2575,11 +2685,11 @@ ha_innobase::delete_table(

	srv_active_wake_master_thread();

  	trx_commit_for_mysql(trx);
  	innobase_commit_low(trx);

  	trx_free_for_mysql(trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, NULL);

	DBUG_RETURN(error);
}
@@ -2640,10 +2750,10 @@ innobase_drop_database(

	srv_active_wake_master_thread();

  	trx_commit_for_mysql(trx);
  	innobase_commit_low(trx);
  	trx_free_for_mysql(trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, NULL);

	return(error);
}
@@ -2693,10 +2803,10 @@ ha_innobase::rename_table(

	srv_active_wake_master_thread();

  	trx_commit_for_mysql(trx);
  	innobase_commit_low(trx);
  	trx_free_for_mysql(trx);

	error = convert_error_code_to_mysql(error);
	error = convert_error_code_to_mysql(error, NULL);

	DBUG_RETURN(error);
}
@@ -2814,7 +2924,7 @@ ha_innobase::estimate_number_of_rows(void)

	estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
	
	DBUG_RETURN((ha_rows) estimate);
	return((ha_rows) estimate);
}

/*************************************************************************