Commit 014214d0 authored by Sergei Golubchik's avatar Sergei Golubchik

percona-server-5.5.39-36.0

parent a9e8b577
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1648,6 +1648,8 @@ dict_create_add_foreign_to_dictionary( ...@@ -1648,6 +1648,8 @@ dict_create_add_foreign_to_dictionary(
ulint i; ulint i;
pars_info_t* info; pars_info_t* info;
ut_ad(mutex_own(&(dict_sys->mutex)));
if (foreign->id == NULL) { if (foreign->id == NULL) {
/* Generate a new constraint id */ /* Generate a new constraint id */
ulint namelen = strlen(table->name); ulint namelen = strlen(table->name);
...@@ -1726,6 +1728,37 @@ dict_create_add_foreign_to_dictionary( ...@@ -1726,6 +1728,37 @@ dict_create_add_foreign_to_dictionary(
"END;\n" "END;\n"
, table, foreign, trx); , table, foreign, trx);
if (error == DB_SUCCESS) {
if (foreign->foreign_table != NULL) {
ib_rbt_t* rbt
= foreign->foreign_table->foreign_rbt;
if (rbt == NULL) {
rbt = dict_table_init_foreign_rbt(
foreign->foreign_table);
} else {
rbt_delete(rbt, foreign->id);
}
rbt_insert(rbt, foreign->id, &foreign);
}
if (foreign->referenced_table != NULL) {
ib_rbt_t* rbt
= foreign->referenced_table->referenced_rbt;
if (rbt == NULL) {
rbt = dict_table_init_referenced_rbt(
foreign->referenced_table);
} else {
rbt_delete(rbt, foreign->id);
}
rbt_insert(rbt, foreign->id, &foreign);
}
}
return(error); return(error);
} }
...@@ -1750,6 +1783,7 @@ dict_create_add_foreigns_to_dictionary( ...@@ -1750,6 +1783,7 @@ dict_create_add_foreigns_to_dictionary(
dict_foreign_t* foreign; dict_foreign_t* foreign;
ulint number = start_id + 1; ulint number = start_id + 1;
ulint error; ulint error;
DBUG_ENTER("dict_create_add_foreigns_to_dictionary");
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
...@@ -1758,7 +1792,7 @@ dict_create_add_foreigns_to_dictionary( ...@@ -1758,7 +1792,7 @@ dict_create_add_foreigns_to_dictionary(
"InnoDB: table SYS_FOREIGN not found" "InnoDB: table SYS_FOREIGN not found"
" in internal data dictionary\n"); " in internal data dictionary\n");
return(DB_ERROR); DBUG_RETURN(DB_ERROR);
} }
for (foreign = UT_LIST_GET_FIRST(table->foreign_list); for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
...@@ -1770,9 +1804,9 @@ dict_create_add_foreigns_to_dictionary( ...@@ -1770,9 +1804,9 @@ dict_create_add_foreigns_to_dictionary(
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
return(error); DBUG_RETURN(error);
} }
} }
return(DB_SUCCESS); DBUG_RETURN(DB_SUCCESS);
} }
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -26,6 +26,7 @@ Created 1/8/1996 Heikki Tuuri ...@@ -26,6 +26,7 @@ Created 1/8/1996 Heikki Tuuri
#include <my_sys.h> #include <my_sys.h>
#include "dict0dict.h" #include "dict0dict.h"
#include "ut0rbt.h"
#ifdef UNIV_NONINL #ifdef UNIV_NONINL
#include "dict0dict.ic" #include "dict0dict.ic"
...@@ -193,6 +194,7 @@ UNIV_INTERN FILE* dict_foreign_err_file = NULL; ...@@ -193,6 +194,7 @@ UNIV_INTERN FILE* dict_foreign_err_file = NULL;
/* mutex protecting the foreign and unique error buffers */ /* mutex protecting the foreign and unique error buffers */
UNIV_INTERN mutex_t dict_foreign_err_mutex; UNIV_INTERN mutex_t dict_foreign_err_mutex;
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/******************************************************************//** /******************************************************************//**
Makes all characters in a NUL-terminated UTF-8 string lower case. */ Makes all characters in a NUL-terminated UTF-8 string lower case. */
UNIV_INTERN UNIV_INTERN
...@@ -1110,6 +1112,10 @@ dict_table_rename_in_cache( ...@@ -1110,6 +1112,10 @@ dict_table_rename_in_cache(
UT_LIST_INIT(table->referenced_list); UT_LIST_INIT(table->referenced_list);
if (table->referenced_rbt != NULL) {
rbt_clear(table->referenced_rbt);
}
return(TRUE); return(TRUE);
} }
...@@ -1120,6 +1126,10 @@ dict_table_rename_in_cache( ...@@ -1120,6 +1126,10 @@ dict_table_rename_in_cache(
foreign = UT_LIST_GET_FIRST(table->foreign_list); foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) { while (foreign != NULL) {
/* The id will be changed. So remove old one */
rbt_delete(foreign->foreign_table->foreign_rbt, foreign->id);
if (ut_strlen(foreign->foreign_table_name) if (ut_strlen(foreign->foreign_table_name)
< ut_strlen(table->name)) { < ut_strlen(table->name)) {
/* Allocate a longer name buffer; /* Allocate a longer name buffer;
...@@ -1267,6 +1277,9 @@ dict_table_rename_in_cache( ...@@ -1267,6 +1277,9 @@ dict_table_rename_in_cache(
mem_free(old_id); mem_free(old_id);
} }
rbt_insert(foreign->foreign_table->foreign_rbt,
foreign->id, &foreign);
foreign = UT_LIST_GET_NEXT(foreign_list, foreign); foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
} }
...@@ -2614,22 +2627,40 @@ dict_foreign_remove_from_cache( ...@@ -2614,22 +2627,40 @@ dict_foreign_remove_from_cache(
/*===========================*/ /*===========================*/
dict_foreign_t* foreign) /*!< in, own: foreign constraint */ dict_foreign_t* foreign) /*!< in, own: foreign constraint */
{ {
DBUG_ENTER("dict_foreign_remove_from_cache");
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
ut_a(foreign); ut_a(foreign);
if (foreign->referenced_table) { if (foreign->referenced_table) {
ib_rbt_t* rbt;
UT_LIST_REMOVE(referenced_list, UT_LIST_REMOVE(referenced_list,
foreign->referenced_table->referenced_list, foreign->referenced_table->referenced_list,
foreign); foreign);
rbt = foreign->referenced_table->referenced_rbt;
if (rbt != NULL) {
rbt_delete(rbt, foreign->id);
}
} }
if (foreign->foreign_table) { if (foreign->foreign_table) {
ib_rbt_t* rbt;
UT_LIST_REMOVE(foreign_list, UT_LIST_REMOVE(foreign_list,
foreign->foreign_table->foreign_list, foreign->foreign_table->foreign_list,
foreign); foreign);
rbt = foreign->foreign_table->foreign_rbt;
if (rbt != NULL) {
rbt_delete(rbt, foreign->id);
}
} }
dict_foreign_free(foreign); dict_foreign_free(foreign);
DBUG_VOID_RETURN;
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -2643,33 +2674,36 @@ dict_foreign_find( ...@@ -2643,33 +2674,36 @@ dict_foreign_find(
dict_table_t* table, /*!< in: table object */ dict_table_t* table, /*!< in: table object */
const char* id) /*!< in: foreign constraint id */ const char* id) /*!< in: foreign constraint id */
{ {
dict_foreign_t* foreign; const ib_rbt_node_t* node;
ut_ad(mutex_own(&(dict_sys->mutex)));
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign) { DBUG_ENTER("dict_foreign_find");
if (ut_strcmp(id, foreign->id) == 0) {
return(foreign); ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(dict_table_check_foreign_keys(table));
if (table->foreign_rbt != NULL) {
ut_a(UT_LIST_GET_LEN(table->foreign_list)
== rbt_size(table->foreign_rbt));
node = rbt_lookup(table->foreign_rbt, id);
if (node != NULL) {
DBUG_RETURN(*(dict_foreign_t**) node->value);
} }
} else {
foreign = UT_LIST_GET_NEXT(foreign_list, foreign); ut_a(UT_LIST_GET_LEN(table->foreign_list) == 0);
} }
foreign = UT_LIST_GET_FIRST(table->referenced_list); if (table->referenced_rbt != NULL) {
ut_a(UT_LIST_GET_LEN(table->referenced_list)
while (foreign) { == rbt_size(table->referenced_rbt));
if (ut_strcmp(id, foreign->id) == 0) { node = rbt_lookup(table->referenced_rbt, id);
if (node != NULL) {
return(foreign); DBUG_RETURN(*(dict_foreign_t**) node->value);
} }
} else {
foreign = UT_LIST_GET_NEXT(referenced_list, foreign); ut_a(UT_LIST_GET_LEN(table->referenced_list) == 0);
} }
return(NULL); DBUG_RETURN(NULL);
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -2907,6 +2941,8 @@ dict_foreign_add_to_cache( ...@@ -2907,6 +2941,8 @@ dict_foreign_add_to_cache(
ibool added_to_referenced_list= FALSE; ibool added_to_referenced_list= FALSE;
FILE* ef = dict_foreign_err_file; FILE* ef = dict_foreign_err_file;
DBUG_ENTER("dict_foreign_add_to_cache");
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
for_table = dict_table_check_if_in_cache_low( for_table = dict_table_check_if_in_cache_low(
...@@ -2916,7 +2952,14 @@ dict_foreign_add_to_cache( ...@@ -2916,7 +2952,14 @@ dict_foreign_add_to_cache(
foreign->referenced_table_name_lookup); foreign->referenced_table_name_lookup);
ut_a(for_table || ref_table); ut_a(for_table || ref_table);
if (ref_table != NULL && ref_table->referenced_rbt == NULL) {
dict_table_init_referenced_rbt(ref_table);
}
if (for_table) { if (for_table) {
if (for_table->foreign_rbt == NULL) {
dict_table_init_foreign_rbt(for_table);
}
for_in_cache = dict_foreign_find(for_table, foreign->id); for_in_cache = dict_foreign_find(for_table, foreign->id);
} }
...@@ -2953,18 +2996,22 @@ dict_foreign_add_to_cache( ...@@ -2953,18 +2996,22 @@ dict_foreign_add_to_cache(
mem_heap_free(foreign->heap); mem_heap_free(foreign->heap);
} }
return(DB_CANNOT_ADD_CONSTRAINT); DBUG_RETURN(DB_CANNOT_ADD_CONSTRAINT);
} }
for_in_cache->referenced_table = ref_table; for_in_cache->referenced_table = ref_table;
for_in_cache->referenced_index = index; for_in_cache->referenced_index = index;
UT_LIST_ADD_LAST(referenced_list, UT_LIST_ADD_LAST(referenced_list,
ref_table->referenced_list, ref_table->referenced_list, for_in_cache);
for_in_cache);
added_to_referenced_list = TRUE; added_to_referenced_list = TRUE;
rbt_insert(ref_table->referenced_rbt,
for_in_cache->id, &for_in_cache);
} }
if (for_in_cache->foreign_table == NULL && for_table) { if (for_in_cache->foreign_table == NULL && for_table) {
index = dict_foreign_find_index( index = dict_foreign_find_index(
for_table, for_table,
for_in_cache->foreign_col_names, for_in_cache->foreign_col_names,
...@@ -2993,22 +3040,28 @@ dict_foreign_add_to_cache( ...@@ -2993,22 +3040,28 @@ dict_foreign_add_to_cache(
referenced_list, referenced_list,
ref_table->referenced_list, ref_table->referenced_list,
for_in_cache); for_in_cache);
rbt_delete(ref_table->referenced_rbt,
for_in_cache->id);
} }
mem_heap_free(foreign->heap); mem_heap_free(foreign->heap);
} }
return(DB_CANNOT_ADD_CONSTRAINT); DBUG_RETURN(DB_CANNOT_ADD_CONSTRAINT);
} }
for_in_cache->foreign_table = for_table; for_in_cache->foreign_table = for_table;
for_in_cache->foreign_index = index; for_in_cache->foreign_index = index;
UT_LIST_ADD_LAST(foreign_list, UT_LIST_ADD_LAST(foreign_list,
for_table->foreign_list, for_table->foreign_list,
for_in_cache); for_in_cache);
rbt_insert(for_table->foreign_rbt, for_in_cache->id,
&for_in_cache);
} }
return(DB_SUCCESS); DBUG_RETURN(DB_SUCCESS);
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
......
...@@ -1834,6 +1834,8 @@ dict_load_table( ...@@ -1834,6 +1834,8 @@ dict_load_table(
const char* err_msg; const char* err_msg;
mtr_t mtr; mtr_t mtr;
DBUG_ENTER("dict_load_table");
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
heap = mem_heap_create(32000); heap = mem_heap_create(32000);
...@@ -1867,7 +1869,7 @@ err_exit: ...@@ -1867,7 +1869,7 @@ err_exit:
mtr_commit(&mtr); mtr_commit(&mtr);
mem_heap_free(heap); mem_heap_free(heap);
return(NULL); DBUG_RETURN(NULL);
} }
field = rec_get_nth_field_old(rec, 0, &len); field = rec_get_nth_field_old(rec, 0, &len);
...@@ -2029,8 +2031,8 @@ err_exit: ...@@ -2029,8 +2031,8 @@ err_exit:
#endif /* 0 */ #endif /* 0 */
func_exit: func_exit:
mem_heap_free(heap); mem_heap_free(heap);
ut_ad(table == NULL || dict_table_check_foreign_keys(table));
return(table); DBUG_RETURN(table);
} }
/***********************************************************************//** /***********************************************************************//**
...@@ -2255,6 +2257,8 @@ dict_load_foreign( ...@@ -2255,6 +2257,8 @@ dict_load_foreign(
dict_table_t* for_table; dict_table_t* for_table;
dict_table_t* ref_table; dict_table_t* ref_table;
DBUG_ENTER("dict_load_foreign");
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
heap2 = mem_heap_create(1000); heap2 = mem_heap_create(1000);
...@@ -2287,7 +2291,7 @@ dict_load_foreign( ...@@ -2287,7 +2291,7 @@ dict_load_foreign(
mtr_commit(&mtr); mtr_commit(&mtr);
mem_heap_free(heap2); mem_heap_free(heap2);
return(DB_ERROR); DBUG_RETURN(DB_ERROR);
} }
field = rec_get_nth_field_old(rec, 0, &len); field = rec_get_nth_field_old(rec, 0, &len);
...@@ -2303,7 +2307,7 @@ dict_load_foreign( ...@@ -2303,7 +2307,7 @@ dict_load_foreign(
mtr_commit(&mtr); mtr_commit(&mtr);
mem_heap_free(heap2); mem_heap_free(heap2);
return(DB_ERROR); DBUG_RETURN(DB_ERROR);
} }
/* Read the table names and the number of columns associated /* Read the table names and the number of columns associated
...@@ -2400,7 +2404,7 @@ dict_load_foreign( ...@@ -2400,7 +2404,7 @@ dict_load_foreign(
a new foreign key constraint but loading one from the data a new foreign key constraint but loading one from the data
dictionary. */ dictionary. */
return(dict_foreign_add_to_cache(foreign, check_charsets, ignore_err)); DBUG_RETURN(dict_foreign_add_to_cache(foreign, check_charsets, ignore_err));
} }
/***********************************************************************//** /***********************************************************************//**
...@@ -2435,6 +2439,8 @@ dict_load_foreigns( ...@@ -2435,6 +2439,8 @@ dict_load_foreigns(
ulint err; ulint err;
mtr_t mtr; mtr_t mtr;
DBUG_ENTER("dict_load_foreigns");
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
sys_foreign = dict_table_get_low("SYS_FOREIGN", DICT_ERR_IGNORE_NONE); sys_foreign = dict_table_get_low("SYS_FOREIGN", DICT_ERR_IGNORE_NONE);
...@@ -2446,7 +2452,7 @@ dict_load_foreigns( ...@@ -2446,7 +2452,7 @@ dict_load_foreigns(
"InnoDB: Error: no foreign key system tables" "InnoDB: Error: no foreign key system tables"
" in the database\n"); " in the database\n");
return(DB_ERROR); DBUG_RETURN(DB_ERROR);
} }
ut_a(!dict_table_is_comp(sys_foreign)); ut_a(!dict_table_is_comp(sys_foreign));
...@@ -2526,7 +2532,7 @@ loop: ...@@ -2526,7 +2532,7 @@ loop:
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
return(err); DBUG_RETURN(err);
} }
mtr_start(&mtr); mtr_start(&mtr);
...@@ -2555,5 +2561,74 @@ load_next_index: ...@@ -2555,5 +2561,74 @@ load_next_index:
goto start_load; goto start_load;
} }
return(DB_SUCCESS); DBUG_RETURN(DB_SUCCESS);
}
/********************************************************************//**
Check if dict_table_t::foreign_rbt and dict_table::foreign_list
contain the same set of foreign key objects; and check if
dict_table_t::referenced_rbt and dict_table::referenced_list contain
the same set of foreign key objects.
@return TRUE if correct, FALSE otherwise. */
ibool
dict_table_check_foreign_keys(
/*==========================*/
const dict_table_t* table) /* in: table object to check */
{
dict_foreign_t* foreign;
const ib_rbt_node_t* node;
ut_ad(mutex_own(&(dict_sys->mutex)));
if (table->foreign_rbt == NULL) {
if (UT_LIST_GET_LEN(table->foreign_list) > 0) {
return(FALSE);
}
} else {
if (UT_LIST_GET_LEN(table->foreign_list)
!= rbt_size(table->foreign_rbt)) {
return(FALSE);
}
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) {
node = rbt_lookup(table->foreign_rbt, foreign->id);
if (node == NULL) {
return(FALSE);
}
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
}
if (table->referenced_rbt == NULL ) {
if (UT_LIST_GET_LEN(table->referenced_list) > 0) {
return(FALSE);
}
} else {
if (UT_LIST_GET_LEN(table->referenced_list)
!= rbt_size(table->referenced_rbt)) {
return(FALSE);
}
foreign = UT_LIST_GET_FIRST(table->referenced_list);
while (foreign != NULL) {
node = rbt_lookup(table->referenced_rbt, foreign->id);
if (node == NULL) {
return(FALSE);
}
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
}
return(TRUE);
} }
...@@ -66,6 +66,7 @@ dict_mem_table_create( ...@@ -66,6 +66,7 @@ dict_mem_table_create(
{ {
dict_table_t* table; dict_table_t* table;
mem_heap_t* heap; mem_heap_t* heap;
DBUG_ENTER("dict_mem_table_create");
ut_ad(name); ut_ad(name);
ut_a(!(flags & (~0 << DICT_TF2_BITS))); ut_a(!(flags & (~0 << DICT_TF2_BITS)));
...@@ -100,8 +101,11 @@ dict_mem_table_create( ...@@ -100,8 +101,11 @@ dict_mem_table_create(
table->is_corrupt = FALSE; table->is_corrupt = FALSE;
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
table->foreign_rbt = NULL;
table->referenced_rbt = NULL;
ut_d(table->magic_n = DICT_TABLE_MAGIC_N); ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
return(table); DBUG_RETURN(table);
} }
/****************************************************************//** /****************************************************************//**
...@@ -120,6 +124,15 @@ dict_mem_table_free( ...@@ -120,6 +124,15 @@ dict_mem_table_free(
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
mutex_free(&(table->autoinc_mutex)); mutex_free(&(table->autoinc_mutex));
#endif /* UNIV_HOTBACKUP */ #endif /* UNIV_HOTBACKUP */
if (table->foreign_rbt != NULL) {
rbt_free(table->foreign_rbt);
}
if (table->referenced_rbt != NULL) {
rbt_free(table->referenced_rbt);
}
ut_free(table->name); ut_free(table->name);
mem_heap_free(table->heap); mem_heap_free(table->heap);
} }
......
...@@ -8995,16 +8995,6 @@ ha_innobase::read_time( ...@@ -8995,16 +8995,6 @@ ha_innobase::read_time(
return(ranges + (double) rows / (double) total_rows * time_for_scan); 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);
}
/*********************************************************************//** /*********************************************************************//**
Calculates the key number used inside MySQL for an Innobase index. We will Calculates the key number used inside MySQL for an Innobase index. We will
first check the "index translation table" for a match of the index to get first check the "index translation table" for a match of the index to get
......
...@@ -141,7 +141,6 @@ class ha_innobase: public handler ...@@ -141,7 +141,6 @@ class ha_innobase: public handler
double scan_time(); double scan_time();
double read_time(uint index, uint ranges, ha_rows rows); double read_time(uint index, uint ranges, ha_rows rows);
my_bool is_fake_change_enabled(THD *thd); my_bool is_fake_change_enabled(THD *thd);
bool is_corrupt() const;
int write_row(uchar * buf); int write_row(uchar * buf);
int update_row(const uchar * old_data, uchar * new_data); int update_row(const uchar * old_data, uchar * new_data);
......
...@@ -42,6 +42,7 @@ Created July 18, 2007 Vasil Dimov ...@@ -42,6 +42,7 @@ Created July 18, 2007 Vasil Dimov
#include "i_s.h" #include "i_s.h"
#include <sql_plugin.h> #include <sql_plugin.h>
#include <mysql/innodb_priv.h> #include <mysql/innodb_priv.h>
#include <debug_sync.h>
extern "C" { extern "C" {
#include "btr0pcur.h" /* for file sys_tables related info. */ #include "btr0pcur.h" /* for file sys_tables related info. */
...@@ -2708,6 +2709,19 @@ i_s_innodb_buffer_page_fill( ...@@ -2708,6 +2709,19 @@ i_s_innodb_buffer_page_fill(
table_name = mem_heap_strdup(heap, table_name = mem_heap_strdup(heap,
index->table_name); index->table_name);
DBUG_EXECUTE_IF("mysql_test_print_index_type",
{
char idx_type[3];
ut_snprintf(idx_type,
sizeof(idx_type),
"%d",
index->type);
index_name=mem_heap_strcat(heap,
index_name,
idx_type);
};);
} }
mutex_exit(&dict_sys->mutex); mutex_exit(&dict_sys->mutex);
...@@ -7511,12 +7525,23 @@ i_s_innodb_changed_pages_fill( ...@@ -7511,12 +7525,23 @@ i_s_innodb_changed_pages_fill(
limit_lsn_range_from_condition(table, cond, &min_lsn, limit_lsn_range_from_condition(table, cond, &min_lsn,
&max_lsn); &max_lsn);
} }
/* If the log tracker is running and our max_lsn > current tracked LSN,
cap the max lsn so that we don't try to read any partial runs as the
tracked LSN advances. */
if (srv_track_changed_pages) {
ib_uint64_t tracked_lsn = log_get_tracked_lsn();
if (max_lsn > tracked_lsn)
max_lsn = tracked_lsn;
}
if (!log_online_bitmap_iterator_init(&i, min_lsn, max_lsn)) { if (!log_online_bitmap_iterator_init(&i, min_lsn, max_lsn)) {
my_error(ER_CANT_FIND_SYSTEM_REC, MYF(0)); my_error(ER_CANT_FIND_SYSTEM_REC, MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DEBUG_SYNC(thd, "i_s_innodb_changed_pages_range_ready");
while(log_online_bitmap_iterator_next(&i) && while(log_online_bitmap_iterator_next(&i) &&
(!srv_max_changed_pages || (!srv_max_changed_pages ||
output_rows_num < srv_max_changed_pages) && output_rows_num < srv_max_changed_pages) &&
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -39,6 +39,7 @@ Created 1/8/1996 Heikki Tuuri ...@@ -39,6 +39,7 @@ Created 1/8/1996 Heikki Tuuri
#include "ut0rnd.h" #include "ut0rnd.h"
#include "ut0byte.h" #include "ut0byte.h"
#include "trx0types.h" #include "trx0types.h"
#include "ut0rbt.h"
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
# include "sync0sync.h" # include "sync0sync.h"
...@@ -1355,6 +1356,42 @@ dict_table_set_corrupt_by_space( ...@@ -1355,6 +1356,42 @@ dict_table_set_corrupt_by_space(
ulint space_id, ulint space_id,
ibool need_mutex); ibool need_mutex);
/**********************************************************************//**
Compares the given foreign key identifier (the key in rb-tree) and the
foreign key identifier in the given fk object (value in rb-tree).
@return negative, 0, or positive if foreign_id is smaller, equal,
or greater than foreign_obj->id, respectively. */
UNIV_INLINE
int
dict_foreign_rbt_cmp(
/*=================*/
const void* foreign_id, /*!< in: the foreign key identifier
which is used as a key in rb-tree. */
const void* foreign_obj); /*!< in: the foreign object itself
which is used as value in rb-tree. */
/**********************************************************************//**
Allocate the table->foreign_rbt, which stores all the foreign objects
that is available in table->foreign_list.
@return the allocated rbt object */
UNIV_INLINE
ib_rbt_t*
dict_table_init_foreign_rbt(
/*========================*/
dict_table_t* table); /*!< in: the table object whose
table->foreign_rbt will be initialized */
/**********************************************************************//**
Allocate the table->referened_rbt, which stores all the foreign objects
that is available in table->referenced_list.
@return the allocated rbt object */
UNIV_INLINE
ib_rbt_t*
dict_table_init_referenced_rbt(
/*===========================*/
dict_table_t* table); /*!< in: the table object whose
table->referenced_rbt will be initialized */
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "dict0dict.ic" #include "dict0dict.ic"
#endif #endif
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -958,3 +958,62 @@ dict_index_is_corrupted( ...@@ -958,3 +958,62 @@ dict_index_is_corrupted(
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
Compares the given foreign key identifier (the key in rb-tree) and the
foreign key identifier in the given fk object (value in rb-tree).
@return negative, 0, or positive if foreign_id is smaller, equal,
or greater than foreign_obj->id, respectively. */
UNIV_INLINE
int
dict_foreign_rbt_cmp(
/*=================*/
const void* foreign_id, /*!< in: the foreign key identifier
which is used as a key in rb-tree. */
const void* foreign_obj) /*!< in: the foreign object itself
which is used as value in rb-tree. */
{
return(ut_strcmp((const char*) foreign_id,
(*(dict_foreign_t**) foreign_obj)->id));
}
/**********************************************************************//**
Allocate the table->foreign_rbt, which stores all the foreign objects
that is available in table->foreign_list. The caller must hold the
dict_sys->mutex.
@return the allocated rbt object */
UNIV_INLINE
ib_rbt_t*
dict_table_init_foreign_rbt(
/*========================*/
dict_table_t* table) /*!< in: the table object whose
table->foreign_rbt will be initialized */
{
ut_a(table->foreign_rbt == NULL);
ut_ad(mutex_own(&(dict_sys->mutex)));
table->foreign_rbt = rbt_create(sizeof(dict_foreign_t*),
dict_foreign_rbt_cmp);
ut_a(table->foreign_rbt != NULL);
return(table->foreign_rbt);
}
/**********************************************************************//**
Allocate the table->referened_rbt, which stores all the foreign objects
that is available in table->referenced_list. The caller must hold the
dict_sys->mutex.
@return the allocated rbt object */
UNIV_INLINE
ib_rbt_t*
dict_table_init_referenced_rbt(
/*===========================*/
dict_table_t* table) /*!< in: the table object whose
table->referenced_rbt will be initialized */
{
ut_a(table->referenced_rbt == NULL);
ut_ad(mutex_own(&(dict_sys->mutex)));
table->referenced_rbt = rbt_create(sizeof(dict_foreign_t*),
dict_foreign_rbt_cmp);
ut_a(table->referenced_rbt != NULL);
return(table->referenced_rbt);
}
...@@ -32,6 +32,7 @@ Created 4/24/1996 Heikki Tuuri ...@@ -32,6 +32,7 @@ Created 4/24/1996 Heikki Tuuri
#include "ut0byte.h" #include "ut0byte.h"
#include "mem0mem.h" #include "mem0mem.h"
#include "btr0types.h" #include "btr0types.h"
#include "ut0rbt.h"
/** enum that defines all 6 system table IDs */ /** enum that defines all 6 system table IDs */
enum dict_system_table_id { enum dict_system_table_id {
...@@ -344,6 +345,17 @@ dict_process_sys_stats_rec( ...@@ -344,6 +345,17 @@ dict_process_sys_stats_rec(
ulint* key_cols, /*!< out: KEY_COLS */ ulint* key_cols, /*!< out: KEY_COLS */
ib_uint64_t* diff_vals, /*!< out: DIFF_VALS */ ib_uint64_t* diff_vals, /*!< out: DIFF_VALS */
ib_uint64_t* non_null_vals); /*!< out: NON_NULL_VALS */ ib_uint64_t* non_null_vals); /*!< out: NON_NULL_VALS */
/********************************************************************//**
Check if dict_table_t::foreign_rbt and dict_table::foreign_list
contains the same set of foreign key objects; and check if
dict_table_t::referenced_rbt and dict_table::referenced_list contains
the same set of foreign key objects.
@return TRUE if correct, FALSE otherwise. */
ibool
dict_table_check_foreign_keys(
/*==========================*/
const dict_table_t* table); /* in: table object to check */
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "dict0load.ic" #include "dict0load.ic"
#endif #endif
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -43,6 +43,7 @@ Created 1/8/1996 Heikki Tuuri ...@@ -43,6 +43,7 @@ Created 1/8/1996 Heikki Tuuri
#include "ut0byte.h" #include "ut0byte.h"
#include "hash0hash.h" #include "hash0hash.h"
#include "trx0types.h" #include "trx0types.h"
#include "ut0rbt.h"
/** Type flags of an index: OR'ing of the flags is allowed to define a /** Type flags of an index: OR'ing of the flags is allowed to define a
combination of types */ combination of types */
...@@ -510,7 +511,6 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */ ...@@ -510,7 +511,6 @@ a foreign key constraint is enforced, therefore RESTRICT just means no flag */
#define DICT_FOREIGN_ON_UPDATE_NO_ACTION 32 /*!< ON UPDATE NO ACTION */ #define DICT_FOREIGN_ON_UPDATE_NO_ACTION 32 /*!< ON UPDATE NO ACTION */
/* @} */ /* @} */
/** Data structure for a database table. Most fields will be /** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */ initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_struct{ struct dict_table_struct{
...@@ -562,6 +562,14 @@ struct dict_table_struct{ ...@@ -562,6 +562,14 @@ struct dict_table_struct{
UT_LIST_BASE_NODE_T(dict_foreign_t) UT_LIST_BASE_NODE_T(dict_foreign_t)
referenced_list;/*!< list of foreign key constraints referenced_list;/*!< list of foreign key constraints
which refer to this table */ which refer to this table */
ib_rbt_t* foreign_rbt; /*!< a rb-tree of all foreign keys
listed in foreign_list, sorted by
foreign->id */
ib_rbt_t* referenced_rbt; /*!< a rb-tree of all foreign keys
listed in referenced_list, sorted by
foreign->id */
UT_LIST_NODE_T(dict_table_t) UT_LIST_NODE_T(dict_table_t)
table_LRU; /*!< node of the LRU list of tables */ table_LRU; /*!< node of the LRU list of tables */
ulint n_mysql_handles_opened; ulint n_mysql_handles_opened;
......
...@@ -581,6 +581,18 @@ void ...@@ -581,6 +581,18 @@ void
log_mem_free(void); log_mem_free(void);
/*==============*/ /*==============*/
/****************************************************************//**
Safely reads the log_sys->tracked_lsn value. Uses atomic operations
if available, otherwise this field is protected with the log system
mutex. The writer counterpart function is log_set_tracked_lsn() in
log0online.c.
@return log_sys->tracked_lsn value. */
UNIV_INLINE
ib_uint64_t
log_get_tracked_lsn(void);
/*=====================*/
extern log_t* log_sys; extern log_t* log_sys;
/* Values used as flags */ /* Values used as flags */
......
...@@ -459,3 +459,24 @@ log_free_check(void) ...@@ -459,3 +459,24 @@ log_free_check(void)
} }
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/****************************************************************//**
Safely reads the log_sys->tracked_lsn value. Uses atomic operations
if available, otherwise this field is protected with the log system
mutex. The writer counterpart function is log_set_tracked_lsn() in
log0online.c.
@return log_sys->tracked_lsn value. */
UNIV_INLINE
ib_uint64_t
log_get_tracked_lsn(void)
/*=====================*/
{
#ifdef HAVE_ATOMIC_BUILTINS_64
return os_atomic_increment_uint64(&log_sys->tracked_lsn, 0);
#else
ut_ad(mutex_own(&(log_sys->mutex)));
return log_sys->tracked_lsn;
#endif
}
...@@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */ ...@@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR) (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
#ifndef PERCONA_INNODB_VERSION #ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 35.2 #define PERCONA_INNODB_VERSION 36.0
#endif #endif
#define INNODB_VERSION_STR MYSQL_SERVER_VERSION #define INNODB_VERSION_STR MYSQL_SERVER_VERSION
......
...@@ -214,25 +214,6 @@ log_buf_pool_get_oldest_modification(void) ...@@ -214,25 +214,6 @@ log_buf_pool_get_oldest_modification(void)
return(lsn); return(lsn);
} }
/****************************************************************//**
Safely reads the log_sys->tracked_lsn value. Uses atomic operations
if available, otherwise this field is protected with the log system
mutex. The writer counterpart function is log_set_tracked_lsn() in
log0online.c.
@return log_sys->tracked_lsn value. */
UNIV_INLINE
ib_uint64_t
log_get_tracked_lsn()
{
#ifdef HAVE_ATOMIC_BUILTINS_64
return os_atomic_increment_uint64(&log_sys->tracked_lsn, 0);
#else
ut_ad(mutex_own(&(log_sys->mutex)));
return log_sys->tracked_lsn;
#endif
}
/****************************************************************//** /****************************************************************//**
Checks if the log groups have a big enough margin of free space in Checks if the log groups have a big enough margin of free space in
so that a new log entry can be written without overwriting log data so that a new log entry can be written without overwriting log data
......
...@@ -1202,6 +1202,9 @@ log_online_write_bitmap(void) ...@@ -1202,6 +1202,9 @@ log_online_write_bitmap(void)
bmp_tree_node = (ib_rbt_node_t*) bmp_tree_node = (ib_rbt_node_t*)
rbt_next(log_bmp_sys->modified_pages, bmp_tree_node); rbt_next(log_bmp_sys->modified_pages, bmp_tree_node);
DBUG_EXECUTE_IF("bitmap_page_2_write_error",
DBUG_SET("+d,bitmap_page_write_error"););
} }
rbt_reset(log_bmp_sys->modified_pages); rbt_reset(log_bmp_sys->modified_pages);
...@@ -1265,6 +1268,7 @@ log_online_follow_redo_log(void) ...@@ -1265,6 +1268,7 @@ log_online_follow_redo_log(void)
/*********************************************************************//** /*********************************************************************//**
Diagnose a bitmap file range setup failure and free the partially-initialized Diagnose a bitmap file range setup failure and free the partially-initialized
bitmap file range. */ bitmap file range. */
UNIV_COLD
static static
void void
log_online_diagnose_inconsistent_dir( log_online_diagnose_inconsistent_dir(
...@@ -1444,26 +1448,30 @@ log_online_setup_bitmap_file_range( ...@@ -1444,26 +1448,30 @@ log_online_setup_bitmap_file_range(
return FALSE; return FALSE;
} }
#ifdef UNIV_DEBUG if (!bitmap_files->files[0].seq_num
if (!bitmap_files->files[0].seq_num) { || bitmap_files->files[0].seq_num != first_file_seq_num) {
log_online_diagnose_inconsistent_dir(bitmap_files); log_online_diagnose_inconsistent_dir(bitmap_files);
return FALSE; return FALSE;
} }
ut_ad(bitmap_files->files[0].seq_num == first_file_seq_num);
{ {
size_t i; size_t i;
for (i = 1; i < bitmap_files->count; i++) { for (i = 1; i < bitmap_files->count; i++) {
if (!bitmap_files->files[i].seq_num) { if (!bitmap_files->files[i].seq_num) {
break; break;
} }
ut_ad(bitmap_files->files[i].seq_num if ((bitmap_files->files[i].seq_num
> bitmap_files->files[i - 1].seq_num); <= bitmap_files->files[i - 1].seq_num)
ut_ad(bitmap_files->files[i].start_lsn || (bitmap_files->files[i].start_lsn
>= bitmap_files->files[i - 1].start_lsn); < bitmap_files->files[i - 1].start_lsn)) {
log_online_diagnose_inconsistent_dir(
bitmap_files);
return FALSE;
}
} }
} }
#endif
return TRUE; return TRUE;
} }
...@@ -1590,6 +1598,17 @@ log_online_bitmap_iterator_init( ...@@ -1590,6 +1598,17 @@ log_online_bitmap_iterator_init(
{ {
ut_a(i); ut_a(i);
if (UNIV_UNLIKELY(min_lsn > max_lsn)) {
/* Empty range */
i->in_files.count = 0;
i->in_files.files = NULL;
i->in.file = os_file_invalid;
i->page = NULL;
i->failed = FALSE;
return TRUE;
}
if (!log_online_setup_bitmap_file_range(&i->in_files, min_lsn, if (!log_online_setup_bitmap_file_range(&i->in_files, min_lsn,
max_lsn)) { max_lsn)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment