summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-09-11 16:42:54 +0200
committerSergei Golubchik <sergii@pisem.net>2014-09-11 16:42:54 +0200
commit75796d9ecb50509b0c462c4aa67d40fee0d9fd24 (patch)
treefc721141a39cd7092ee84add25a3597a6e74ca4a /storage
parentc30a8442e8324f53f9157aabcc0330db0cd2e95f (diff)
parent993395bfa090266eb0ded41173130268a3ff01e7 (diff)
downloadmariadb-git-75796d9ecb50509b0c462c4aa67d40fee0d9fd24.tar.gz
InnoDB 5.6.20
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/CMakeLists.txt17
-rw-r--r--storage/innobase/api/api0api.cc23
-rw-r--r--storage/innobase/btr/btr0cur.cc43
-rw-r--r--storage/innobase/buf/buf0buf.cc8
-rw-r--r--storage/innobase/buf/buf0lru.cc27
-rw-r--r--storage/innobase/dict/dict0crea.cc44
-rw-r--r--storage/innobase/dict/dict0dict.cc351
-rw-r--r--storage/innobase/dict/dict0mem.cc27
-rw-r--r--storage/innobase/fil/fil0fil.cc51
-rw-r--r--storage/innobase/fts/fts0ast.cc136
-rw-r--r--storage/innobase/fts/fts0blex.cc8
-rw-r--r--storage/innobase/fts/fts0blex.l8
-rw-r--r--storage/innobase/fts/fts0fts.cc46
-rw-r--r--storage/innobase/fts/fts0pars.cc51
-rw-r--r--storage/innobase/fts/fts0pars.y22
-rw-r--r--storage/innobase/fts/fts0que.cc57
-rw-r--r--storage/innobase/fts/fts0tlex.cc6
-rw-r--r--storage/innobase/fts/fts0tlex.l6
-rw-r--r--storage/innobase/handler/ha_innodb.cc28
-rw-r--r--storage/innobase/handler/handler0alter.cc70
-rw-r--r--storage/innobase/include/buf0buf.h2
-rw-r--r--storage/innobase/include/buf0buf.ic6
-rw-r--r--storage/innobase/include/dict0crea.h34
-rw-r--r--storage/innobase/include/dict0mem.h134
-rw-r--r--storage/innobase/include/fil0fil.h12
-rw-r--r--storage/innobase/include/fts0ast.h69
-rw-r--r--storage/innobase/include/fts0fts.h1
-rw-r--r--storage/innobase/include/fts0pars.h6
-rw-r--r--storage/innobase/include/log0log.h6
-rw-r--r--storage/innobase/include/os0file.h2
-rw-r--r--storage/innobase/include/os0sync.h18
-rw-r--r--storage/innobase/include/sync0rw.ic9
-rw-r--r--storage/innobase/include/sync0sync.h2
-rw-r--r--storage/innobase/include/sync0sync.ic6
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/log/log0log.cc4
-rw-r--r--storage/innobase/log/log0recv.cc20
-rw-r--r--storage/innobase/os/os0file.cc8
-rw-r--r--storage/innobase/page/page0zip.cc16
-rw-r--r--storage/innobase/row/row0ins.cc26
-rw-r--r--storage/innobase/row/row0mysql.cc152
-rw-r--r--storage/innobase/row/row0upd.cc34
-rw-r--r--storage/innobase/srv/srv0start.cc20
-rw-r--r--storage/innobase/sync/sync0arr.cc7
-rw-r--r--storage/innobase/sync/sync0rw.cc11
-rw-r--r--storage/innobase/sync/sync0sync.cc8
-rw-r--r--storage/innobase/trx/trx0sys.cc22
47 files changed, 1017 insertions, 649 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index e227d953133..425d0bd0f1c 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -72,7 +72,6 @@ IF(NOT CMAKE_CROSSCOMPILING)
long x;
long y;
long res;
- char c;
x = 10;
y = 123;
@@ -93,6 +92,16 @@ IF(NOT CMAKE_CROSSCOMPILING)
if (res != 123 + 10 || x != 123 + 10) {
return(1);
}
+ return(0);
+ }"
+ HAVE_IB_GCC_ATOMIC_BUILTINS
+ )
+ CHECK_C_SOURCE_RUNS(
+ "
+ int main()
+ {
+ long res;
+ char c;
c = 10;
res = __sync_lock_test_and_set(&c, 123);
@@ -101,7 +110,7 @@ IF(NOT CMAKE_CROSSCOMPILING)
}
return(0);
}"
- HAVE_IB_GCC_ATOMIC_BUILTINS
+ HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE
)
CHECK_C_SOURCE_RUNS(
"#include<stdint.h>
@@ -148,6 +157,10 @@ IF(HAVE_IB_GCC_ATOMIC_BUILTINS)
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS=1)
ENDIF()
+IF(HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE)
+ ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_BYTE=1)
+ENDIF()
+
IF(HAVE_IB_GCC_ATOMIC_BUILTINS_64)
ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS_64=1)
ENDIF()
diff --git a/storage/innobase/api/api0api.cc b/storage/innobase/api/api0api.cc
index bb65dd82216..a060cbc7270 100644
--- a/storage/innobase/api/api0api.cc
+++ b/storage/innobase/api/api0api.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2008, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2008, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -2044,6 +2044,8 @@ ib_cursor_delete_row(
const rec_t* rec;
ib_bool_t page_format;
mtr_t mtr;
+ rec_t* copy = NULL;
+ byte ptr[UNIV_PAGE_SIZE_MAX];
page_format = static_cast<ib_bool_t>(
dict_table_is_comp(index->table));
@@ -2052,16 +2054,27 @@ ib_cursor_delete_row(
if (btr_pcur_restore_position(
BTR_SEARCH_LEAF, pcur, &mtr)) {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+
+ rec_offs_init(offsets_);
rec = btr_pcur_get_rec(pcur);
- } else {
- rec = NULL;
+
+ /* Since mtr will be commited, the rec
+ will not be protected. Make a copy of
+ the rec. */
+ offsets = rec_get_offsets(
+ rec, index, offsets, ULINT_UNDEFINED, &heap);
+ ut_ad(rec_offs_size(offsets) < UNIV_PAGE_SIZE_MAX);
+ copy = rec_copy(ptr, rec, offsets);
}
mtr_commit(&mtr);
- if (rec && !rec_get_deleted_flag(rec, page_format)) {
- err = ib_delete_row(cursor, pcur, rec);
+ if (copy && !rec_get_deleted_flag(copy, page_format)) {
+ err = ib_delete_row(cursor, pcur, copy);
} else {
err = DB_RECORD_NOT_FOUND;
}
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 34a72f360be..bd3d688a0c2 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -2557,6 +2557,31 @@ make_external:
ut_ad(flags & BTR_KEEP_POS_FLAG);
}
+ if (big_rec_vec) {
+ const ulint redo_10p = srv_log_file_size * UNIV_PAGE_SIZE / 10;
+ ulint total_blob_len = 0;
+
+ /* Calculate the total number of bytes for blob data */
+ for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
+ total_blob_len += big_rec_vec->fields[i].len;
+ }
+
+ if (total_blob_len > redo_10p) {
+ ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
+ " length (" ULINTPF ") is greater than"
+ " 10%% of the redo log file size (" UINT64PF
+ "). Please increase innodb_log_file_size.",
+ total_blob_len, srv_log_file_size);
+ if (n_reserved > 0) {
+ fil_space_release_free_extents(
+ index->space, n_reserved);
+ }
+
+ err = DB_TOO_BIG_RECORD;
+ goto err_exit;
+ }
+ }
+
/* Store state of explicit locks on rec on the page infimum record,
before deleting rec. The page infimum acts as a dummy carrier of the
locks, taking care also of lock releases, before we can move the locks
@@ -4378,6 +4403,7 @@ btr_store_big_rec_extern_fields(
buf_block_t** freed_pages = NULL;
ulint n_freed_pages = 0;
dberr_t error = DB_SUCCESS;
+ ulint total_blob_len = 0;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets));
@@ -4397,6 +4423,23 @@ btr_store_big_rec_extern_fields(
rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
+ const ulint redo_10p = (srv_log_file_size * UNIV_PAGE_SIZE / 10);
+
+ /* Calculate the total number of bytes for blob data */
+ for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
+ total_blob_len += big_rec_vec->fields[i].len;
+ }
+
+ if (total_blob_len > redo_10p) {
+ ut_ad(op == BTR_STORE_INSERT);
+ ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data length"
+ " (" ULINTPF ") is greater than 10%% of the"
+ " redo log file size (" UINT64PF "). Please"
+ " increase innodb_log_file_size.",
+ total_blob_len, srv_log_file_size);
+ return(DB_TOO_BIG_RECORD);
+ }
+
if (page_zip) {
int err;
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 4bae962e7d3..6f00d2e43b5 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -2882,12 +2882,6 @@ got_block:
ut_ad(buf_block_get_state(fix_block) == BUF_BLOCK_FILE_PAGE);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
- other systems, Valgrind could complain about uninitialized pad
- bytes. */
- UNIV_MEM_ASSERT_RW(&fix_block->page, sizeof(fix_block->page));
-#endif
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
@@ -5401,7 +5395,7 @@ buf_get_free_list_len(void)
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
-Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
+Inits a page to the buffer buf_pool, for use in mysqlbackup --restore. */
UNIV_INTERN
void
buf_page_init_for_backup_restore(
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index 64409e1993d..8574a6101e7 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -1818,13 +1818,6 @@ buf_LRU_free_page(
rw_lock_x_lock(hash_lock);
mutex_enter(block_mutex);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
- other systems, Valgrind could complain about uninitialized pad
- bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
-
if (!buf_page_can_relocate(bpage)) {
/* Do not free buffer fixed or I/O-fixed blocks. */
@@ -1862,12 +1855,6 @@ func_exit:
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
- other systems, Valgrind could complain about uninitialized pad
- bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
#ifdef UNIV_DEBUG
if (buf_debug_prints) {
@@ -1940,13 +1927,6 @@ func_exit:
ut_ad(prev_b->in_LRU_list);
ut_ad(buf_page_in_file(prev_b));
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no
- padding in buf_page_t. On other
- systems, Valgrind could complain about
- uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(prev_b, sizeof *prev_b);
-#endif
UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU,
prev_b, b);
@@ -2172,13 +2152,6 @@ buf_LRU_block_remove_hashed(
ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
ut_a(bpage->buf_fix_count == 0);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in
- buf_page_t. On other systems, Valgrind could complain
- about uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
-
buf_LRU_remove_block(bpage);
buf_pool->freed_page_clock += 1;
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index ff892749d4f..30523ff2af4 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-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
the terms of the GNU General Public License as published by the Free Software
@@ -1611,26 +1611,25 @@ dict_create_add_foreign_to_dictionary(
return(error);
}
-/********************************************************************//**
-Adds foreign key definitions to data dictionary tables in the database.
-@return error code or DB_SUCCESS */
+/** Adds the given set of foreign key objects to the dictionary tables
+in the database. This function does not modify the dictionary cache. The
+caller must ensure that all foreign key objects contain a valid constraint
+name in foreign->id.
+@param[in] local_fk_set set of foreign key objects, to be added to
+the dictionary tables
+@param[in] table table to which the foreign key objects in
+local_fk_set belong to
+@param[in,out] trx transaction
+@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_foreigns_to_dictionary(
/*===================================*/
- ulint start_id,/*!< in: if we are actually doing ALTER TABLE
- ADD CONSTRAINT, we want to generate constraint
- numbers which are bigger than in the table so
- far; we number the constraints from
- start_id + 1 up; start_id should be set to 0 if
- we are creating a new table, or if the table
- so far has no constraints for which the name
- was generated here */
- dict_table_t* table, /*!< in: table */
- trx_t* trx) /*!< in: transaction */
+ const dict_foreign_set& local_fk_set,
+ const dict_table_t* table,
+ trx_t* trx)
{
dict_foreign_t* foreign;
- ulint number = start_id + 1;
dberr_t error;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1643,17 +1642,12 @@ dict_create_add_foreigns_to_dictionary(
return(DB_ERROR);
}
- for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::const_iterator it = local_fk_set.begin();
+ it != local_fk_set.end();
+ ++it) {
- error = dict_create_add_foreign_id(&number, table->name,
- foreign);
-
- if (error != DB_SUCCESS) {
-
- return(error);
- }
+ foreign = *it;
+ ut_ad(foreign->id != NULL);
error = dict_create_add_foreign_to_dictionary(table->name,
foreign, trx);
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 30266262f37..51e62fefa6b 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -27,6 +27,7 @@ Created 1/8/1996 Heikki Tuuri
#include "dict0dict.h"
#include "fts0fts.h"
#include "fil0fil.h"
+#include <algorithm>
#ifdef UNIV_NONINL
#include "dict0dict.ic"
@@ -1251,8 +1252,8 @@ dict_table_can_be_evicted(
#endif /* UNIV_SYNC_DEBUG */
ut_a(table->can_be_evicted);
- ut_a(UT_LIST_GET_LEN(table->foreign_list) == 0);
- ut_a(UT_LIST_GET_LEN(table->referenced_list) == 0);
+ ut_a(table->foreign_set.empty());
+ ut_a(table->referenced_set.empty());
if (table->n_ref_count == 0) {
dict_index_t* index;
@@ -1468,6 +1469,22 @@ dict_index_find_on_id_low(
return(NULL);
}
+/** Function object to remove a foreign key constraint from the
+referenced_set of the referenced table. The foreign key object is
+also removed from the dictionary cache. The foreign key constraint
+is not removed from the foreign_set of the table containing the
+constraint. */
+struct dict_foreign_remove_partial
+{
+ void operator()(dict_foreign_t* foreign) {
+ dict_table_t* table = foreign->referenced_table;
+ if (table != NULL) {
+ table->referenced_set.erase(foreign);
+ }
+ dict_foreign_free(foreign);
+ }
+};
+
/**********************************************************************//**
Renames a table object.
@return TRUE if success */
@@ -1642,27 +1659,25 @@ dict_table_rename_in_cache(
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);
- }
+ std::for_each(table->foreign_set.begin(),
+ table->foreign_set.end(),
+ dict_foreign_remove_partial());
+ table->foreign_set.clear();
/* Reset table field in referencing constraints */
+ for (dict_foreign_set::iterator it
+ = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign != NULL) {
+ foreign = *it;
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);
+ /* Make the set of referencing constraints empty */
+ table->referenced_set.clear();
return(DB_SUCCESS);
}
@@ -1671,9 +1686,19 @@ dict_table_rename_in_cache(
the constraint id of new format >= 4.0.18 constraints. Note that at
this point we have already changed table->name to the new name. */
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
+ dict_foreign_set fk_set;
+
+ for (;;) {
+
+ dict_foreign_set::iterator it
+ = table->foreign_set.begin();
+
+ if (it == table->foreign_set.end()) {
+ break;
+ }
+
+ foreign = *it;
- while (foreign != NULL) {
if (ut_strlen(foreign->foreign_table_name)
< ut_strlen(table->name)) {
/* Allocate a longer name buffer;
@@ -1823,12 +1848,18 @@ dict_table_rename_in_cache(
mem_free(old_id);
}
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ table->foreign_set.erase(it);
+ fk_set.insert(foreign);
}
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ ut_a(table->foreign_set.empty());
+ table->foreign_set.swap(fk_set);
+
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
if (ut_strlen(foreign->referenced_table_name)
< ut_strlen(table->name)) {
@@ -1898,27 +1929,17 @@ dict_table_remove_from_cache_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-#if 0
- fputs("Removing table ", stderr);
- ut_print_name(stderr, table->name, ULINT_UNDEFINED);
- fputs(" from dictionary cache\n", stderr);
-#endif
-
/* Remove the foreign constraints from the cache */
-
- for (foreign = UT_LIST_GET_LAST(table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_LAST(table->foreign_list)) {
-
- dict_foreign_remove_from_cache(foreign);
- }
+ std::for_each(table->foreign_set.begin(), table->foreign_set.end(),
+ dict_foreign_remove_partial());
+ table->foreign_set.clear();
/* Reset table field in referencing constraints */
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
-
+ foreign = *it;
foreign->referenced_table = NULL;
foreign->referenced_index = NULL;
}
@@ -3134,7 +3155,7 @@ dict_table_is_referenced_by_foreign_key(
/*====================================*/
const dict_table_t* table) /*!< in: InnoDB table */
{
- return(UT_LIST_GET_LEN(table->referenced_list) > 0);
+ return(!table->referenced_set.empty());
}
/*********************************************************************//**
@@ -3154,9 +3175,11 @@ dict_table_get_referenced_constraint(
ut_ad(index != NULL);
ut_ad(table != NULL);
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
if (foreign->referenced_index == index) {
@@ -3185,9 +3208,11 @@ dict_table_get_foreign_constraint(
ut_ad(index != NULL);
ut_ad(table != NULL);
- for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
if (foreign->foreign_index == index) {
@@ -3198,17 +3223,6 @@ dict_table_get_foreign_constraint(
return(NULL);
}
-/*********************************************************************//**
-Frees a foreign key struct. */
-UNIV_INTERN
-void
-dict_foreign_free(
-/*==============*/
- dict_foreign_t* foreign) /*!< in, own: foreign key struct */
-{
- mem_heap_free(foreign->heap);
-}
-
/**********************************************************************//**
Removes a foreign constraint struct from the dictionary cache. */
UNIV_INTERN
@@ -3220,16 +3234,12 @@ dict_foreign_remove_from_cache(
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_a(foreign);
- if (foreign->referenced_table) {
- UT_LIST_REMOVE(referenced_list,
- foreign->referenced_table->referenced_list,
- foreign);
+ if (foreign->referenced_table != NULL) {
+ foreign->referenced_table->referenced_set.erase(foreign);
}
- if (foreign->foreign_table) {
- UT_LIST_REMOVE(foreign_list,
- foreign->foreign_table->foreign_list,
- foreign);
+ if (foreign->foreign_table != NULL) {
+ foreign->foreign_table->foreign_set.erase(foreign);
}
dict_foreign_free(foreign);
@@ -3243,33 +3253,21 @@ static
dict_foreign_t*
dict_foreign_find(
/*==============*/
- dict_table_t* table, /*!< in: table object */
- const char* id) /*!< in: foreign constraint id */
+ dict_table_t* table, /*!< in: table object */
+ dict_foreign_t* foreign) /*!< in: foreign constraint */
{
- dict_foreign_t* foreign;
-
ut_ad(mutex_own(&(dict_sys->mutex)));
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign) {
- if (ut_strcmp(id, foreign->id) == 0) {
-
- return(foreign);
- }
+ dict_foreign_set::iterator it = table->foreign_set.find(foreign);
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ if (it != table->foreign_set.end()) {
+ return(*it);
}
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign) {
- if (ut_strcmp(id, foreign->id) == 0) {
-
- return(foreign);
- }
+ it = table->referenced_set.find(foreign);
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
+ if (it != table->referenced_set.end()) {
+ return(*it);
}
return(NULL);
@@ -3407,11 +3405,11 @@ dict_foreign_add_to_cache(
ut_a(for_table || ref_table);
if (for_table) {
- for_in_cache = dict_foreign_find(for_table, foreign->id);
+ for_in_cache = dict_foreign_find(for_table, foreign);
}
if (!for_in_cache && ref_table) {
- for_in_cache = dict_foreign_find(ref_table, foreign->id);
+ for_in_cache = dict_foreign_find(ref_table, foreign);
}
if (for_in_cache) {
@@ -3448,9 +3446,12 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_table = ref_table;
for_in_cache->referenced_index = index;
- UT_LIST_ADD_LAST(referenced_list,
- ref_table->referenced_list,
- for_in_cache);
+
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = ref_table->referenced_set.insert(for_in_cache);
+
+ ut_a(ret.second); /* second is true if the insertion
+ took place */
added_to_referenced_list = TRUE;
}
@@ -3479,10 +3480,13 @@ dict_foreign_add_to_cache(
if (for_in_cache == foreign) {
if (added_to_referenced_list) {
- UT_LIST_REMOVE(
- referenced_list,
- ref_table->referenced_list,
- for_in_cache);
+ const dict_foreign_set::size_type n
+ = ref_table->referenced_set
+ .erase(for_in_cache);
+
+ ut_a(n == 1); /* the number of
+ elements removed must
+ be one */
}
mem_heap_free(foreign->heap);
@@ -3493,9 +3497,11 @@ dict_foreign_add_to_cache(
for_in_cache->foreign_table = for_table;
for_in_cache->foreign_index = index;
- UT_LIST_ADD_LAST(foreign_list,
- for_table->foreign_list,
- for_in_cache);
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = for_table->foreign_set.insert(for_in_cache);
+
+ ut_a(ret.second); /* second is true if the insertion
+ took place */
}
/* We need to move the table to the non-LRU end of the table LRU
@@ -4073,9 +4079,12 @@ dict_table_get_highest_foreign_id(
ut_a(table);
len = ut_strlen(table->name);
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
- while (foreign) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+ foreign = *it;
+
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
&& 0 == ut_memcmp(foreign->id, table->name, len)
&& 0 == ut_memcmp(foreign->id + len,
@@ -4094,8 +4103,6 @@ dict_table_get_highest_foreign_id(
}
}
}
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
return(biggest_id);
@@ -4156,6 +4163,7 @@ dict_create_foreign_constraints_low(
dict_table_t* referenced_table;
dict_table_t* table_to_alter;
ulint highest_id_so_far = 0;
+ ulint number = 1;
dict_index_t* index;
dict_foreign_t* foreign;
const char* ptr = sql_string;
@@ -4174,6 +4182,8 @@ dict_create_foreign_constraints_low(
const dict_col_t*columns[500];
const char* column_names[500];
const char* referenced_table_name;
+ dict_foreign_set local_fk_set;
+ dict_foreign_set_free local_fk_set_free(local_fk_set);
ut_ad(!srv_read_only_mode);
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -4238,6 +4248,7 @@ dict_create_foreign_constraints_low(
table_to_alter);
}
+ number = highest_id_so_far + 1;
/* Scan for foreign key declarations in a loop */
loop:
/* Scan either to "CONSTRAINT" or "FOREIGN", whichever is closer */
@@ -4282,7 +4293,7 @@ loop:
command, determine if there are any foreign keys, and
if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */
- if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
+ if (reject_fks && !local_fk_set.empty()) {
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4292,7 +4303,17 @@ loop:
to the data dictionary system tables on disk */
error = dict_create_add_foreigns_to_dictionary(
- highest_id_so_far, table, trx);
+ local_fk_set, table, trx);
+
+ if (error == DB_SUCCESS) {
+
+ table->foreign_set.insert(local_fk_set.begin(),
+ local_fk_set.end());
+ std::for_each(local_fk_set.begin(),
+ local_fk_set.end(),
+ dict_foreign_add_to_referenced_table());
+ local_fk_set.clear();
+ }
return(error);
}
@@ -4451,6 +4472,24 @@ col_loop1:
strcpy(foreign->id + db_len + 1, constraint_name);
}
+ if (foreign->id == NULL) {
+ error = dict_create_add_foreign_id(&number,
+ table->name, foreign);
+ if (error != DB_SUCCESS) {
+ dict_foreign_free(foreign);
+ return(error);
+ }
+ }
+
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = local_fk_set.insert(foreign);
+
+ if (!ret.second) {
+ /* A duplicate foreign key name has been found */
+ dict_foreign_free(foreign);
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
foreign->foreign_table = table;
foreign->foreign_table_name = mem_heap_strdup(
foreign->heap, table->name);
@@ -4476,8 +4515,6 @@ col_loop1:
checking of foreign key constraints! */
if (!success || (!referenced_table && trx->check_foreigns)) {
- dict_foreign_free(foreign);
-
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve table name close to:\n"
@@ -4491,7 +4528,6 @@ col_loop1:
ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -4506,7 +4542,6 @@ col_loop2:
i++;
if (!success) {
- dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
@@ -4527,7 +4562,6 @@ col_loop2:
ptr = dict_accept(cs, ptr, ")", &success);
if (!success || foreign->n_fields != i) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
@@ -4553,7 +4587,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "UPDATE", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
@@ -4591,7 +4624,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "ACTION", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
@@ -4610,7 +4642,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "SET", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -4619,7 +4650,6 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "NULL", &success);
if (!success) {
- dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -4632,8 +4662,6 @@ scan_on_conditions:
/* It is not sensible to define SET NULL
if the column is not allowed to be NULL! */
- dict_foreign_free(foreign);
-
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
@@ -4659,8 +4687,6 @@ try_find_index:
if (n_on_deletes > 1 || n_on_updates > 1) {
/* It is an error to define more than 1 action */
- dict_foreign_free(foreign);
-
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
@@ -4682,7 +4708,6 @@ try_find_index:
foreign->foreign_index,
TRUE, FALSE);
if (!index) {
- dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
@@ -4726,16 +4751,6 @@ try_find_index:
= mem_heap_strdup(foreign->heap, column_names[i]);
}
- /* We found an ok constraint definition: add to the lists */
-
- UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
-
- if (referenced_table) {
- UT_LIST_ADD_LAST(referenced_list,
- referenced_table->referenced_list,
- foreign);
- }
-
goto loop;
}
/**************************************************************************
@@ -4821,7 +4836,6 @@ dict_foreign_parse_drop_constraints(
const char*** constraints_to_drop) /*!< out: id's of the
constraints to drop */
{
- dict_foreign_t* foreign;
ibool success;
char* str;
size_t len;
@@ -4898,25 +4912,10 @@ loop:
(*constraints_to_drop)[*n] = id;
(*n)++;
- /* Look for the given constraint id */
-
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign != NULL) {
- if (0 == innobase_strcasecmp(foreign->id, id)
- || (strchr(foreign->id, '/')
- && 0 == innobase_strcasecmp(
- id,
- dict_remove_db_name(foreign->id)))) {
- /* Found */
- break;
- }
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
-
- if (foreign == NULL) {
+ if (std::find_if(table->foreign_set.begin(),
+ table->foreign_set.end(),
+ dict_foreign_matches_id(id))
+ == table->foreign_set.end()) {
if (!srv_read_only_mode) {
FILE* ef = dict_foreign_err_file;
@@ -5243,7 +5242,6 @@ dict_table_print(
dict_table_t* table) /*!< in: table */
{
dict_index_t* index;
- dict_foreign_t* foreign;
ulint i;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -5282,19 +5280,13 @@ dict_table_print(
dict_table_stats_unlock(table, RW_X_LATCH);
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- while (foreign != NULL) {
- dict_foreign_print_low(foreign);
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
- }
-
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
+ std::for_each(table->foreign_set.begin(),
+ table->foreign_set.end(),
+ dict_foreign_print_low);
- while (foreign != NULL) {
- dict_foreign_print_low(foreign);
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
+ std::for_each(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_print_low);
}
/**********************************************************************//**
@@ -5502,15 +5494,12 @@ dict_print_info_on_foreign_keys(
mutex_enter(&(dict_sys->mutex));
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
- if (foreign == NULL) {
- mutex_exit(&(dict_sys->mutex));
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
- return;
- }
+ foreign = *it;
- while (foreign != NULL) {
if (create_table_format) {
dict_print_info_on_foreign_key_in_create_format(
file, trx, foreign, TRUE);
@@ -5567,8 +5556,6 @@ dict_print_info_on_foreign_keys(
fputs(" ON UPDATE NO ACTION", file);
}
}
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
mutex_exit(&(dict_sys->mutex));
@@ -5900,10 +5887,11 @@ dict_foreign_replace_index(
ut_ad(index->to_be_dropped);
ut_ad(index->table == table);
- for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+ foreign = *it;
if (foreign->foreign_index == index) {
ut_ad(foreign->foreign_table == index->table);
@@ -5923,10 +5911,11 @@ dict_foreign_replace_index(
}
}
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+ foreign = *it;
if (foreign->referenced_index == index) {
ut_ad(foreign->referenced_table == index->table);
@@ -6246,24 +6235,24 @@ dict_table_schema_check(
}
}
- if (req_schema->n_foreign != UT_LIST_GET_LEN(table->foreign_list)) {
+ if (req_schema->n_foreign != table->foreign_set.size()) {
ut_snprintf(
errstr, errstr_sz,
- "Table %s has %lu foreign key(s) pointing to other "
- "tables, but it must have %lu.",
+ "Table %s has " ULINTPF " foreign key(s) pointing"
+ " to other tables, but it must have %lu.",
ut_format_name(req_schema->table_name,
TRUE, buf, sizeof(buf)),
- UT_LIST_GET_LEN(table->foreign_list),
+ static_cast<ulint>(table->foreign_set.size()),
req_schema->n_foreign);
return(DB_ERROR);
}
- if (req_schema->n_referenced != UT_LIST_GET_LEN(table->referenced_list)) {
+ if (req_schema->n_referenced != table->referenced_set.size()) {
ut_snprintf(
errstr, errstr_sz,
- "There are %lu foreign key(s) pointing to %s, "
+ "There are " ULINTPF " foreign key(s) pointing to %s, "
"but there must be %lu.",
- UT_LIST_GET_LEN(table->referenced_list),
+ static_cast<ulint>(table->referenced_set.size()),
ut_format_name(req_schema->table_name,
TRUE, buf, sizeof(buf)),
req_schema->n_referenced);
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 6310b2fd225..885627a61bc 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -124,6 +124,9 @@ dict_mem_table_create(
}
#endif /* !UNIV_HOTBACKUP */
+ new(&table->foreign_set) dict_foreign_set();
+ new(&table->referenced_set) dict_foreign_set();
+
return(table);
}
@@ -156,6 +159,9 @@ dict_mem_table_free(
dict_table_stats_latch_destroy(table);
+ table->foreign_set.~dict_foreign_set();
+ table->referenced_set.~dict_foreign_set();
+
ut_free(table->name);
mem_heap_free(table->heap);
}
@@ -326,10 +332,15 @@ dict_mem_table_col_rename_low(
table->col_names = col_names;
}
+ dict_foreign_t* foreign;
+
/* Replace the field names in every foreign key constraint. */
- for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
for (unsigned f = 0; f < foreign->n_fields; f++) {
/* These can point straight to
table->col_names, because the foreign key
@@ -341,10 +352,12 @@ dict_mem_table_col_rename_low(
}
}
- for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
for (unsigned f = 0; f < foreign->n_fields; f++) {
/* foreign->referenced_col_names[] need to be
copies, because the constraint may become
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index f4e5721caa7..08839f751ff 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -112,7 +112,7 @@ completes, we decrement the count and return the file node to the LRU-list if
the count drops to zero. */
/** When mysqld is run, the default directory "." is the mysqld datadir,
-but in the MySQL Embedded Server Library and ibbackup it is not the default
+but in the MySQL Embedded Server Library and mysqlbackup it is not the default
directory, and we must set the base file path explicitly */
UNIV_INTERN const char* fil_path_to_mysql_datadir = ".";
@@ -2017,8 +2017,8 @@ fil_check_first_page(
}
/*******************************************************************//**
-Reads the flushed lsn, arch no, and tablespace flag fields from a data
-file at database startup.
+Reads the flushed lsn, arch no, space_id and tablespace flag fields from
+the first page of a data file at database startup.
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
UNIV_INTERN
@@ -2055,16 +2055,19 @@ fil_read_first_page(
os_file_read(data_file, page, 0, UNIV_PAGE_SIZE);
- *flags = fsp_header_get_flags(page);
-
- *space_id = fsp_header_get_space_id(page);
-
- flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
-
+ /* The FSP_HEADER on page 0 is only valid for the first file
+ in a tablespace. So if this is not the first datafile, leave
+ *flags and *space_id as they were read from the first file and
+ do not validate the first page. */
if (!one_read_already) {
+ *flags = fsp_header_get_flags(page);
+ *space_id = fsp_header_get_space_id(page);
+
check_msg = fil_check_first_page(page);
}
+ flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
+
ut_free(buf);
if (check_msg) {
@@ -2272,13 +2275,13 @@ exists and the space id in it matches. Replays the create operation if a file
at that path does not exist yet. If the database directory for the file to be
created does not exist, then we create the directory, too.
-Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to the
-datadir that we should use in replaying the file operations.
+Note that mysqlbackup --apply-log sets fil_path_to_mysql_datadir to point to
+the datadir that we should use in replaying the file operations.
InnoDB recovery does not replay these fully since it always sets the space id
-to zero. But ibbackup does replay them. TODO: If remote tablespaces are used,
-ibbackup will only create tables in the default directory since MLOG_FILE_CREATE
-and MLOG_FILE_CREATE2 only know the tablename, not the path.
+to zero. But mysqlbackup does replay them. TODO: If remote tablespaces are
+used, mysqlbackup will only create tables in the default directory since
+MLOG_FILE_CREATE and MLOG_FILE_CREATE2 only know the tablename, not the path.
@return end of log record, or NULL if the record was not completely
contained between ptr and end_ptr */
@@ -2365,11 +2368,11 @@ fil_op_log_parse_or_replay(
}
/* Let us try to perform the file operation, if sensible. Note that
- ibbackup has at this stage already read in all space id info to the
+ mysqlbackup has at this stage already read in all space id info to the
fil0fil.cc data structures.
NOTE that our algorithm is not guaranteed to work correctly if there
- were renames of tables during the backup. See ibbackup code for more
+ were renames of tables during the backup. See mysqlbackup code for more
on the problem. */
switch (type) {
@@ -2784,12 +2787,12 @@ fil_delete_tablespace(
if (err == DB_SUCCESS) {
#ifndef UNIV_HOTBACKUP
/* Write a log record about the deletion of the .ibd
- file, so that ibbackup can replay it in the
+ file, so that mysqlbackup can replay it in the
--apply-log phase. We use a dummy mtr and the familiar
log write mechanism. */
mtr_t mtr;
- /* When replaying the operation in ibbackup, do not try
+ /* When replaying the operation in mysqlbackup, do not try
to write any log record */
mtr_start(&mtr);
@@ -4463,7 +4466,7 @@ will_not_choose:
" (< 4 pages 16 kB each),\n"
"InnoDB: or the space id in the file header"
" is not sensible.\n"
- "InnoDB: This can happen in an ibbackup run,"
+ "InnoDB: This can happen in an mysqlbackup run,"
" and is not dangerous.\n",
fsp->filepath, fsp->id, fsp->filepath, size);
os_file_close(fsp->file);
@@ -4500,7 +4503,7 @@ will_not_choose:
"InnoDB: because space %s with the same id\n"
"InnoDB: was scanned earlier. This can happen"
" if you have renamed tables\n"
- "InnoDB: during an ibbackup run.\n",
+ "InnoDB: during an mysqlbackup run.\n",
fsp->filepath, fsp->id, fsp->filepath,
space->name);
os_file_close(fsp->file);
@@ -5213,9 +5216,9 @@ file_extended:
#ifdef UNIV_HOTBACKUP
/********************************************************************//**
Extends all tablespaces to the size stored in the space header. During the
-ibbackup --apply-log phase we extended the spaces on-demand so that log records
-could be applied, but that may have left spaces still too small compared to
-the size stored in the space header. */
+mysqlbackup --apply-log phase we extended the spaces on-demand so that log
+records could be applied, but that may have left spaces still too small
+compared to the size stored in the space header. */
UNIV_INTERN
void
fil_extend_tablespaces_to_stored_len(void)
@@ -5712,7 +5715,7 @@ fil_io(
ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
#ifdef UNIV_HOTBACKUP
- /* In ibbackup do normal i/o, not aio */
+ /* In mysqlbackup do normal i/o, not aio */
if (type == OS_FILE_READ) {
ret = os_file_read(node->handle, buf, offset, len);
} else {
diff --git a/storage/innobase/fts/fts0ast.cc b/storage/innobase/fts/fts0ast.cc
index d6c19c0050a..dd48ffee14d 100644
--- a/storage/innobase/fts/fts0ast.cc
+++ b/storage/innobase/fts/fts0ast.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -83,11 +83,11 @@ UNIV_INTERN
fts_ast_node_t*
fts_ast_create_node_term(
/*=====================*/
- void* arg, /*!< in: ast state instance */
- const char* ptr) /*!< in: ast term string */
+ void* arg, /*!< in: ast state instance */
+ const fts_ast_string_t* ptr) /*!< in: ast term string */
{
fts_ast_state_t* state = static_cast<fts_ast_state_t*>(arg);
- ulint len = strlen(ptr);
+ ulint len = ptr->len;
ulint cur_pos = 0;
fts_ast_node_t* node = NULL;
fts_ast_node_t* node_list = NULL;
@@ -101,8 +101,9 @@ fts_ast_create_node_term(
cur_len = innobase_mysql_fts_get_token(
state->charset,
- reinterpret_cast<const byte*>(ptr) + cur_pos,
- reinterpret_cast<const byte*>(ptr) + len, &str, &offset);
+ reinterpret_cast<const byte*>(ptr->str) + cur_pos,
+ reinterpret_cast<const byte*>(ptr->str) + len,
+ &str, &offset);
if (cur_len == 0) {
break;
@@ -124,10 +125,8 @@ fts_ast_create_node_term(
node->type = FTS_AST_TERM;
- node->term.ptr = static_cast<byte*>(ut_malloc(
- str.f_len + 1));
- memcpy(node->term.ptr, str.f_str, str.f_len);
- node->term.ptr[str.f_len] = '\0';
+ node->term.ptr = fts_ast_string_create(
+ str.f_str, str.f_len);
fts_ast_state_add_node(
static_cast<fts_ast_state_t*>(arg), node);
@@ -160,25 +159,21 @@ UNIV_INTERN
fts_ast_node_t*
fts_ast_create_node_text(
/*=====================*/
- void* arg, /*!< in: ast state instance */
- const char* ptr) /*!< in: ast text string */
+ void* arg, /*!< in: ast state instance */
+ const fts_ast_string_t* ptr) /*!< in: ast text string */
{
- ulint len = strlen(ptr);
+ ulint len = ptr->len;
fts_ast_node_t* node = NULL;
+ /* Once we come here, the string must have at least 2 quotes ""
+ around the query string, which could be empty. Also the query
+ string may contain 0x00 in it, we don't treat it as null-terminated. */
+ ut_ad(len >= 2);
+ ut_ad(ptr->str[0] == '\"' && ptr->str[len - 1] == '\"');
- ut_ad(len >= 1);
-
- if (len <= 2) {
- /* There is a way to directly supply null terminator
- in the query string (by using 0x220022) and get here,
- and certainly it would not make a valid query text */
- ut_ad(ptr[0] == '\"');
-
- if (len == 2) {
- ut_ad(ptr[1] == '\"');
- }
-
+ if (len == 2) {
+ /* If the query string contains nothing except quotes,
+ it's obviously an invalid query. */
return(NULL);
}
@@ -188,11 +183,9 @@ fts_ast_create_node_text(
len -= 2;
node->type = FTS_AST_TEXT;
- node->text.ptr = static_cast<byte*>(ut_malloc(len + 1));
-
/*!< Skip copying the first quote */
- memcpy(node->text.ptr, ptr + 1, len);
- node->text.ptr[len] = 0;
+ node->text.ptr = fts_ast_string_create(
+ reinterpret_cast<const byte*>(ptr->str + 1), len);
node->text.distance = ULINT_UNDEFINED;
fts_ast_state_add_node((fts_ast_state_t*) arg, node);
@@ -275,14 +268,14 @@ fts_ast_free_node(
switch (node->type) {
case FTS_AST_TEXT:
if (node->text.ptr) {
- ut_free(node->text.ptr);
+ fts_ast_string_free(node->text.ptr);
node->text.ptr = NULL;
}
break;
case FTS_AST_TERM:
if (node->term.ptr) {
- ut_free(node->term.ptr);
+ fts_ast_string_free(node->term.ptr);
node->term.ptr = NULL;
}
break;
@@ -421,10 +414,10 @@ fts_ast_state_free(
fts_ast_node_t* next = node->next_alloc;
if (node->type == FTS_AST_TEXT && node->text.ptr) {
- ut_free(node->text.ptr);
+ fts_ast_string_free(node->text.ptr);
node->text.ptr = NULL;
} else if (node->type == FTS_AST_TERM && node->term.ptr) {
- ut_free(node->term.ptr);
+ fts_ast_string_free(node->term.ptr);
node->term.ptr = NULL;
}
@@ -445,11 +438,13 @@ fts_ast_node_print(
{
switch (node->type) {
case FTS_AST_TEXT:
- printf("TEXT: %s\n", node->text.ptr);
+ printf("TEXT: ");
+ fts_ast_string_print(node->text.ptr);
break;
case FTS_AST_TERM:
- printf("TERM: %s\n", node->term.ptr);
+ printf("TERM: ");
+ fts_ast_string_print(node->term.ptr);
break;
case FTS_AST_LIST:
@@ -628,3 +623,74 @@ fts_ast_visit(
return(error);
}
+
+/**
+Create an ast string object, with NUL-terminator, so the string
+has one more byte than len
+@param[in] str pointer to string
+@param[in] len length of the string
+@return ast string with NUL-terminator */
+UNIV_INTERN
+fts_ast_string_t*
+fts_ast_string_create(
+ const byte* str,
+ ulint len)
+{
+ fts_ast_string_t* ast_str;
+
+ ut_ad(len > 0);
+
+ ast_str = static_cast<fts_ast_string_t*>
+ (ut_malloc(sizeof(fts_ast_string_t)));
+ ast_str->str = static_cast<byte*>(ut_malloc(len + 1));
+
+ ast_str->len = len;
+ memcpy(ast_str->str, str, len);
+ ast_str->str[len] = '\0';
+
+ return(ast_str);
+}
+
+/**
+Free an ast string instance
+@param[in,out] ast_str string to free */
+UNIV_INTERN
+void
+fts_ast_string_free(
+ fts_ast_string_t* ast_str)
+{
+ if (ast_str != NULL) {
+ ut_free(ast_str->str);
+ ut_free(ast_str);
+ }
+}
+
+/**
+Translate ast string of type FTS_AST_NUMB to unsigned long by strtoul
+@param[in] str string to translate
+@param[in] base the base
+@return translated number */
+UNIV_INTERN
+ulint
+fts_ast_string_to_ul(
+ const fts_ast_string_t* ast_str,
+ int base)
+{
+ return(strtoul(reinterpret_cast<const char*>(ast_str->str),
+ NULL, base));
+}
+
+/**
+Print the ast string
+@param[in] str string to print */
+UNIV_INTERN
+void
+fts_ast_string_print(
+ const fts_ast_string_t* ast_str)
+{
+ for (ulint i = 0; i < ast_str->len; ++i) {
+ printf("%c", ast_str->str[i]);
+ }
+
+ printf("\n");
+}
diff --git a/storage/innobase/fts/fts0blex.cc b/storage/innobase/fts/fts0blex.cc
index f83523825d2..7d0acb00a3b 100644
--- a/storage/innobase/fts/fts0blex.cc
+++ b/storage/innobase/fts/fts0blex.cc
@@ -451,7 +451,7 @@ static yyconst flex_int16_t yy_chk[32] =
#line 1 "fts0blex.l"
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -806,7 +806,7 @@ case 3:
YY_RULE_SETUP
#line 53 "fts0blex.l"
{
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_NUMB);
}
@@ -815,7 +815,7 @@ case 4:
YY_RULE_SETUP
#line 59 "fts0blex.l"
{
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TERM);
}
@@ -824,7 +824,7 @@ case 5:
YY_RULE_SETUP
#line 65 "fts0blex.l"
{
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TEXT);
}
diff --git a/storage/innobase/fts/fts0blex.l b/storage/innobase/fts/fts0blex.l
index 6193f0df187..ae6e8ffaa48 100644
--- a/storage/innobase/fts/fts0blex.l
+++ b/storage/innobase/fts/fts0blex.l
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -51,19 +51,19 @@ this program; if not, write to the Free Software Foundation, Inc.,
}
[0-9]+ {
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_NUMB);
}
[^" \n*()+\-<>~@%]* {
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TERM);
}
\"[^\"\n]*\" {
- val->token = strdup(fts0bget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0bget_text(yyscanner)), fts0bget_leng(yyscanner));
return(FTS_TEXT);
}
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index f503cc487b7..848d60f6e3f 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -608,8 +608,10 @@ fts_cache_init(
cache->total_size = 0;
+ mutex_enter((ib_mutex_t*) &cache->deleted_lock);
cache->deleted_doc_ids = ib_vector_create(
cache->sync_heap, sizeof(fts_update_t), 4);
+ mutex_exit((ib_mutex_t*) &cache->deleted_lock);
/* Reset the cache data for all the FTS indexes. */
for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
@@ -1137,7 +1139,10 @@ fts_cache_clear(
cache->sync_heap->arg = NULL;
cache->total_size = 0;
+
+ mutex_enter((ib_mutex_t*) &cache->deleted_lock);
cache->deleted_doc_ids = NULL;
+ mutex_exit((ib_mutex_t*) &cache->deleted_lock);
}
/*********************************************************************//**
@@ -1954,10 +1959,15 @@ fts_create_one_index_table(
char* table_name = fts_get_table_name(fts_table);
dberr_t error;
CHARSET_INFO* charset;
+ ulint flags2 = 0;
ut_ad(index->type & DICT_FTS);
- new_table = dict_mem_table_create(table_name, 0, 5, 1, 0);
+ if (srv_file_per_table) {
+ flags2 = DICT_TF2_USE_TABLESPACE;
+ }
+
+ new_table = dict_mem_table_create(table_name, 0, 5, 1, flags2);
field = dict_index_get_nth_field(index, 0);
charset = innobase_get_fts_charset(
@@ -1986,7 +1996,7 @@ fts_create_one_index_table(
dict_mem_table_add_col(new_table, heap, "ilist", DATA_BLOB,
4130048, 0);
- error = row_create_table_for_mysql(new_table, trx, true);
+ error = row_create_table_for_mysql(new_table, trx, false);
if (error != DB_SUCCESS) {
trx->error_state = error;
@@ -2251,11 +2261,15 @@ static
fts_trx_t*
fts_trx_create(
/*===========*/
- trx_t* trx) /*!< in: InnoDB transaction */
+ trx_t* trx) /*!< in/out: InnoDB
+ transaction */
{
- fts_trx_t* ftt;
- ib_alloc_t* heap_alloc;
- mem_heap_t* heap = mem_heap_create(1024);
+ fts_trx_t* ftt;
+ ib_alloc_t* heap_alloc;
+ mem_heap_t* heap = mem_heap_create(1024);
+ trx_named_savept_t* savep;
+
+ ut_a(trx->fts_trx == NULL);
ftt = static_cast<fts_trx_t*>(mem_heap_alloc(heap, sizeof(fts_trx_t)));
ftt->trx = trx;
@@ -2273,6 +2287,14 @@ fts_trx_create(
fts_savepoint_create(ftt->savepoints, NULL, NULL);
fts_savepoint_create(ftt->last_stmt, NULL, NULL);
+ /* Copy savepoints that already set before. */
+ for (savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
+ savep != NULL;
+ savep = UT_LIST_GET_NEXT(trx_savepoints, savep)) {
+
+ fts_savepoint_take(trx, ftt, savep->name);
+ }
+
return(ftt);
}
@@ -4366,6 +4388,7 @@ fts_sync_commit(
/* We need to do this within the deleted lock since fts_delete() can
attempt to add a deleted doc id to the cache deleted id array. */
fts_cache_clear(cache);
+ DEBUG_SYNC_C("fts_deleted_doc_ids_clear");
fts_cache_init(cache);
rw_lock_x_unlock(&cache->lock);
@@ -5167,6 +5190,12 @@ fts_cache_append_deleted_doc_ids(
mutex_enter((ib_mutex_t*) &cache->deleted_lock);
+ if (cache->deleted_doc_ids == NULL) {
+ mutex_exit((ib_mutex_t*) &cache->deleted_lock);
+ return;
+ }
+
+
for (i = 0; i < ib_vector_size(cache->deleted_doc_ids); ++i) {
fts_update_t* update;
@@ -5452,16 +5481,15 @@ void
fts_savepoint_take(
/*===============*/
trx_t* trx, /*!< in: transaction */
+ fts_trx_t* fts_trx, /*!< in: fts transaction */
const char* name) /*!< in: savepoint name */
{
mem_heap_t* heap;
- fts_trx_t* fts_trx;
fts_savepoint_t* savepoint;
fts_savepoint_t* last_savepoint;
ut_a(name != NULL);
- fts_trx = trx->fts_trx;
heap = fts_trx->heap;
/* The implied savepoint must exist. */
@@ -5778,7 +5806,7 @@ fts_savepoint_rollback(
ut_a(ib_vector_size(savepoints) > 0);
/* Restore the savepoint. */
- fts_savepoint_take(trx, name);
+ fts_savepoint_take(trx, trx->fts_trx, name);
}
}
diff --git a/storage/innobase/fts/fts0pars.cc b/storage/innobase/fts/fts0pars.cc
index 83d465b0988..7f0ba4e0c1b 100644
--- a/storage/innobase/fts/fts0pars.cc
+++ b/storage/innobase/fts/fts0pars.cc
@@ -100,6 +100,8 @@ extern int ftserror(const char* p);
#define YYPARSE_PARAM state
#define YYLEX_PARAM ((fts_ast_state_t*) state)->lexer
+#define YYTOKENFREE(token) fts_ast_string_free((token))
+
typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner);
typedef int (*fts_scanner)();
@@ -154,9 +156,9 @@ typedef union YYSTYPE
/* Line 293 of yacc.c */
#line 61 "fts0pars.y"
- int oper;
- char* token;
- fts_ast_node_t* node;
+ int oper;
+ fts_ast_string_t* token;
+ fts_ast_node_t* node;
@@ -632,6 +634,19 @@ while (YYID (0))
#define YYTERROR 1
#define YYERRCODE 256
+#define YYERRCLEANUP \
+do \
+ switch (yylastchar) \
+ { \
+ case FTS_NUMB: \
+ case FTS_TEXT: \
+ case FTS_TERM: \
+ YYTOKENFREE(yylval.token); \
+ break; \
+ default: \
+ break; \
+ } \
+while (YYID (0))
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends
@@ -1169,6 +1184,8 @@ yyparse ()
{
/* The lookahead symbol. */
int yychar;
+/* The backup of yychar when there is an error and we're in yyerrlab. */
+int yylastchar;
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
@@ -1524,8 +1541,8 @@ yyreduce:
/* Line 1806 of yacc.c */
#line 141 "fts0pars.y"
{
- fts_ast_term_set_distance((yyvsp[(1) - (3)].node), strtoul((yyvsp[(3) - (3)].token), NULL, 10));
- free((yyvsp[(3) - (3)].token));
+ fts_ast_term_set_distance((yyvsp[(1) - (3)].node), fts_ast_string_to_ul((yyvsp[(3) - (3)].token), 10));
+ fts_ast_string_free((yyvsp[(3) - (3)].token));
}
break;
@@ -1557,8 +1574,8 @@ yyreduce:
{
(yyval.node) = fts_ast_create_node_list(state, (yyvsp[(1) - (4)].node));
fts_ast_add_node((yyval.node), (yyvsp[(2) - (4)].node));
- fts_ast_term_set_distance((yyvsp[(2) - (4)].node), strtoul((yyvsp[(4) - (4)].token), NULL, 10));
- free((yyvsp[(4) - (4)].token));
+ fts_ast_term_set_distance((yyvsp[(2) - (4)].node), fts_ast_string_to_ul((yyvsp[(4) - (4)].token), 10));
+ fts_ast_string_free((yyvsp[(4) - (4)].token));
}
break;
@@ -1623,7 +1640,7 @@ yyreduce:
#line 191 "fts0pars.y"
{
(yyval.node) = fts_ast_create_node_term(state, (yyvsp[(1) - (1)].token));
- free((yyvsp[(1) - (1)].token));
+ fts_ast_string_free((yyvsp[(1) - (1)].token));
}
break;
@@ -1633,7 +1650,7 @@ yyreduce:
#line 196 "fts0pars.y"
{
(yyval.node) = fts_ast_create_node_term(state, (yyvsp[(1) - (1)].token));
- free((yyvsp[(1) - (1)].token));
+ fts_ast_string_free((yyvsp[(1) - (1)].token));
}
break;
@@ -1652,7 +1669,7 @@ yyreduce:
#line 207 "fts0pars.y"
{
(yyval.node) = fts_ast_create_node_text(state, (yyvsp[(1) - (1)].token));
- free((yyvsp[(1) - (1)].token));
+ fts_ast_string_free((yyvsp[(1) - (1)].token));
}
break;
@@ -1700,6 +1717,8 @@ yyreduce:
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
+ /* Backup yychar, in case we would change it. */
+ yylastchar = yychar;
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
@@ -1755,7 +1774,11 @@ yyerrlab:
{
/* Return failure if at end of input. */
if (yychar == YYEOF)
- YYABORT;
+ {
+ /* Since we don't need the token, we have to free it first. */
+ YYERRCLEANUP;
+ YYABORT;
+ }
}
else
{
@@ -1812,7 +1835,11 @@ yyerrlab1:
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
- YYABORT;
+ {
+ /* Since we don't need the error token, we have to free it first. */
+ YYERRCLEANUP;
+ YYABORT;
+ }
yydestruct ("Error: popping",
diff --git a/storage/innobase/fts/fts0pars.y b/storage/innobase/fts/fts0pars.y
index ff22e9a9873..e48036e82fe 100644
--- a/storage/innobase/fts/fts0pars.y
+++ b/storage/innobase/fts/fts0pars.y
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -59,9 +59,9 @@ struct fts_lexer_struct {
%}
%union {
- int oper;
- char* token;
- fts_ast_node_t* node;
+ int oper;
+ fts_ast_string_t* token;
+ fts_ast_node_t* node;
};
/* Enable re-entrant parser */
@@ -139,8 +139,8 @@ expr : term {
}
| text '@' FTS_NUMB {
- fts_ast_term_set_distance($1, strtoul($3, NULL, 10));
- free($3);
+ fts_ast_term_set_distance($1, fts_ast_string_to_ul($3, 10));
+ fts_ast_string_free($3);
}
| prefix term '*' {
@@ -157,8 +157,8 @@ expr : term {
| prefix text '@' FTS_NUMB {
$$ = fts_ast_create_node_list(state, $1);
fts_ast_add_node($$, $2);
- fts_ast_term_set_distance($2, strtoul($4, NULL, 10));
- free($4);
+ fts_ast_term_set_distance($2, fts_ast_string_to_ul($4, 10));
+ fts_ast_string_free($4);
}
| prefix text {
@@ -190,12 +190,12 @@ prefix : '-' {
term : FTS_TERM {
$$ = fts_ast_create_node_term(state, $1);
- free($1);
+ fts_ast_string_free($1);
}
| FTS_NUMB {
$$ = fts_ast_create_node_term(state, $1);
- free($1);
+ fts_ast_string_free($1);
}
/* Ignore leading '*' */
@@ -206,7 +206,7 @@ term : FTS_TERM {
text : FTS_TEXT {
$$ = fts_ast_create_node_text(state, $1);
- free($1);
+ fts_ast_string_free($1);
}
;
%%
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index adbf433e608..f26fd89ac76 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -2800,20 +2800,19 @@ fts_query_get_token(
ulint str_len;
byte* new_ptr = NULL;
- str_len = ut_strlen((char*) node->term.ptr);
+ str_len = node->term.ptr->len;
ut_a(node->type == FTS_AST_TERM);
token->f_len = str_len;
- token->f_str = node->term.ptr;
+ token->f_str = node->term.ptr->str;
if (node->term.wildcard) {
token->f_str = static_cast<byte*>(ut_malloc(str_len + 2));
token->f_len = str_len + 1;
- /* Need to copy the NUL character too. */
- memcpy(token->f_str, node->term.ptr, str_len + 1);
+ memcpy(token->f_str, node->term.ptr->str, str_len);
token->f_str[str_len] = '%';
token->f_str[token->f_len] = 0;
@@ -2848,8 +2847,8 @@ fts_query_visitor(
switch (node->type) {
case FTS_AST_TEXT:
- token.f_str = node->text.ptr;
- token.f_len = ut_strlen((char*) token.f_str);
+ token.f_str = node->text.ptr->str;
+ token.f_len = node->text.ptr->len;
if (query->oper == FTS_EXIST) {
ut_ad(query->intersection == NULL);
@@ -2878,8 +2877,8 @@ fts_query_visitor(
break;
case FTS_AST_TERM:
- token.f_str = node->term.ptr;
- token.f_len = ut_strlen(reinterpret_cast<char*>(token.f_str));
+ token.f_str = node->term.ptr->str;
+ token.f_len = node->term.ptr->len;
/* Add the word to our RB tree that will be used to
calculate this terms per document frequency. */
@@ -3191,13 +3190,9 @@ fts_query_read_node(
to assign the frequency on search string behalf. */
if (query->cur_node->type == FTS_AST_TERM
&& query->cur_node->term.wildcard) {
-
- /* These cast are safe since we only care about the
- terminating NUL character as an end of string marker. */
- term.f_len = ut_strlen(reinterpret_cast<char*>
- (query->cur_node->term.ptr));
+ term.f_len = query->cur_node->term.ptr->len;
ut_ad(FTS_MAX_WORD_LEN >= term.f_len);
- memcpy(term.f_str, query->cur_node->term.ptr, term.f_len);
+ memcpy(term.f_str, query->cur_node->term.ptr->str, term.f_len);
} else {
term.f_len = word->f_len;
ut_ad(FTS_MAX_WORD_LEN >= word->f_len);
@@ -3507,14 +3502,15 @@ fts_query_prepare_result(
doc_freq = rbt_value(fts_doc_freq_t, node);
/* Don't put deleted docs into result */
- if (fts_bsearch(array, 0, static_cast<int>(size), doc_freq->doc_id)
- >= 0) {
+ if (fts_bsearch(array, 0, static_cast<int>(size),
+ doc_freq->doc_id) >= 0) {
+ /* one less matching doc count */
+ --word_freq->doc_count;
continue;
}
ranking.doc_id = doc_freq->doc_id;
- ranking.rank = static_cast<fts_rank_t>(
- doc_freq->freq * word_freq->idf * word_freq->idf);
+ ranking.rank = static_cast<fts_rank_t>(doc_freq->freq);
ranking.words = NULL;
fts_query_add_ranking(query, result->rankings_by_id,
@@ -3527,6 +3523,25 @@ fts_query_prepare_result(
}
}
+ /* Calculate IDF only after we exclude the deleted items */
+ fts_query_calculate_idf(query);
+
+ node = rbt_first(query->word_freqs);
+ word_freq = rbt_value(fts_word_freq_t, node);
+
+ /* Calculate the ranking for each doc */
+ for (node = rbt_first(result->rankings_by_id);
+ node != NULL;
+ node = rbt_next(result->rankings_by_id, node)) {
+
+ fts_ranking_t* ranking;
+
+ ranking = rbt_value(fts_ranking_t, node);
+
+ ranking->rank = static_cast<fts_rank_t>(
+ ranking->rank * word_freq->idf * word_freq->idf);
+ }
+
return(result);
}
@@ -3900,6 +3915,7 @@ fts_query(
/* Get the deleted doc ids that are in the cache. */
fts_cache_append_deleted_doc_ids(
index->table->fts->cache, query.deleted->doc_ids);
+ DEBUG_SYNC_C("fts_deleted_doc_ids_append");
/* Sort the vector so that we can do a binary search over the ids. */
ib_vector_sort(query.deleted->doc_ids, fts_update_doc_id_cmp);
@@ -3956,7 +3972,8 @@ fts_query(
}
/* Calculate the inverse document frequency of the terms. */
- if (query.error == DB_SUCCESS) {
+ if (query.error == DB_SUCCESS
+ && query.flags != FTS_OPT_RANKING) {
fts_query_calculate_idf(&query);
}
diff --git a/storage/innobase/fts/fts0tlex.cc b/storage/innobase/fts/fts0tlex.cc
index ef17ab1acf2..b744fbf0763 100644
--- a/storage/innobase/fts/fts0tlex.cc
+++ b/storage/innobase/fts/fts0tlex.cc
@@ -447,7 +447,7 @@ static yyconst flex_int16_t yy_chk[29] =
#line 1 "fts0tlex.l"
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -802,7 +802,7 @@ case 3:
YY_RULE_SETUP
#line 54 "fts0tlex.l"
{
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TEXT);
}
@@ -811,7 +811,7 @@ case 4:
YY_RULE_SETUP
#line 60 "fts0tlex.l"
{
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TERM);
}
diff --git a/storage/innobase/fts/fts0tlex.l b/storage/innobase/fts/fts0tlex.l
index a18c2a55081..4f55a83afe5 100644
--- a/storage/innobase/fts/fts0tlex.l
+++ b/storage/innobase/fts/fts0tlex.l
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -52,13 +52,13 @@ this program; if not, write to the Free Software Foundation, Inc.,
}
\"[^\"\n]*\" {
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TEXT);
}
[^" \n\%]* {
- val->token = strdup(fts0tget_text(yyscanner));
+ val->token = fts_ast_string_create(reinterpret_cast<const byte*>(fts0tget_text(yyscanner)), fts0tget_leng(yyscanner));
return(FTS_TERM);
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 50af060e15f..388032f3c96 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3572,7 +3572,7 @@ innobase_commit_ordered_2(
{
DBUG_ENTER("innobase_commit_ordered_2");
- /* We need current binlog position for ibbackup to work.
+ /* We need current binlog position for mysqlbackup to work.
Note, the position is current because commit_ordered is guaranteed
to be called in same sequenece as writing to binlog. */
@@ -4144,7 +4144,7 @@ innobase_savepoint(
error = trx_savepoint_for_mysql(trx, name, (ib_int64_t)0);
if (error == DB_SUCCESS && trx->fts_trx != NULL) {
- fts_savepoint_take(trx, name);
+ fts_savepoint_take(trx, trx->fts_trx, name);
}
DBUG_RETURN(convert_error_code_to_mysql(error, 0, NULL));
@@ -12169,9 +12169,13 @@ ha_innobase::get_foreign_key_list(
mutex_enter(&(dict_sys->mutex));
- for (foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = prebuilt->table->foreign_set.begin();
+ it != prebuilt->table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
pf_key_info = get_foreign_key_info(thd, foreign);
if (pf_key_info) {
f_key_list->push_back(pf_key_info);
@@ -12207,9 +12211,13 @@ ha_innobase::get_parent_foreign_key_list(
mutex_enter(&(dict_sys->mutex));
- for (foreign = UT_LIST_GET_FIRST(prebuilt->table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = prebuilt->table->referenced_set.begin();
+ it != prebuilt->table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
pf_key_info = get_foreign_key_info(thd, foreign);
if (pf_key_info) {
f_key_list->push_back(pf_key_info);
@@ -12242,8 +12250,8 @@ ha_innobase::can_switch_engines(void)
"determining if there are foreign key constraints";
row_mysql_freeze_data_dictionary(prebuilt->trx);
- can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
- && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
+ can_switch = prebuilt->table->referenced_set.empty()
+ && prebuilt->table->foreign_set.empty();
row_mysql_unfreeze_data_dictionary(prebuilt->trx);
prebuilt->trx->op_info = "";
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 810de051c9b..cb5faa42199 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -590,15 +590,9 @@ innobase_init_foreign(
/* Check if any existing foreign key has the same id,
this is needed only if user supplies the constraint name */
- for (const dict_foreign_t* existing_foreign
- = UT_LIST_GET_FIRST(table->foreign_list);
- existing_foreign != 0;
- existing_foreign = UT_LIST_GET_NEXT(
- foreign_list, existing_foreign)) {
-
- if (ut_strcmp(existing_foreign->id, foreign->id) == 0) {
- return(false);
- }
+ if (table->foreign_set.find(foreign)
+ != table->foreign_set.end()) {
+ return(false);
}
}
@@ -2236,14 +2230,18 @@ innobase_check_foreigns_low(
const char* col_name,
bool drop)
{
+ dict_foreign_t* foreign;
ut_ad(mutex_own(&dict_sys->mutex));
/* Check if any FOREIGN KEY constraints are defined on this
column. */
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->foreign_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+
+ for (dict_foreign_set::iterator it = user_table->foreign_set.begin();
+ it != user_table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
if (!drop && !(foreign->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
| DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
@@ -2275,10 +2273,13 @@ innobase_check_foreigns_low(
/* Check if any FOREIGN KEY constraints in other tables are
referring to the column that is being dropped. */
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->referenced_list);
- foreign;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = user_table->referenced_set.begin();
+ it != user_table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
if (innobase_dropping_foreign(foreign, drop_fk, n_drop_fk)) {
continue;
}
@@ -3598,11 +3599,12 @@ check_if_ok_to_rename:
continue;
}
- for (dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- prebuilt->table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(
- foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = prebuilt->table->foreign_set.begin();
+ it != prebuilt->table->foreign_set.end();
+ ++it) {
+
+ dict_foreign_t* foreign = *it;
const char* fid = strchr(foreign->id, '/');
DBUG_ASSERT(fid);
@@ -4443,10 +4445,12 @@ err_exit:
rename_foreign:
trx->op_info = "renaming column in SYS_FOREIGN_COLS";
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->foreign_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+ for (dict_foreign_set::iterator it = user_table->foreign_set.begin();
+ it != user_table->foreign_set.end();
+ ++it) {
+
+ dict_foreign_t* foreign = *it;
+
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->foreign_col_names[i], from)) {
continue;
@@ -4476,10 +4480,12 @@ rename_foreign:
}
}
- for (const dict_foreign_t* foreign = UT_LIST_GET_FIRST(
- user_table->referenced_list);
- foreign != NULL;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+ for (dict_foreign_set::iterator it
+ = user_table->referenced_set.begin();
+ it != user_table->referenced_set.end();
+ ++it) {
+
+ dict_foreign_t* foreign = *it;
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->referenced_col_names[i], from)) {
continue;
@@ -4803,8 +4809,8 @@ innobase_update_foreign_cache(
column names. No need to pass col_names or to drop
constraints from the data dictionary cache. */
DBUG_ASSERT(!ctx->col_names);
- DBUG_ASSERT(UT_LIST_GET_LEN(user_table->foreign_list) == 0);
- DBUG_ASSERT(UT_LIST_GET_LEN(user_table->referenced_list) == 0);
+ DBUG_ASSERT(user_table->foreign_set.empty());
+ DBUG_ASSERT(user_table->referenced_set.empty());
user_table = ctx->new_table;
} else {
/* Drop the foreign key constraints if the
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 289de8f42ae..3f2ac4980cf 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -447,7 +447,7 @@ buf_page_create(
mtr_t* mtr); /*!< in: mini-transaction handle */
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
-Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
+Inits a page to the buffer buf_pool, for use in mysqlbackup --restore. */
UNIV_INTERN
void
buf_page_init_for_backup_restore(
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index b15a7fb11b6..6e419674f98 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -1160,12 +1160,6 @@ buf_page_hash_get_low(
ut_a(buf_page_in_file(bpage));
ut_ad(bpage->in_page_hash);
ut_ad(!bpage->in_zip_hash);
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in
- buf_page_t. On other systems, Valgrind could complain
- about uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
-#endif
}
return(bpage);
diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h
index 6ec1079957b..67eab9058da 100644
--- a/storage/innobase/include/dict0crea.h
+++ b/storage/innobase/include/dict0crea.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, 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
the terms of the GNU General Public License as published by the Free Software
@@ -124,28 +124,24 @@ dict_create_add_foreign_id(
const char* name, /*!< in: table name */
dict_foreign_t* foreign)/*!< in/out: foreign key */
__attribute__((nonnull));
-/********************************************************************//**
-Adds foreign key definitions to data dictionary tables in the database. We
-look at table->foreign_list, and also generate names to constraints that were
-not named by the user. A generated constraint has a name of the format
-databasename/tablename_ibfk_NUMBER, where the numbers start from 1, and are
-given locally for this table, that is, the number is not global, as in the
-old format constraints < 4.0.18 it used to be.
-@return error code or DB_SUCCESS */
+
+/** Adds the given set of foreign key objects to the dictionary tables
+in the database. This function does not modify the dictionary cache. The
+caller must ensure that all foreign key objects contain a valid constraint
+name in foreign->id.
+@param[in] local_fk_set set of foreign key objects, to be added to
+the dictionary tables
+@param[in] table table to which the foreign key objects in
+local_fk_set belong to
+@param[in,out] trx transaction
+@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_foreigns_to_dictionary(
/*===================================*/
- ulint start_id,/*!< in: if we are actually doing ALTER TABLE
- ADD CONSTRAINT, we want to generate constraint
- numbers which are bigger than in the table so
- far; we number the constraints from
- start_id + 1 up; start_id should be set to 0 if
- we are creating a new table, or if the table
- so far has no constraints for which the name
- was generated here */
- dict_table_t* table, /*!< in: table */
- trx_t* trx) /*!< in: transaction */
+ const dict_foreign_set& local_fk_set,
+ const dict_table_t* table,
+ trx_t* trx)
__attribute__((nonnull, warn_unused_result));
/****************************************************************//**
Creates the tablespaces and datafiles system tables inside InnoDB
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index f1975456ab1..f5326fbdb41 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -47,6 +47,8 @@ Created 1/8/1996 Heikki Tuuri
#include "trx0types.h"
#include "fts0fts.h"
#include "os0once.h"
+#include <set>
+#include <algorithm>
/* Forward declaration. */
struct ib_rbt_t;
@@ -706,12 +708,106 @@ struct dict_foreign_t{
does not generate new indexes
implicitly */
dict_index_t* referenced_index;/*!< referenced index */
- UT_LIST_NODE_T(dict_foreign_t)
- foreign_list; /*!< list node for foreign keys of the
- table */
- UT_LIST_NODE_T(dict_foreign_t)
- referenced_list;/*!< list node for referenced
- keys of the table */
+};
+
+/** Compare two dict_foreign_t objects using their ids. Used in the ordering
+of dict_table_t::foreign_set and dict_table_t::referenced_set. It returns
+true if the first argument is considered to go before the second in the
+strict weak ordering it defines, and false otherwise. */
+struct dict_foreign_compare {
+
+ bool operator()(
+ const dict_foreign_t* lhs,
+ const dict_foreign_t* rhs) const
+ {
+ return(ut_strcmp(lhs->id, rhs->id) < 0);
+ }
+};
+
+/** A function object to find a foreign key with the given index as the
+referenced index. Return the foreign key with matching criteria or NULL */
+struct dict_foreign_with_index {
+
+ dict_foreign_with_index(const dict_index_t* index)
+ : m_index(index)
+ {}
+
+ bool operator()(const dict_foreign_t* foreign) const
+ {
+ return(foreign->referenced_index == m_index);
+ }
+
+ const dict_index_t* m_index;
+};
+
+/* A function object to check if the foreign constraint is between different
+tables. Returns true if foreign key constraint is between different tables,
+false otherwise. */
+struct dict_foreign_different_tables {
+
+ bool operator()(const dict_foreign_t* foreign) const
+ {
+ return(foreign->foreign_table != foreign->referenced_table);
+ }
+};
+
+/** A function object to check if the foreign key constraint has the same
+name as given. If the full name of the foreign key constraint doesn't match,
+then, check if removing the database name from the foreign key constraint
+matches. Return true if it matches, false otherwise. */
+struct dict_foreign_matches_id {
+
+ dict_foreign_matches_id(const char* id)
+ : m_id(id)
+ {}
+
+ bool operator()(const dict_foreign_t* foreign) const
+ {
+ if (0 == innobase_strcasecmp(foreign->id, m_id)) {
+ return(true);
+ }
+ if (const char* pos = strchr(foreign->id, '/')) {
+ if (0 == innobase_strcasecmp(m_id, pos + 1)) {
+ return(true);
+ }
+ }
+ return(false);
+ }
+
+ const char* m_id;
+};
+
+typedef std::set<dict_foreign_t*, dict_foreign_compare> dict_foreign_set;
+
+/*********************************************************************//**
+Frees a foreign key struct. */
+inline
+void
+dict_foreign_free(
+/*==============*/
+ dict_foreign_t* foreign) /*!< in, own: foreign key struct */
+{
+ mem_heap_free(foreign->heap);
+}
+
+/** The destructor will free all the foreign key constraints in the set
+by calling dict_foreign_free() on each of the foreign key constraints.
+This is used to free the allocated memory when a local set goes out
+of scope. */
+struct dict_foreign_set_free {
+
+ dict_foreign_set_free(const dict_foreign_set& foreign_set)
+ : m_foreign_set(foreign_set)
+ {}
+
+ ~dict_foreign_set_free()
+ {
+ std::for_each(m_foreign_set.begin(),
+ m_foreign_set.end(),
+ dict_foreign_free);
+ }
+
+ const dict_foreign_set& m_foreign_set;
};
/** The flags for ON_UPDATE and ON_DELETE can be ORed; the default is that
@@ -733,6 +829,8 @@ the table, DML from memcached will be blocked. */
/** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_t{
+
+
table_id_t id; /*!< id of the table */
mem_heap_t* heap; /*!< memory heap */
char* name; /*!< table name */
@@ -787,13 +885,16 @@ struct dict_table_t{
hash_node_t id_hash; /*!< hash chain node */
UT_LIST_BASE_NODE_T(dict_index_t)
indexes; /*!< list of indexes of the table */
- UT_LIST_BASE_NODE_T(dict_foreign_t)
- foreign_list;/*!< list of foreign key constraints
+
+ dict_foreign_set foreign_set;
+ /*!< set of foreign key constraints
in the table; these refer to columns
in other tables */
- UT_LIST_BASE_NODE_T(dict_foreign_t)
- referenced_list;/*!< list of foreign key constraints
+
+ dict_foreign_set referenced_set;
+ /*!< list of foreign key constraints
which refer to this table */
+
UT_LIST_NODE_T(dict_table_t)
table_LRU; /*!< node of the LRU list of tables */
unsigned fk_max_recusive_level:8;
@@ -1035,6 +1136,19 @@ struct dict_table_t{
#endif /* UNIV_DEBUG */
};
+/** A function object to add the foreign key constraint to the referenced set
+of the referenced table, if it exists in the dictionary cache. */
+struct dict_foreign_add_to_referenced_table {
+ void operator()(dict_foreign_t* foreign) const
+ {
+ if (dict_table_t* table = foreign->referenced_table) {
+ std::pair<dict_foreign_set::iterator, bool> ret
+ = table->referenced_set.insert(foreign);
+ ut_a(ret.second);
+ }
+ }
+};
+
#ifndef UNIV_NONINL
#include "dict0mem.ic"
#endif
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 72b4cfd3bfb..b607ca36d70 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -48,7 +48,7 @@ struct fil_space_t;
typedef std::list<const char*> space_name_list_t;
/** When mysqld is run, the default directory "." is the mysqld datadir,
-but in the MySQL Embedded Server Library and ibbackup it is not the default
+but in the MySQL Embedded Server Library and mysqlbackup it is not the default
directory, and we must set the base file path explicitly */
extern const char* fil_path_to_mysql_datadir;
@@ -426,8 +426,8 @@ exists and the space id in it matches. Replays the create operation if a file
at that path does not exist yet. If the database directory for the file to be
created does not exist, then we create the directory, too.
-Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to the
-datadir that we should use in replaying the file operations.
+Note that mysqlbackup --apply-log sets fil_path_to_mysql_datadir to point to
+the datadir that we should use in replaying the file operations.
@return end of log record, or NULL if the record was not completely
contained between ptr and end_ptr */
UNIV_INTERN
@@ -680,9 +680,9 @@ fil_space_for_table_exists_in_mem(
#else /* !UNIV_HOTBACKUP */
/********************************************************************//**
Extends all tablespaces to the size stored in the space header. During the
-ibbackup --apply-log phase we extended the spaces on-demand so that log records
-could be appllied, but that may have left spaces still too small compared to
-the size stored in the space header. */
+mysqlbackup --apply-log phase we extended the spaces on-demand so that log
+records could be appllied, but that may have left spaces still too small
+compared to the size stored in the space header. */
UNIV_INTERN
void
fil_extend_tablespaces_to_stored_len(void);
diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h
index c0aac6d8e4c..50ee587e282 100644
--- a/storage/innobase/include/fts0ast.h
+++ b/storage/innobase/include/fts0ast.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -76,6 +76,7 @@ enum fts_ast_oper_t {
struct fts_lexer_t;
struct fts_ast_node_t;
struct fts_ast_state_t;
+struct fts_ast_string_t;
typedef dberr_t (*fts_ast_callback)(fts_ast_oper_t, fts_ast_node_t*, void*);
@@ -101,16 +102,16 @@ extern
fts_ast_node_t*
fts_ast_create_node_term(
/*=====================*/
- void* arg, /*!< in: ast state */
- const char* ptr); /*!< in: term string */
+ void* arg, /*!< in: ast state */
+ const fts_ast_string_t* ptr); /*!< in: term string */
/********************************************************************
Create an AST text node */
extern
fts_ast_node_t*
fts_ast_create_node_text(
/*=====================*/
- void* arg, /*!< in: ast state */
- const char* ptr); /*!< in: text string */
+ void* arg, /*!< in: ast state */
+ const fts_ast_string_t* ptr); /*!< in: text string */
/********************************************************************
Create an AST expr list node */
extern
@@ -233,16 +234,66 @@ fts_lexer_free(
free */
__attribute__((nonnull));
+/**
+Create an ast string object, with NUL-terminator, so the string
+has one more byte than len
+@param[in] str pointer to string
+@param[in] len length of the string
+@return ast string with NUL-terminator */
+UNIV_INTERN
+fts_ast_string_t*
+fts_ast_string_create(
+ const byte* str,
+ ulint len);
+
+/**
+Free an ast string instance
+@param[in,out] ast_str string to free */
+UNIV_INTERN
+void
+fts_ast_string_free(
+ fts_ast_string_t* ast_str);
+
+/**
+Translate ast string of type FTS_AST_NUMB to unsigned long by strtoul
+@param[in] str string to translate
+@param[in] base the base
+@return translated number */
+UNIV_INTERN
+ulint
+fts_ast_string_to_ul(
+ const fts_ast_string_t* ast_str,
+ int base);
+
+/**
+Print the ast string
+@param[in] str string to print */
+UNIV_INTERN
+void
+fts_ast_string_print(
+ const fts_ast_string_t* ast_str);
+
+/* String of length len.
+We always store the string of length len with a terminating '\0',
+regardless of there is any 0x00 in the string itself */
+struct fts_ast_string_t {
+ /*!< Pointer to string. */
+ byte* str;
+
+ /*!< Length of the string. */
+ ulint len;
+};
+
/* Query term type */
struct fts_ast_term_t {
- byte* ptr; /*!< Pointer to term string.*/
- ibool wildcard; /*!< TRUE if wild card set.*/
+ fts_ast_string_t* ptr; /*!< Pointer to term string.*/
+ ibool wildcard; /*!< TRUE if wild card set.*/
};
/* Query text type */
struct fts_ast_text_t {
- byte* ptr; /*!< Pointer to term string.*/
- ulint distance; /*!< > 0 if proximity distance
+ fts_ast_string_t* ptr; /*!< Pointer to text string.*/
+ ulint distance; /*!< > 0 if proximity distance
set */
};
diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h
index 5bea5bc0e97..a2996ecacc8 100644
--- a/storage/innobase/include/fts0fts.h
+++ b/storage/innobase/include/fts0fts.h
@@ -745,6 +745,7 @@ void
fts_savepoint_take(
/*===============*/
trx_t* trx, /*!< in: transaction */
+ fts_trx_t* fts_trx, /*!< in: fts transaction */
const char* name) /*!< in: savepoint name */
__attribute__((nonnull));
/**********************************************************************//**
diff --git a/storage/innobase/include/fts0pars.h b/storage/innobase/include/fts0pars.h
index 50f636944e5..8108e811599 100644
--- a/storage/innobase/include/fts0pars.h
+++ b/storage/innobase/include/fts0pars.h
@@ -53,9 +53,9 @@ typedef union YYSTYPE
/* Line 2068 of yacc.c */
#line 61 "fts0pars.y"
- int oper;
- char* token;
- fts_ast_node_t* node;
+ int oper;
+ fts_ast_string_t* token;
+ fts_ast_node_t* node;
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 0182d9b00b6..ad9710b1870 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -656,13 +656,13 @@ extern log_t* log_sys;
megabyte.
This information might have been used
- since ibbackup version 0.35 but
+ since mysqlbackup version 0.35 but
before 1.41 to decide if unused ends of
non-auto-extending data files
in space 0 can be truncated.
This information was made obsolete
- by ibbackup --compress. */
+ by mysqlbackup --compress. */
#define LOG_CHECKPOINT_FSP_MAGIC_N (12 + LOG_CHECKPOINT_ARRAY_END)
/*!< Not used (0);
This magic number tells if the
@@ -691,7 +691,7 @@ extern log_t* log_sys;
/* a 32-byte field which contains
the string 'ibbackup' and the
creation time if the log file was
- created by ibbackup --restore;
+ created by mysqlbackup --restore;
when mysqld is first time started
on the restored database, it can
print helpful info for the user */
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 8e2948e2d68..5fea0023220 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -126,7 +126,7 @@ enum os_file_create_t {
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
-#define OS_FILE_READ_ALLOW_DELETE 555 /* for ibbackup */
+#define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */
/* Options for file_create */
#define OS_FILE_AIO 61
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index f62278a1259..534b9940e84 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -357,6 +357,10 @@ Atomic compare-and-swap and increment for InnoDB. */
# define HAVE_ATOMIC_BUILTINS
+# ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE
+# define HAVE_ATOMIC_BUILTINS_BYTE
+# endif
+
# ifdef HAVE_IB_GCC_ATOMIC_BUILTINS_64
# define HAVE_ATOMIC_BUILTINS_64
# endif
@@ -440,6 +444,7 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
#elif defined(HAVE_IB_SOLARIS_ATOMICS)
# define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS_BYTE
# define HAVE_ATOMIC_BUILTINS_64
/* If not compiling with GCC or GCC doesn't support the atomic
@@ -524,6 +529,7 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
#elif defined(HAVE_WINDOWS_ATOMICS)
# define HAVE_ATOMIC_BUILTINS
+# define HAVE_ATOMIC_BUILTINS_BYTE
# ifndef _WIN32
# define HAVE_ATOMIC_BUILTINS_64
@@ -695,7 +701,15 @@ for synchronization */
} while (0);
/** barrier definitions for memory ordering */
-#ifdef HAVE_IB_GCC_ATOMIC_THREAD_FENCE
+#if defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64 || defined __WIN__
+/* Performance regression was observed at some conditions for Intel
+architecture. Disable memory barrier for Intel architecture for now. */
+# define os_rmb do { } while(0)
+# define os_wmb do { } while(0)
+# define os_isync do { } while(0)
+# define IB_MEMORY_BARRIER_STARTUP_MSG \
+ "Memory barrier is not used"
+#elif defined(HAVE_IB_GCC_ATOMIC_THREAD_FENCE)
# define HAVE_MEMORY_BARRIER
# define os_rmb __atomic_thread_fence(__ATOMIC_ACQUIRE)
# define os_wmb __atomic_thread_fence(__ATOMIC_RELEASE)
@@ -723,7 +737,7 @@ for synchronization */
# define os_wmb __machine_w_barrier()
# define os_isync os_rmb; os_wmb
# define IB_MEMORY_BARRIER_STARTUP_MSG \
- "Soralis memory ordering functions are used for memory barrier"
+ "Solaris memory ordering functions are used for memory barrier"
#elif defined(HAVE_WINDOWS_MM_FENCE)
# define HAVE_MEMORY_BARRIER
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index 7ea910b4719..bb05ae7daf1 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -93,6 +93,7 @@ rw_lock_set_waiter_flag(
(void) os_compare_and_swap_ulint(&lock->waiters, 0, 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
lock->waiters = 1;
+ os_wmb;
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
}
@@ -110,6 +111,7 @@ rw_lock_reset_waiter_flag(
(void) os_compare_and_swap_ulint(&lock->waiters, 1, 0);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
lock->waiters = 0;
+ os_wmb;
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
}
@@ -200,13 +202,16 @@ rw_lock_lock_word_decr(
{
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
lint local_lock_word;
- os_rmb;
- while ((local_lock_word= lock->lock_word) > 0) {
+
+ os_rmb;
+ local_lock_word = lock->lock_word;
+ while (local_lock_word > 0) {
if (os_compare_and_swap_lint(&lock->lock_word,
local_lock_word,
local_lock_word - amount)) {
return(TRUE);
}
+ local_lock_word = lock->lock_word;
}
return(FALSE);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index 7b00e16476b..82fb353a41b 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -49,6 +49,8 @@ extern "C" my_bool timed_mutexes;
#ifdef HAVE_WINDOWS_ATOMICS
typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates
on LONG variable */
+#elif defined(HAVE_ATOMIC_BUILTINS) && !defined(HAVE_ATOMIC_BUILTINS_BYTE)
+typedef ulint lock_word_t;
#else
typedef byte lock_word_t;
#endif
diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic
index 9c7f3d2cd4b..687f7ee5142 100644
--- a/storage/innobase/include/sync0sync.ic
+++ b/storage/innobase/include/sync0sync.ic
@@ -80,7 +80,11 @@ ib_mutex_test_and_set(
ib_mutex_t* mutex) /*!< in: mutex */
{
#if defined(HAVE_ATOMIC_BUILTINS)
+# if defined(HAVE_ATOMIC_BUILTINS_BYTE)
return(os_atomic_test_and_set_byte(&mutex->lock_word, 1));
+# else
+ return(os_atomic_test_and_set_ulint(&mutex->lock_word, 1));
+# endif
#else
ibool ret;
@@ -92,7 +96,7 @@ ib_mutex_test_and_set(
ut_a(mutex->lock_word == 0);
mutex->lock_word = 1;
- os_wmb;
+ os_wmb;
}
return((byte) ret);
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index bc359746a0b..2635fca3220 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -44,7 +44,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 19
+#define INNODB_VERSION_BUGFIX 20
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 5282e45dddb..53794a0d773 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -1249,7 +1249,7 @@ log_group_file_header_flush(
mach_write_to_4(buf + LOG_GROUP_ID, group->id);
mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn);
- /* Wipe over possible label of ibbackup --restore */
+ /* Wipe over possible label of mysqlbackup --restore */
memcpy(buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, " ", 4);
dest_offset = nth_file * group->file_size;
@@ -1996,7 +1996,7 @@ log_reset_first_header_and_checkpoint(
lsn = start + LOG_BLOCK_HDR_SIZE;
- /* Write the label of ibbackup --restore */
+ /* Write the label of mysqlbackup --restore */
strcpy((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
"ibbackup ");
ut_sprintf_timestamp((char*) hdr_buf
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index a521e098598..4fe9620ccaa 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -59,7 +59,7 @@ Created 9/20/1997 Heikki Tuuri
/** This is set to FALSE if the backup was originally taken with the
-ibbackup --include regexp option: then we do not want to create tables in
+mysqlbackup --include regexp option: then we do not want to create tables in
directories which were not included */
UNIV_INTERN ibool recv_replay_file_ops = TRUE;
#endif /* !UNIV_HOTBACKUP */
@@ -2056,7 +2056,7 @@ recv_apply_log_recs_for_backup(void)
/* Extend the tablespace's last file if the page_no
does not fall inside its bounds; we assume the last
- file is auto-extending, and ibbackup copied the file
+ file is auto-extending, and mysqlbackup copied the file
when it still was smaller */
success = fil_extend_space_to_desired_size(
@@ -2427,10 +2427,10 @@ loop:
#ifdef UNIV_HOTBACKUP
if (recv_replay_file_ops) {
- /* In ibbackup --apply-log, replay an .ibd file
- operation, if possible; note that
- fil_path_to_mysql_datadir is set in ibbackup to
- point to the datadir we should use there */
+ /* In mysqlbackup --apply-log, replay an .ibd
+ file operation, if possible; note that
+ fil_path_to_mysql_datadir is set in mysqlbackup
+ to point to the datadir we should use there */
if (NULL == fil_op_log_parse_or_replay(
body, end_ptr, type,
@@ -3090,17 +3090,17 @@ recv_recovery_from_checkpoint_start_func(
if (srv_read_only_mode) {
ib_logf(IB_LOG_LEVEL_ERROR,
- "Cannot restore from ibbackup, InnoDB running "
- "in read-only mode!");
+ "Cannot restore from mysqlbackup, InnoDB "
+ "running in read-only mode!");
return(DB_ERROR);
}
- /* This log file was created by ibbackup --restore: print
+ /* This log file was created by mysqlbackup --restore: print
a note to the user about it */
ib_logf(IB_LOG_LEVEL_INFO,
- "The log file was created by ibbackup --apply-log "
+ "The log file was created by mysqlbackup --apply-log "
"at %s. The following crash recovery is part of a "
"normal restore.",
log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP);
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 3972ef4afe9..162c51425f4 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -1816,7 +1816,7 @@ os_file_delete_if_exists_func(
bool ret;
ulint count = 0;
loop:
- /* In Windows, deleting an .ibd file may fail if ibbackup is copying
+ /* In Windows, deleting an .ibd file may fail if mysqlbackup is copying
it */
ret = DeleteFile((LPCTSTR) name);
@@ -1841,7 +1841,7 @@ loop:
ib_logf(IB_LOG_LEVEL_WARN, "Delete of file %s failed.", name);
}
- os_thread_sleep(1000000); /* sleep for a second */
+ os_thread_sleep(500000); /* sleep for 0.5 second */
if (count > 2000) {
@@ -1878,7 +1878,7 @@ os_file_delete_func(
BOOL ret;
ulint count = 0;
loop:
- /* In Windows, deleting an .ibd file may fail if ibbackup is copying
+ /* In Windows, deleting an .ibd file may fail if mysqlbackup is copying
it */
ret = DeleteFile((LPCTSTR) name);
@@ -1901,7 +1901,7 @@ loop:
fprintf(stderr,
"InnoDB: Warning: cannot delete file %s\n"
- "InnoDB: Are you running ibbackup"
+ "InnoDB: Are you running mysqlbackup"
" to back up the file?\n", name);
}
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 4b19a35925e..6989953cb0c 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -3278,24 +3278,8 @@ page_zip_validate_low(
temp_page_buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
temp_page = static_cast<byte*>(ut_align(temp_page_buf, UNIV_PAGE_SIZE));
-#ifdef UNIV_DEBUG_VALGRIND
- /* Get detailed information on the valid bits in case the
- UNIV_MEM_ASSERT_RW() checks fail. The v-bits of page[],
- page_zip->data[] or page_zip could be viewed at temp_page[] or
- temp_page_zip in a debugger when running valgrind --db-attach. */
- (void) VALGRIND_GET_VBITS(page, temp_page, UNIV_PAGE_SIZE);
UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
-# if UNIV_WORD_SIZE == 4
- VALGRIND_GET_VBITS(page_zip, &temp_page_zip, sizeof temp_page_zip);
- /* On 32-bit systems, there is no padding in page_zip_des_t.
- On other systems, Valgrind could complain about uninitialized
- pad bytes. */
- UNIV_MEM_ASSERT_RW(page_zip, sizeof *page_zip);
-# endif
- (void) VALGRIND_GET_VBITS(page_zip->data, temp_page,
- page_zip_get_size(page_zip));
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
-#endif /* UNIV_DEBUG_VALGRIND */
temp_page_zip = *page_zip;
valid = page_zip_decompress(&temp_page_zip, temp_page, TRUE);
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 834dfe6f8eb..49bb5980548 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1711,12 +1711,11 @@ do_possible_lock_wait:
table case (check_ref == 0), since MDL lock will prevent
concurrent DDL and DML on the same table */
if (!check_ref) {
- for (const dict_foreign_t* check_foreign
- = UT_LIST_GET_FIRST( table->referenced_list);
- check_foreign;
- check_foreign = UT_LIST_GET_NEXT(
- referenced_list, check_foreign)) {
- if (check_foreign == foreign) {
+ for (dict_foreign_set::iterator it
+ = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+ if (*it == foreign) {
verified = true;
break;
}
@@ -1764,12 +1763,15 @@ row_ins_check_foreign_constraints(
trx = thr_get_trx(thr);
- foreign = UT_LIST_GET_FIRST(table->foreign_list);
-
DEBUG_SYNC_C_IF_THD(thr_get_trx(thr)->mysql_thd,
"foreign_constraint_check_for_ins");
- while (foreign) {
+ for (dict_foreign_set::iterator it = table->foreign_set.begin();
+ it != table->foreign_set.end();
+ ++it) {
+
+ foreign = *it;
+
if (foreign->foreign_index == index) {
dict_table_t* ref_table = NULL;
dict_table_t* foreign_table = foreign->foreign_table;
@@ -1825,8 +1827,6 @@ row_ins_check_foreign_constraints(
return(err);
}
}
-
- foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
return(DB_SUCCESS);
@@ -2858,7 +2858,7 @@ row_ins_clust_index_entry(
dberr_t err;
ulint n_uniq;
- if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
+ if (!index->table->foreign_set.empty()) {
err = row_ins_check_foreign_constraints(
index->table, index, entry, thr);
if (err != DB_SUCCESS) {
@@ -2916,7 +2916,7 @@ row_ins_sec_index_entry(
mem_heap_t* offsets_heap;
mem_heap_t* heap;
- if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
+ if (!index->table->foreign_set.empty()) {
err = row_ins_check_foreign_constraints(index->table, index,
entry, thr);
if (err != DB_SUCCESS) {
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index dd7af8a3526..ca70543a97b 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -63,6 +63,7 @@ Created 9/17/2000 Heikki Tuuri
#include "m_string.h"
#include "my_sys.h"
#include "ha_prototypes.h"
+#include <algorithm>
/** Provide optional 4.x backwards compatibility for 5.0 and above */
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
@@ -1573,8 +1574,6 @@ init_fts_doc_id_for_ref(
{
dict_foreign_t* foreign;
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
table->fk_max_recusive_level = 0;
(*depth)++;
@@ -1586,17 +1585,25 @@ init_fts_doc_id_for_ref(
/* Loop through this table's referenced list and also
recursively traverse each table's foreign table list */
- while (foreign && foreign->foreign_table) {
- if (foreign->foreign_table->fts) {
- fts_init_doc_id(foreign->foreign_table);
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
+ if (foreign->foreign_table == NULL) {
+ break;
}
- if (UT_LIST_GET_LEN(foreign->foreign_table->referenced_list)
- > 0 && foreign->foreign_table != table) {
- init_fts_doc_id_for_ref(foreign->foreign_table, depth);
+ if (foreign->foreign_table->fts != NULL) {
+ fts_init_doc_id(foreign->foreign_table);
}
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
+ if (!foreign->foreign_table->referenced_set.empty()
+ && foreign->foreign_table != table) {
+ init_fts_doc_id_for_ref(
+ foreign->foreign_table, depth);
+ }
}
}
@@ -2825,43 +2832,47 @@ row_discard_tablespace_foreign_key_checks(
const trx_t* trx, /*!< in: transaction handle */
const dict_table_t* table) /*!< in: table to be discarded */
{
- const dict_foreign_t* foreign;
+
+ if (srv_read_only_mode || !trx->check_foreigns) {
+ return(DB_SUCCESS);
+ }
/* Check if the table is referenced by foreign key constraints from
some other table (not the table itself) */
+ dict_foreign_set::iterator it
+ = std::find_if(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_different_tables());
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign && foreign->foreign_table == table;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
-
+ if (it == table->referenced_set.end()) {
+ return(DB_SUCCESS);
}
- if (!srv_read_only_mode && foreign && trx->check_foreigns) {
+ const dict_foreign_t* foreign = *it;
+ FILE* ef = dict_foreign_err_file;
- FILE* ef = dict_foreign_err_file;
+ ut_ad(foreign->foreign_table != table);
+ ut_ad(foreign->referenced_table == table);
- /* We only allow discarding a referenced table if
- FOREIGN_KEY_CHECKS is set to 0 */
+ /* We only allow discarding a referenced table if
+ FOREIGN_KEY_CHECKS is set to 0 */
- mutex_enter(&dict_foreign_err_mutex);
+ mutex_enter(&dict_foreign_err_mutex);
- rewind(ef);
+ rewind(ef);
- ut_print_timestamp(ef);
+ ut_print_timestamp(ef);
- fputs(" Cannot DISCARD table ", ef);
- ut_print_name(stderr, trx, TRUE, table->name);
- fputs("\n"
- "because it is referenced by ", ef);
- ut_print_name(stderr, trx, TRUE, foreign->foreign_table_name);
- putc('\n', ef);
+ fputs(" Cannot DISCARD table ", ef);
+ ut_print_name(stderr, trx, TRUE, table->name);
+ fputs("\n"
+ "because it is referenced by ", ef);
+ ut_print_name(stderr, trx, TRUE, foreign->foreign_table_name);
+ putc('\n', ef);
- mutex_exit(&dict_foreign_err_mutex);
-
- return(DB_CANNOT_DROP_CONSTRAINT);
- }
+ mutex_exit(&dict_foreign_err_mutex);
- return(DB_SUCCESS);
+ return(DB_CANNOT_DROP_CONSTRAINT);
}
/*********************************************************************//**
@@ -3164,7 +3175,6 @@ row_truncate_table_for_mysql(
dict_table_t* table, /*!< in: table handle */
trx_t* trx) /*!< in: transaction handle */
{
- dict_foreign_t* foreign;
dberr_t err;
mem_heap_t* heap;
byte* buf;
@@ -3256,18 +3266,17 @@ row_truncate_table_for_mysql(
/* Check if the table is referenced by foreign key constraints from
some other table (not the table itself) */
- for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
- foreign != 0 && foreign->foreign_table == table;
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
-
- /* Do nothing. */
- }
+ dict_foreign_set::iterator it
+ = std::find_if(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_different_tables());
if (!srv_read_only_mode
- && foreign
+ && it != table->referenced_set.end()
&& trx->check_foreigns) {
- FILE* ef = dict_foreign_err_file;
+ FILE* ef = dict_foreign_err_file;
+ dict_foreign_t* foreign = *it;
/* We only allow truncating a referenced table if
FOREIGN_KEY_CHECKS is set to 0 */
@@ -3868,42 +3877,45 @@ row_drop_table_for_mysql(
/* Check if the table is referenced by foreign key constraints from
some other table (not the table itself) */
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
+ if (!srv_read_only_mode && trx->check_foreigns) {
- while (foreign && foreign->foreign_table == table) {
-check_next_foreign:
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
+ for (dict_foreign_set::iterator it
+ = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
- if (!srv_read_only_mode
- && foreign
- && trx->check_foreigns
- && !(drop_db && dict_tables_have_same_db(
- name, foreign->foreign_table_name_lookup))) {
- FILE* ef = dict_foreign_err_file;
+ foreign = *it;
- /* We only allow dropping a referenced table if
- FOREIGN_KEY_CHECKS is set to 0 */
+ const bool ref_ok = drop_db
+ && dict_tables_have_same_db(
+ name,
+ foreign->foreign_table_name_lookup);
- err = DB_CANNOT_DROP_CONSTRAINT;
+ if (foreign->foreign_table != table && !ref_ok) {
- mutex_enter(&dict_foreign_err_mutex);
- rewind(ef);
- ut_print_timestamp(ef);
+ FILE* ef = dict_foreign_err_file;
- fputs(" Cannot drop table ", ef);
- ut_print_name(ef, trx, TRUE, name);
- fputs("\n"
- "because it is referenced by ", ef);
- ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
- putc('\n', ef);
- mutex_exit(&dict_foreign_err_mutex);
+ /* We only allow dropping a referenced table
+ if FOREIGN_KEY_CHECKS is set to 0 */
- goto funct_exit;
- }
+ err = DB_CANNOT_DROP_CONSTRAINT;
+
+ mutex_enter(&dict_foreign_err_mutex);
+ rewind(ef);
+ ut_print_timestamp(ef);
- if (foreign && trx->check_foreigns) {
- goto check_next_foreign;
+ fputs(" Cannot drop table ", ef);
+ ut_print_name(ef, trx, TRUE, name);
+ fputs("\n"
+ "because it is referenced by ", ef);
+ ut_print_name(ef, trx, TRUE,
+ foreign->foreign_table_name);
+ putc('\n', ef);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ goto funct_exit;
+ }
+ }
}
/* TODO: could we replace the counter n_foreign_key_checks_running
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index fb626519132..db810e28735 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -51,7 +51,7 @@ Created 12/27/1996 Heikki Tuuri
#include "pars0sym.h"
#include "eval0eval.h"
#include "buf0lru.h"
-
+#include <algorithm>
/* What kind of latch and lock can we assume when the control comes to
-------------------------------------------------------------------
@@ -136,12 +136,10 @@ row_upd_index_is_referenced(
trx_t* trx) /*!< in: transaction */
{
dict_table_t* table = index->table;
- dict_foreign_t* foreign;
ibool froze_data_dict = FALSE;
ibool is_referenced = FALSE;
- if (!UT_LIST_GET_FIRST(table->referenced_list)) {
-
+ if (table->referenced_set.empty()) {
return(FALSE);
}
@@ -150,19 +148,13 @@ row_upd_index_is_referenced(
froze_data_dict = TRUE;
}
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
-
- while (foreign) {
- if (foreign->referenced_index == index) {
-
- is_referenced = TRUE;
- goto func_exit;
- }
+ dict_foreign_set::iterator it
+ = std::find_if(table->referenced_set.begin(),
+ table->referenced_set.end(),
+ dict_foreign_with_index(index));
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
- }
+ is_referenced = (it != table->referenced_set.end());
-func_exit:
if (froze_data_dict) {
row_mysql_unfreeze_data_dictionary(trx);
}
@@ -200,7 +192,7 @@ row_upd_check_references_constraints(
dberr_t err;
ibool got_s_lock = FALSE;
- if (UT_LIST_GET_FIRST(table->referenced_list) == NULL) {
+ if (table->referenced_set.empty()) {
return(DB_SUCCESS);
}
@@ -227,9 +219,13 @@ row_upd_check_references_constraints(
}
run_again:
- foreign = UT_LIST_GET_FIRST(table->referenced_list);
- while (foreign) {
+ for (dict_foreign_set::iterator it = table->referenced_set.begin();
+ it != table->referenced_set.end();
+ ++it) {
+
+ foreign = *it;
+
/* Note that we may have an update which updates the index
record, but does NOT update the first fields which are
referenced in a foreign key constraint. Then the update does
@@ -282,8 +278,6 @@ run_again:
goto func_exit;
}
}
-
- foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
err = DB_SUCCESS;
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 8208d2d46e7..d1be5be9238 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1648,6 +1648,19 @@ innobase_start_or_create_for_mysql(void)
"" IB_ATOMICS_STARTUP_MSG "");
ib_logf(IB_LOG_LEVEL_INFO,
+ "" IB_MEMORY_BARRIER_STARTUP_MSG "");
+
+#ifndef HAVE_MEMORY_BARRIER
+#if defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64 || defined __WIN__
+#else
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "MySQL was built without a memory barrier capability on this"
+ " architecture, which might allow a mutex/rw_lock violation"
+ " under high thread concurrency. This may cause a hang.");
+#endif /* IA32 or AMD64 */
+#endif /* HAVE_MEMORY_BARRIER */
+
+ ib_logf(IB_LOG_LEVEL_INFO,
"Compressed tables use zlib " ZLIB_VERSION
#ifdef UNIV_ZIP_DEBUG
" with validation"
@@ -2631,13 +2644,6 @@ files_checked:
srv_undo_logs = ULONG_UNDEFINED;
}
- /* Flush the changes made to TRX_SYS_PAGE by trx_sys_create_rsegs()*/
- if (!srv_force_recovery && !srv_read_only_mode) {
- bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
- ut_a(success);
- buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
- }
-
if (!srv_read_only_mode) {
/* Create the thread which watches the timeouts
for lock waits */
diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc
index 6fad5f7d9ba..f643e5b794f 100644
--- a/storage/innobase/sync/sync0arr.cc
+++ b/storage/innobase/sync/sync0arr.cc
@@ -749,6 +749,7 @@ sync_arr_cell_can_wake_up(
mutex = static_cast<ib_mutex_t*>(cell->wait_object);
+ os_rmb;
if (mutex_get_lock_word(mutex) == 0) {
return(TRUE);
@@ -758,7 +759,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object);
- os_rmb;
+ os_rmb;
if (lock->lock_word > 0) {
/* Either unlocked or only read locked. */
@@ -770,7 +771,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word == 0 means all readers have left */
- os_rmb;
+ os_rmb;
if (lock->lock_word == 0) {
return(TRUE);
@@ -779,7 +780,7 @@ sync_arr_cell_can_wake_up(
lock = static_cast<rw_lock_t*>(cell->wait_object);
/* lock_word > 0 means no writer or reserved writer */
- os_rmb;
+ os_rmb;
if (lock->lock_word > 0) {
return(TRUE);
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index 49d2a2e21ea..8a211d81af5 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -388,7 +388,7 @@ lock_loop:
}
HMT_medium();
- if (lock->lock_word <= 0) {
+ if (i >= SYNC_SPIN_ROUNDS) {
os_thread_yield();
}
@@ -475,9 +475,9 @@ rw_lock_x_lock_wait(
counter_index = (size_t) os_thread_get_curr_id();
+ os_rmb;
ut_ad(lock->lock_word <= 0);
- os_rmb;
HMT_low();
while (lock->lock_word < 0) {
if (srv_spin_wait_delay) {
@@ -564,8 +564,11 @@ rw_lock_x_lock_low(
} else {
os_thread_id_t thread_id = os_thread_get_curr_id();
- if (!pass)
+
+ if (!pass) {
os_rmb;
+ }
+
/* Decrement failed: relock or failed lock */
if (!pass && lock->recursive
&& os_thread_eq(lock->writer_thread, thread_id)) {
@@ -657,7 +660,7 @@ lock_loop:
os_rmb;
}
HMT_medium();
- if (i == SYNC_SPIN_ROUNDS) {
+ if (i >= SYNC_SPIN_ROUNDS) {
os_thread_yield();
} else {
goto lock_loop;
diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc
index cc852b99497..6494191bfe9 100644
--- a/storage/innobase/sync/sync0sync.cc
+++ b/storage/innobase/sync/sync0sync.cc
@@ -127,7 +127,7 @@ it and did not see the waiters byte set to 1, a case which would lead the
other thread to an infinite wait.
LEMMA 1: After a thread resets the event of a mutex (or rw_lock), some
-=======
+======
thread will eventually call os_event_set() on that particular event.
Thus no infinite wait is possible in this case.
@@ -140,7 +140,7 @@ os_event_set() with the mutex as an argument.
Q.E.D.
LEMMA 2: If an os_event_set() call is made after some thread has called
-=======
+======
the os_event_reset() and before it starts wait on that event, the call
will not be lost to the second thread. This is true even if there is an
intervening call to os_event_reset() by another thread.
@@ -504,16 +504,16 @@ mutex_loop:
spin_loop:
HMT_low();
+ os_rmb;
while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) {
if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
}
- os_rmb; // Ensure future reads sees new values
i++;
}
HMT_medium();
- if (i == SYNC_SPIN_ROUNDS) {
+ if (i >= SYNC_SPIN_ROUNDS) {
os_thread_yield();
}
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index fcf1c1cedf4..52830a77b12 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -952,7 +952,7 @@ trx_sys_print_mysql_binlog_offset_from_page(
== TRX_SYS_MYSQL_LOG_MAGIC_N) {
fprintf(stderr,
- "ibbackup: Last MySQL binlog file position %lu %lu,"
+ "mysqlbackup: Last MySQL binlog file position %lu %lu,"
" file name %s\n",
(ulong) mach_read_from_4(
sys_header + TRX_SYS_MYSQL_LOG_INFO
@@ -1003,9 +1003,9 @@ trx_sys_read_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to read system tablespace "
- "file format,\n"
- " ibbackup: but could not open the tablespace "
+ " mysqlbackup: Error: trying to read system "
+ "tablespace file format,\n"
+ " mysqlbackup: but could not open the tablespace "
"file %s!\n", pathname);
return(FALSE);
}
@@ -1022,9 +1022,9 @@ trx_sys_read_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to read system tablespace "
- "file format,\n"
- " ibbackup: but failed to read the tablespace "
+ " mysqlbackup: Error: trying to read system "
+ "tablespace file format,\n"
+ " mysqlbackup: but failed to read the tablespace "
"file %s!\n", pathname);
os_file_close(file);
@@ -1083,9 +1083,9 @@ trx_sys_read_pertable_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to read per-table "
+ " mysqlbackup: Error: trying to read per-table "
"tablespace format,\n"
- " ibbackup: but could not open the tablespace "
+ " mysqlbackup: but could not open the tablespace "
"file %s!\n", pathname);
return(FALSE);
@@ -1102,9 +1102,9 @@ trx_sys_read_pertable_file_format_id(
ut_print_timestamp(stderr);
fprintf(stderr,
- " ibbackup: Error: trying to per-table data file "
+ " mysqlbackup: Error: trying to per-table data file "
"format,\n"
- " ibbackup: but failed to read the tablespace "
+ " mysqlbackup: but failed to read the tablespace "
"file %s!\n", pathname);
os_file_close(file);