1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

Merge mysql-5.5-innodb -> mysql-5.5

This commit is contained in:
Vasil Dimov
2011-04-04 09:12:11 +03:00
45 changed files with 1022 additions and 1156 deletions

View File

@ -0,0 +1,73 @@
CREATE TABLE Bug_60196_FK1 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE Bug_60196_FK2 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE Bug_60196 (
FK1_Key INT NOT NULL,
FK2_Key INT NOT NULL,
PRIMARY KEY (FK2_Key, FK1_Key),
KEY FK1_Key (FK1_Key),
KEY FK2_Key (FK2_Key),
CONSTRAINT FK_FK1 FOREIGN KEY (FK1_Key)
REFERENCES Bug_60196_FK1 (Primary_Key)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT FK_FK2 FOREIGN KEY (FK2_Key)
REFERENCES Bug_60196_FK2 (Primary_Key)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
INSERT INTO Bug_60196_FK1 VALUES (1), (2), (3), (4), (5);
INSERT INTO Bug_60196_FK2 VALUES (1), (2), (3), (4), (5);
INSERT INTO Bug_60196 VALUES (1, 1);
INSERT INTO Bug_60196 VALUES (1, 2);
INSERT INTO Bug_60196 VALUES (1, 3);
INSERT INTO Bug_60196 VALUES (1, 99);
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`bug_60196`, CONSTRAINT `FK_FK2` FOREIGN KEY (`FK2_Key`) REFERENCES `Bug_60196_FK2` (`Primary_Key`) ON DELETE CASCADE ON UPDATE CASCADE)
INSERT INTO Bug_60196 VALUES (99, 1);
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`bug_60196`, CONSTRAINT `FK_FK1` FOREIGN KEY (`FK1_Key`) REFERENCES `Bug_60196_FK1` (`Primary_Key`) ON DELETE CASCADE ON UPDATE CASCADE)
SELECT * FROM bug_60196_FK1;
Primary_Key
1
2
3
4
5
SELECT * FROM bug_60196_FK2;
Primary_Key
1
2
3
4
5
SELECT * FROM bug_60196;
FK1_Key FK2_Key
1 1
1 2
1 3
# Stop server
# Restart server.
#
# Try to insert more to the example table with foreign keys.
# Bug60196 causes the foreign key file not to be found after
# the resstart above.
#
SELECT * FROM Bug_60196;
FK1_Key FK2_Key
1 1
1 2
1 3
INSERT INTO Bug_60196 VALUES (2, 1);
INSERT INTO Bug_60196 VALUES (2, 2);
INSERT INTO Bug_60196 VALUES (2, 3);
SELECT * FROM Bug_60196;
FK1_Key FK2_Key
1 1
1 2
1 3
2 1
2 2
2 3
# Clean up.
DROP TABLE Bug_60196;
DROP TABLE Bug_60196_FK1;
DROP TABLE Bug_60196_FK2;

View File

@ -0,0 +1 @@
--lower-case-table-names=2

View File

@ -0,0 +1,87 @@
# Bug#60196 - Setting lowercase_table_names to 2 on Windows causing
# Foreign Key problems after an engine is restarted.
# This test case needs InnoDB, a lowercase file system,
# lower-case-table-names=2, and cannot use the embedded server
# because it restarts the server.
--source include/not_embedded.inc
--source include/have_lowercase2.inc
--source include/have_case_insensitive_file_system.inc
--source include/have_innodb.inc
#
# Create test data.
#
CREATE TABLE Bug_60196_FK1 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE Bug_60196_FK2 (Primary_Key INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE Bug_60196 (
FK1_Key INT NOT NULL,
FK2_Key INT NOT NULL,
PRIMARY KEY (FK2_Key, FK1_Key),
KEY FK1_Key (FK1_Key),
KEY FK2_Key (FK2_Key),
CONSTRAINT FK_FK1 FOREIGN KEY (FK1_Key)
REFERENCES Bug_60196_FK1 (Primary_Key)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT FK_FK2 FOREIGN KEY (FK2_Key)
REFERENCES Bug_60196_FK2 (Primary_Key)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
INSERT INTO Bug_60196_FK1 VALUES (1), (2), (3), (4), (5);
INSERT INTO Bug_60196_FK2 VALUES (1), (2), (3), (4), (5);
INSERT INTO Bug_60196 VALUES (1, 1);
INSERT INTO Bug_60196 VALUES (1, 2);
INSERT INTO Bug_60196 VALUES (1, 3);
--error ER_NO_REFERENCED_ROW_2
INSERT INTO Bug_60196 VALUES (1, 99);
--error ER_NO_REFERENCED_ROW_2
INSERT INTO Bug_60196 VALUES (99, 1);
SELECT * FROM bug_60196_FK1;
SELECT * FROM bug_60196_FK2;
SELECT * FROM bug_60196;
--echo # Stop server
# Write file to make mysql-test-run.pl wait for the server to stop
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
# Send a shutdown request to the server
-- shutdown_server 10
# Call script that will poll the server waiting for it to disapear
-- source include/wait_until_disconnected.inc
--echo # Restart server.
# Write file to make mysql-test-run.pl start up the server again
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
# Turn on reconnect
--enable_reconnect
# Call script that will poll the server waiting for it to be back online again
--source include/wait_until_connected_again.inc
# Turn off reconnect again
--disable_reconnect
--echo #
--echo # Try to insert more to the example table with foreign keys.
--echo # Bug60196 causes the foreign key file not to be found after
--echo # the resstart above.
--echo #
SELECT * FROM Bug_60196;
INSERT INTO Bug_60196 VALUES (2, 1);
INSERT INTO Bug_60196 VALUES (2, 2);
INSERT INTO Bug_60196 VALUES (2, 3);
SELECT * FROM Bug_60196;
--echo
--echo # Clean up.
DROP TABLE Bug_60196;
DROP TABLE Bug_60196_FK1;
DROP TABLE Bug_60196_FK2;

View File

@ -241,7 +241,6 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
row/row0sel.c row/row0uins.c row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
srv/srv0srv.c srv/srv0start.c
sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
thr/thr0loc.c
trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
usr/usr0sess.c

View File

@ -402,7 +402,7 @@ btr_cur_search_to_nth_level(
ut_ad(level == 0 || mode == PAGE_CUR_LE);
ut_ad(dict_index_check_search_tuple(index, tuple));
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside());
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr));
ut_ad(dtuple_check_typed(tuple));
#ifdef UNIV_DEBUG
@ -4904,27 +4904,45 @@ btr_copy_blob_prefix(
/*******************************************************************//**
Copies the prefix of a compressed BLOB. The clustered index record
that points to this BLOB must be protected by a lock or a page latch. */
that points to this BLOB must be protected by a lock or a page latch.
@return number of bytes written to buf */
static
void
ulint
btr_copy_zblob_prefix(
/*==================*/
z_stream* d_stream,/*!< in/out: the decompressing stream */
byte* buf, /*!< out: the externally stored part of
the field, or a prefix of it */
ulint len, /*!< in: length of buf, in bytes */
ulint zip_size,/*!< in: compressed BLOB page size */
ulint space_id,/*!< in: space id of the BLOB pages */
ulint page_no,/*!< in: page number of the first BLOB page */
ulint offset) /*!< in: offset on the first BLOB page */
{
ulint page_type = FIL_PAGE_TYPE_ZBLOB;
ulint page_type = FIL_PAGE_TYPE_ZBLOB;
mem_heap_t* heap;
int err;
z_stream d_stream;
d_stream.next_out = buf;
d_stream.avail_out = len;
d_stream.next_in = Z_NULL;
d_stream.avail_in = 0;
/* Zlib inflate needs 32 kilobytes for the default
window size, plus a few kilobytes for small objects. */
heap = mem_heap_create(40000);
page_zip_set_alloc(&d_stream, heap);
ut_ad(ut_is_2pow(zip_size));
ut_ad(zip_size >= PAGE_ZIP_MIN_SIZE);
ut_ad(zip_size <= UNIV_PAGE_SIZE);
ut_ad(space_id);
err = inflateInit(&d_stream);
ut_a(err == Z_OK);
for (;;) {
buf_page_t* bpage;
int err;
ulint next_page_no;
/* There is no latch on bpage directly. Instead,
@ -4940,7 +4958,7 @@ btr_copy_zblob_prefix(
" compressed BLOB"
" page %lu space %lu\n",
(ulong) page_no, (ulong) space_id);
return;
goto func_exit;
}
if (UNIV_UNLIKELY
@ -4966,13 +4984,13 @@ btr_copy_zblob_prefix(
offset += 4;
}
d_stream->next_in = bpage->zip.data + offset;
d_stream->avail_in = zip_size - offset;
d_stream.next_in = bpage->zip.data + offset;
d_stream.avail_in = zip_size - offset;
err = inflate(d_stream, Z_NO_FLUSH);
err = inflate(&d_stream, Z_NO_FLUSH);
switch (err) {
case Z_OK:
if (!d_stream->avail_out) {
if (!d_stream.avail_out) {
goto end_of_blob;
}
break;
@ -4989,13 +5007,13 @@ inflate_error:
" compressed BLOB"
" page %lu space %lu returned %d (%s)\n",
(ulong) page_no, (ulong) space_id,
err, d_stream->msg);
err, d_stream.msg);
case Z_BUF_ERROR:
goto end_of_blob;
}
if (next_page_no == FIL_NULL) {
if (!d_stream->avail_in) {
if (!d_stream.avail_in) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: unexpected end of"
@ -5004,7 +5022,7 @@ inflate_error:
(ulong) page_no,
(ulong) space_id);
} else {
err = inflate(d_stream, Z_FINISH);
err = inflate(&d_stream, Z_FINISH);
switch (err) {
case Z_STREAM_END:
case Z_BUF_ERROR:
@ -5016,7 +5034,7 @@ inflate_error:
end_of_blob:
buf_page_release_zip(bpage);
return;
goto func_exit;
}
buf_page_release_zip(bpage);
@ -5028,6 +5046,12 @@ end_of_blob:
offset = FIL_PAGE_NEXT;
page_type = FIL_PAGE_TYPE_ZBLOB2;
}
func_exit:
inflateEnd(&d_stream);
mem_heap_free(heap);
UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
return(d_stream.total_out);
}
/*******************************************************************//**
@ -5053,28 +5077,8 @@ btr_copy_externally_stored_field_prefix_low(
}
if (UNIV_UNLIKELY(zip_size)) {
int err;
z_stream d_stream;
mem_heap_t* heap;
/* Zlib inflate needs 32 kilobytes for the default
window size, plus a few kilobytes for small objects. */
heap = mem_heap_create(40000);
page_zip_set_alloc(&d_stream, heap);
err = inflateInit(&d_stream);
ut_a(err == Z_OK);
d_stream.next_out = buf;
d_stream.avail_out = len;
d_stream.avail_in = 0;
btr_copy_zblob_prefix(&d_stream, zip_size,
space_id, page_no, offset);
inflateEnd(&d_stream);
mem_heap_free(heap);
UNIV_MEM_ASSERT_RW(buf, d_stream.total_out);
return(d_stream.total_out);
return(btr_copy_zblob_prefix(buf, len, zip_size,
space_id, page_no, offset));
} else {
return(btr_copy_blob_prefix(buf, len, space_id,
page_no, offset));

View File

@ -1213,8 +1213,8 @@ btr_search_drop_page_hash_when_freed(
having to fear a deadlock. */
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
BUF_GET_IF_IN_POOL, __FILE__, __LINE__,
&mtr);
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
&mtr);
/* Because the buffer pool mutex was released by
buf_page_peek_if_search_hashed(), it is possible that the
block was removed from the buffer pool by another thread

View File

@ -1233,7 +1233,7 @@ buf_pool_init_instance(
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
buf_pool->last_printout_time = ut_time();
}
/* 2. Initialize flushing fields
@ -1365,11 +1365,11 @@ buf_pool_drop_hash_index_instance(
/* block->is_hashed cannot be modified
when we have an x-latch on btr_search_latch;
see the comment in buf0buf.h */
if (!block->is_hashed) {
continue;
}
/* To follow the latching order, we
have to release btr_search_latch
before acquiring block->latch. */
@ -1378,14 +1378,14 @@ buf_pool_drop_hash_index_instance(
we must rescan all blocks, because
some may become hashed again. */
*released_search_latch = TRUE;
rw_lock_x_lock(&block->lock);
/* This should be guaranteed by the
callers, which will be holding
btr_search_enabled_mutex. */
ut_ad(!btr_search_enabled);
/* Because we did not buffer-fix the
block by calling buf_block_get_gen(),
it is possible that the block has been
@ -1395,7 +1395,7 @@ buf_pool_drop_hash_index_instance(
block is mapped to. All we want to do
is to drop any hash entries referring
to the page. */
/* It is possible that
block->page.state != BUF_FILE_PAGE.
Even that does not matter, because
@ -1403,18 +1403,18 @@ buf_pool_drop_hash_index_instance(
check block->is_hashed before doing
anything. block->is_hashed can only
be set on uncompressed file pages. */
btr_search_drop_page_hash_index(block);
rw_lock_x_unlock(&block->lock);
rw_lock_x_lock(&btr_search_latch);
ut_ad(!btr_search_enabled);
}
}
}
/********************************************************************//**
Drops the adaptive hash index. To prevent a livelock, this function
is only to be called while holding btr_search_latch and while
@ -1990,30 +1990,30 @@ buf_pool_resize(void)
ulint min_change_size = 1048576 * srv_buf_pool_instances;
buf_pool_mutex_enter_all();
if (srv_buf_pool_old_size == srv_buf_pool_size) {
buf_pool_mutex_exit_all();
return;
} else if (srv_buf_pool_curr_size + min_change_size
> srv_buf_pool_size) {
change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
/ UNIV_PAGE_SIZE;
buf_pool_mutex_exit_all();
/* Disable adaptive hash indexes and empty the index
in order to free up memory in the buffer pool chunks. */
buf_pool_shrink(change_size);
} else if (srv_buf_pool_curr_size + min_change_size
< srv_buf_pool_size) {
/* Enlarge the buffer pool by at least one megabyte */
change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
buf_pool_mutex_exit_all();
@ -2026,10 +2026,10 @@ buf_pool_resize(void)
return;
}
buf_pool_page_hash_rebuild();
}
/****************************************************************//**
Remove the sentinel block for the watch before replacing it with a real block.
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
@ -2316,9 +2316,6 @@ buf_page_get_zip(
unsigned access_time;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
#ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside());
#endif
buf_pool->stat.n_page_gets++;
for (;;) {
@ -2533,16 +2530,19 @@ buf_block_align_instance(
/* TODO: protect buf_pool->chunks with a mutex (it will
currently remain constant after buf_pool_init()) */
for (chunk = buf_pool->chunks, i = buf_pool->n_chunks; i--; chunk++) {
lint offs = ptr - chunk->blocks->frame;
ulint offs;
if (UNIV_UNLIKELY(offs < 0)) {
if (UNIV_UNLIKELY(ptr < chunk->blocks->frame)) {
continue;
}
/* else */
offs = ptr - chunk->blocks->frame;
offs >>= UNIV_PAGE_SIZE_SHIFT;
if (UNIV_LIKELY((ulint) offs < chunk->size)) {
if (UNIV_LIKELY(offs < chunk->size)) {
buf_block_t* block = &chunk->blocks[offs];
/* The function buf_chunk_init() invokes
@ -2719,7 +2719,7 @@ buf_page_get_gen(
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
buf_block_t* guess, /*!< in: guessed block or NULL */
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
BUF_GET_NO_LATCH, or
BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or
BUF_GET_IF_IN_POOL_OR_WATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
@ -2738,16 +2738,26 @@ buf_page_get_gen(
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_NO_LATCH));
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
ut_ad(mode == BUF_GET
|| mode == BUF_GET_IF_IN_POOL
|| mode == BUF_GET_NO_LATCH
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH);
#ifdef UNIV_DEBUG
switch (mode) {
case BUF_GET_NO_LATCH:
ut_ad(rw_latch == RW_NO_LATCH);
break;
case BUF_GET:
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
break;
default:
ut_error;
}
#endif /* UNIV_DEBUG */
ut_ad(zip_size == fil_space_get_zip_size(space));
ut_ad(ut_is_2pow(zip_size));
#ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside() || ibuf_page_low(space, zip_size, offset,
FALSE, file, line, NULL));
ut_ad(!ibuf_inside(mtr)
|| ibuf_page_low(space, zip_size, offset,
FALSE, file, line, NULL));
#endif
buf_pool->stat.n_page_gets++;
fold = buf_page_address_fold(space, offset);
@ -2802,6 +2812,7 @@ loop2:
buf_pool_mutex_exit(buf_pool);
if (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_PEEK_IF_IN_POOL
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
return(NULL);
@ -2842,7 +2853,8 @@ got_block:
must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
if (must_read && mode == BUF_GET_IF_IN_POOL) {
if (must_read && (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_PEEK_IF_IN_POOL)) {
/* The page is being read to buffer pool,
but we cannot wait around for the read to
@ -2876,7 +2888,7 @@ wait_until_unfixed:
Try again later. */
buf_pool_mutex_exit(buf_pool);
os_thread_sleep(WAIT_FOR_READ);
goto loop;
}
@ -2965,6 +2977,7 @@ wait_until_unfixed:
mutex_exit(&buf_pool->zip_mutex);
buf_pool->n_pend_unzip++;
bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
buf_pool_mutex_exit(buf_pool);
@ -3058,7 +3071,9 @@ wait_until_unfixed:
buf_pool_mutex_exit(buf_pool);
buf_page_set_accessed_make_young(&block->page, access_time);
if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
buf_page_set_accessed_make_young(&block->page, access_time);
}
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!block->page.file_page_was_freed);
@ -3111,11 +3126,12 @@ wait_until_unfixed:
mtr_memo_push(mtr, block, fix_type);
if (!access_time) {
if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL) && !access_time) {
/* In the case of a first access, try to apply linear
read-ahead */
buf_read_ahead_linear(space, zip_size, offset);
buf_read_ahead_linear(space, zip_size, offset,
ibuf_inside(mtr));
}
#ifdef UNIV_IBUF_COUNT_DEBUG
@ -3172,7 +3188,7 @@ buf_page_optimistic_get(
access_time = buf_page_is_accessed(&block->page);
buf_page_set_accessed_make_young(&block->page, access_time);
ut_ad(!ibuf_inside()
ut_ad(!ibuf_inside(mtr)
|| ibuf_page(buf_block_get_space(block),
buf_block_get_zip_size(block),
buf_block_get_page_no(block), NULL));
@ -3228,7 +3244,8 @@ buf_page_optimistic_get(
buf_read_ahead_linear(buf_block_get_space(block),
buf_block_get_zip_size(block),
buf_block_get_page_no(block));
buf_block_get_page_no(block),
ibuf_inside(mtr));
}
#ifdef UNIV_IBUF_COUNT_DEBUG
@ -3304,7 +3321,7 @@ buf_page_get_known_nowait(
buf_pool_mutex_exit(buf_pool);
}
ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
if (rw_latch == RW_S_LATCH) {
success = rw_lock_s_lock_nowait(&(block->lock),
@ -3569,14 +3586,13 @@ buf_page_init_for_read(
/* It is a read-ahead within an ibuf routine */
ut_ad(!ibuf_bitmap_page(zip_size, offset));
ut_ad(ibuf_inside());
mtr_start(&mtr);
ibuf_mtr_start(&mtr);
if (!recv_no_ibuf_operations
&& !ibuf_page(space, zip_size, offset, &mtr)) {
mtr_commit(&mtr);
ibuf_mtr_commit(&mtr);
return(NULL);
}
@ -3700,6 +3716,7 @@ err_exit:
/* The block was added by some other thread. */
watch_page = NULL;
bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
buf_buddy_free(buf_pool, data, zip_size);
@ -3760,7 +3777,7 @@ func_exit:
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
mtr_commit(&mtr);
ibuf_mtr_commit(&mtr);
}
ut_ad(!bpage || buf_page_in_file(bpage));
@ -4788,7 +4805,7 @@ buf_get_modified_ratio_pct(void)
buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
/* 1 + is there to avoid division by zero */
return(ratio);
@ -5171,7 +5188,7 @@ buf_all_freed(void)
return(TRUE);
}
/*********************************************************************//**
Checks that there currently are no pending i/o-operations for the buffer
pool.

View File

@ -247,74 +247,78 @@ buf_LRU_drop_page_hash_for_tablespace(
sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE);
buf_pool_mutex_enter(buf_pool);
num_entries = 0;
scan_again:
num_entries = 0;
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
mutex_t* block_mutex = buf_page_get_mutex(bpage);
buf_page_t* prev_bpage;
ibool is_fixed;
mutex_enter(block_mutex);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
ut_a(buf_page_in_file(bpage));
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
|| bpage->space != id
|| bpage->buf_fix_count > 0
|| bpage->io_fix != BUF_IO_NONE) {
/* We leave the fixed pages as is in this scan.
To be dealt with later in the final scan. */
mutex_exit(block_mutex);
/* Compressed pages are never hashed.
Skip blocks of other tablespaces.
Skip I/O-fixed blocks (to be dealt with later). */
next_page:
bpage = prev_bpage;
continue;
}
mutex_enter(&((buf_block_t*) bpage)->mutex);
is_fixed = bpage->buf_fix_count > 0
|| !((buf_block_t*) bpage)->is_hashed;
mutex_exit(&((buf_block_t*) bpage)->mutex);
if (is_fixed) {
goto next_page;
}
if (((buf_block_t*) bpage)->is_hashed) {
/* Store the page number so that we can drop the hash
index in a batch later. */
page_arr[num_entries] = bpage->offset;
ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
++num_entries;
/* Store the offset(i.e.: page_no) in the array
so that we can drop hash index in a batch
later. */
page_arr[num_entries] = bpage->offset;
mutex_exit(block_mutex);
ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
++num_entries;
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
goto next_page;
}
/* Array full. We release the buf_pool->mutex to
obey the latching order. */
buf_pool_mutex_exit(buf_pool);
buf_LRU_drop_page_hash_batch(
id, zip_size, page_arr, num_entries);
num_entries = 0;
buf_pool_mutex_enter(buf_pool);
} else {
mutex_exit(block_mutex);
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
goto next_page;
}
next_page:
/* Note that we may have released the buf_pool mutex
above after reading the prev_bpage during processing
of a page_hash_batch (i.e.: when the array was full).
This means that prev_bpage can change in LRU list.
This is OK because this function is a 'best effort'
to drop as many search hash entries as possible and
it does not guarantee that ALL such entries will be
dropped. */
bpage = prev_bpage;
/* Array full. We release the buf_pool->mutex to obey
the latching order. */
buf_pool_mutex_exit(buf_pool);
buf_LRU_drop_page_hash_batch(
id, zip_size, page_arr, num_entries);
num_entries = 0;
buf_pool_mutex_enter(buf_pool);
/* Note that we released the buf_pool mutex above
after reading the prev_bpage during processing of a
page_hash_batch (i.e.: when the array was full).
Because prev_bpage could belong to a compressed-only
block, it may have been relocated, and thus the
pointer cannot be trusted. Because bpage is of type
buf_block_t, it is safe to dereference.
bpage can change in the LRU list. This is OK because
this function is a 'best effort' to drop as many
search hash entries as possible and it does not
guarantee that ALL such entries will be dropped. */
/* If, however, bpage has been removed from LRU list
to the free list then we should restart the scan.
bpage->state is protected by buf_pool mutex. */
if (bpage && !buf_page_in_file(bpage)) {
ut_a(num_entries == 0);
if (bpage
&& buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
goto scan_again;
}
}
@ -1889,6 +1893,7 @@ buf_LRU_block_remove_hashed_page(
buf_pool, bpage->zip.data,
page_zip_get_size(&bpage->zip));
bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_free(buf_pool, bpage, sizeof(*bpage));
buf_pool_mutex_exit_allow(buf_pool);

View File

@ -236,10 +236,10 @@ UNIV_INTERN
ulint
buf_read_ahead_linear(
/*==================*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset) /*!< in: page number of a page; NOTE: the current thread
must want access to this page (see NOTE 3 above) */
ulint space, /*!< in: space id */
ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
ulint offset, /*!< in: page number; see NOTE 3 above */
ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf routine */
{
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ib_int64_t tablespace_version;
@ -429,11 +429,9 @@ buf_read_ahead_linear(
/* If we got this far, read-ahead can be sensible: do it */
if (ibuf_inside()) {
ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
} else {
ibuf_mode = BUF_READ_ANY_PAGE;
}
ibuf_mode = inside_ibuf
? BUF_READ_IBUF_PAGES_ONLY | OS_AIO_SIMULATED_WAKE_LATER
: BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER;
count = 0;
@ -450,7 +448,7 @@ buf_read_ahead_linear(
if (!ibuf_bitmap_page(zip_size, i)) {
count += buf_read_page_low(
&err, FALSE,
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
ibuf_mode,
space, zip_size, FALSE, tablespace_version, i);
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
@ -520,7 +518,6 @@ buf_read_ibuf_merge_pages(
{
ulint i;
ut_ad(!ibuf_inside());
#ifdef UNIV_IBUF_DEBUG
ut_a(n_stored < UNIV_PAGE_SIZE);
#endif

View File

@ -2258,10 +2258,12 @@ loop:
/* Since table names in SYS_FOREIGN are stored in a case-insensitive
order, we have to check that the table name matches also in a binary
string comparison. On Unix, MySQL allows table names that only differ
in character case. */
if (0 != ut_memcmp(field, table_name, len)) {
in character case. If lower_case_table_names=2 then what is stored
may not be the same case, but the previous comparison showed that they
match with no-case. */
if ((srv_lower_case_table_names != 2)
&& (0 != ut_memcmp(field, table_name, len))) {
goto next_rec;
}

View File

@ -4342,8 +4342,6 @@ fil_io(
ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
|| !ibuf_bitmap_page(zip_size, block_offset)
|| sync || is_log);
ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
|| ibuf_page(space_id, zip_size, block_offset, NULL));
# endif /* UNIV_LOG_DEBUG */
if (sync) {
mode = OS_AIO_SYNC;

View File

@ -51,6 +51,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <mysql/plugin.h>
#include <mysql/innodb_priv.h>
#include <mysql/psi/psi.h>
#include <my_sys.h>
/** @file ha_innodb.cc */
@ -81,7 +82,6 @@ extern "C" {
#include "fil0fil.h"
#include "trx0xa.h"
#include "row0merge.h"
#include "thr0loc.h"
#include "dict0boot.h"
#include "ha_prototypes.h"
#include "ut0mem.h"
@ -279,7 +279,6 @@ static PSI_mutex_info all_innodb_mutexes[] = {
{&sync_thread_mutex_key, "sync_thread_mutex", 0},
# endif /* UNIV_SYNC_DEBUG */
{&trx_doublewrite_mutex_key, "trx_doublewrite_mutex", 0},
{&thr_local_mutex_key, "thr_local_mutex", 0},
{&trx_undo_mutex_key, "trx_undo_mutex", 0}
};
# endif /* UNIV_PFS_MUTEX */
@ -1146,6 +1145,20 @@ innobase_strcasecmp(
return(my_strcasecmp(system_charset_info, a, b));
}
/******************************************************************//**
Strip dir name from a full path name and return only the file name
@return file name or "null" if no file name */
extern "C" UNIV_INTERN
const char*
innobase_basename(
/*==============*/
const char* path_name) /*!< in: full path name */
{
const char* name = base_name(path_name);
return((name) ? name : "null");
}
/******************************************************************//**
Makes all characters in a NUL-terminated UTF-8 string lower case. */
extern "C" UNIV_INTERN
@ -3028,7 +3041,6 @@ innobase_close_connection(
innobase_rollback_trx(trx);
thr_local_free(trx->mysql_thread_id);
trx_free_for_mysql(trx);
DBUG_RETURN(0);
@ -9263,7 +9275,8 @@ innodb_mutex_show_status(
if (mutex->count_using > 0) {
buf1len= my_snprintf(buf1, sizeof(buf1),
"%s:%s",
mutex->cmutex_name, mutex->cfile_name);
mutex->cmutex_name,
innobase_basename(mutex->cfile_name));
buf2len= my_snprintf(buf2, sizeof(buf2),
"count=%lu, spin_waits=%lu,"
" spin_rounds=%lu, "
@ -9293,7 +9306,8 @@ innodb_mutex_show_status(
}
#else /* UNIV_DEBUG */
buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu",
mutex->cfile_name, (ulong) mutex->cline);
innobase_basename(mutex->cfile_name),
(ulong) mutex->cline);
buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
(ulong) mutex->count_os_wait);
@ -9309,7 +9323,8 @@ innodb_mutex_show_status(
if (block_mutex) {
buf1len = (uint) my_snprintf(buf1, sizeof buf1,
"combined %s:%lu",
block_mutex->cfile_name,
innobase_basename(
block_mutex->cfile_name),
(ulong) block_mutex->cline);
buf2len = (uint) my_snprintf(buf2, sizeof buf2,
"os_waits=%lu",
@ -9340,7 +9355,8 @@ innodb_mutex_show_status(
}
buf1len = my_snprintf(buf1, sizeof buf1, "%s:%lu",
lock->cfile_name, (ulong) lock->cline);
innobase_basename(lock->cfile_name),
(ulong) lock->cline);
buf2len = my_snprintf(buf2, sizeof buf2, "os_waits=%lu",
(ulong) lock->count_os_wait);
@ -9355,7 +9371,8 @@ innodb_mutex_show_status(
if (block_lock) {
buf1len = (uint) my_snprintf(buf1, sizeof buf1,
"combined %s:%lu",
block_lock->cfile_name,
innobase_basename(
block_lock->cfile_name),
(ulong) block_lock->cline);
buf2len = (uint) my_snprintf(buf2, sizeof buf2,
"os_waits=%lu",
@ -11359,7 +11376,7 @@ mysql_declare_plugin(innobase)
MYSQL_STORAGE_ENGINE_PLUGIN,
&innobase_storage_engine,
innobase_hton_name,
"Innobase Oy",
plugin_author,
"Supports transactions, row-level locking, and foreign keys",
PLUGIN_LICENSE_GPL,
innobase_init, /* Plugin Init */

View File

@ -47,8 +47,6 @@ extern "C" {
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
}
static const char plugin_author[] = "Innobase Oy";
#define OK(expr) \
if ((expr) != 0) { \
DBUG_RETURN(1); \
@ -1059,7 +1057,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits =
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, "Innobase Oy"),
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */

View File

@ -26,6 +26,8 @@ Created July 18, 2007 Vasil Dimov
#ifndef i_s_h
#define i_s_h
const char plugin_author[] = "Oracle Corporation";
extern struct st_mysql_plugin i_s_innodb_trx;
extern struct st_mysql_plugin i_s_innodb_locks;
extern struct st_mysql_plugin i_s_innodb_lock_waits;

File diff suppressed because it is too large Load Diff

View File

@ -150,7 +150,7 @@ UNIV_INLINE
ulint
btr_pcur_get_up_match(
/*==================*/
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
const btr_pcur_t* cursor); /*!< in: persistent cursor */
/**************************************************************//**
Gets the low_match value for a pcur after a search.
@return number of matched fields at the cursor or to the right if
@ -159,7 +159,7 @@ UNIV_INLINE
ulint
btr_pcur_get_low_match(
/*===================*/
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
const btr_pcur_t* cursor); /*!< in: persistent cursor */
/**************************************************************//**
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
user record satisfying the search condition, in the case PAGE_CUR_L or
@ -264,22 +264,6 @@ ulint
btr_pcur_get_rel_pos(
/*=================*/
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Sets the mtr field for a pcur. */
UNIV_INLINE
void
btr_pcur_set_mtr(
/*=============*/
btr_pcur_t* cursor, /*!< in: persistent cursor */
mtr_t* mtr); /*!< in, own: mtr */
/*********************************************************//**
Gets the mtr field for a pcur.
@return mtr */
UNIV_INLINE
mtr_t*
btr_pcur_get_mtr(
/*=============*/
btr_pcur_t* cursor); /*!< in: persistent cursor */
/**************************************************************//**
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
that is, the cursor becomes detached. If there have been modifications
@ -387,10 +371,6 @@ page_cur_t*
btr_pcur_get_page_cur(
/*==================*/
const btr_pcur_t* cursor); /*!< in: persistent cursor */
#else /* UNIV_DEBUG */
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
#endif /* UNIV_DEBUG */
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
@ -398,7 +378,7 @@ UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
btr_pcur_t* cursor);/*!< in: persistent cursor */
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the buffer block of a persistent cursor.
@return pointer to the block */
@ -406,7 +386,7 @@ UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
btr_pcur_t* cursor);/*!< in: persistent cursor */
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/*********************************************************//**
Returns the record of a persistent cursor.
@return pointer to the record */
@ -414,7 +394,14 @@ UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
btr_pcur_t* cursor);/*!< in: persistent cursor */
const btr_pcur_t* cursor);/*!< in: persistent cursor */
#else /* UNIV_DEBUG */
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
# define btr_pcur_get_page(cursor) ((cursor)->btr_cur.page_cur.block->frame)
# define btr_pcur_get_block(cursor) ((cursor)->btr_cur.page_cur.block)
# define btr_pcur_get_rec(cursor) ((cursor)->btr_cur.page_cur.rec)
#endif /* UNIV_DEBUG */
/*********************************************************//**
Checks if the persistent cursor is on a user record. */
UNIV_INLINE
@ -517,9 +504,6 @@ struct btr_pcur_struct{
/* NOTE that the following fields may possess dynamically allocated
memory which should be freed if not needed anymore! */
mtr_t* mtr; /*!< NULL, or this field may contain
a mini-transaction which holds the
latch on the cursor page */
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
buffer for old_rec */
ulint buf_size; /*!< old_rec_buf size if old_rec_buf

View File

@ -42,34 +42,6 @@ btr_pcur_get_rel_pos(
return(cursor->rel_pos);
}
/*********************************************************//**
Sets the mtr field for a pcur. */
UNIV_INLINE
void
btr_pcur_set_mtr(
/*=============*/
btr_pcur_t* cursor, /*!< in: persistent cursor */
mtr_t* mtr) /*!< in, own: mtr */
{
ut_ad(cursor);
cursor->mtr = mtr;
}
/*********************************************************//**
Gets the mtr field for a pcur.
@return mtr */
UNIV_INLINE
mtr_t*
btr_pcur_get_mtr(
/*=============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor);
return(cursor->mtr);
}
#ifdef UNIV_DEBUG
/*********************************************************//**
Returns the btr cursor component of a persistent cursor.
@ -95,7 +67,7 @@ btr_pcur_get_page_cur(
{
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
}
#endif /* UNIV_DEBUG */
/*********************************************************//**
Returns the page of a persistent cursor.
@return pointer to the page */
@ -103,7 +75,7 @@ UNIV_INLINE
page_t*
btr_pcur_get_page(
/*==============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@ -117,7 +89,7 @@ UNIV_INLINE
buf_block_t*
btr_pcur_get_block(
/*===============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@ -131,13 +103,14 @@ UNIV_INLINE
rec_t*
btr_pcur_get_rec(
/*=============*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor)));
}
#endif /* UNIV_DEBUG */
/**************************************************************//**
Gets the up_match value for a pcur after a search.
@ -147,9 +120,9 @@ UNIV_INLINE
ulint
btr_pcur_get_up_match(
/*==================*/
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
btr_cur_t* btr_cursor;
const btr_cur_t* btr_cursor;
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
@ -169,9 +142,9 @@ UNIV_INLINE
ulint
btr_pcur_get_low_match(
/*===================*/
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
const btr_pcur_t* cursor) /*!< in: persistent cursor */
{
btr_cur_t* btr_cursor;
const btr_cur_t* btr_cursor;
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));

View File

@ -41,6 +41,8 @@ Created 11/5/1995 Heikki Tuuri
/* @{ */
#define BUF_GET 10 /*!< get always */
#define BUF_GET_IF_IN_POOL 11 /*!< get if in pool */
#define BUF_PEEK_IF_IN_POOL 12 /*!< get if in pool, do not make
the block young in the LRU list */
#define BUF_GET_NO_LATCH 14 /*!< get and bufferfix, but
set no latch; we have
separated this case, because
@ -396,7 +398,7 @@ buf_page_get_gen(
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
buf_block_t* guess, /*!< in: guessed block or NULL */
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
BUF_GET_NO_LATCH or
BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH or
BUF_GET_IF_IN_POOL_OR_WATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */

View File

@ -70,10 +70,10 @@ UNIV_INTERN
ulint
buf_read_ahead_linear(
/*==================*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset);/*!< in: page number of a page; NOTE: the current thread
must want access to this page (see NOTE 3 above) */
ulint space, /*!< in: space id */
ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
ulint offset, /*!< in: page number; see NOTE 3 above */
ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf routine */
/********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in
order to contract the insert buffer tree. Technically, this function is like

View File

@ -173,6 +173,15 @@ innobase_strcasecmp(
const char* a, /*!< in: first string to compare */
const char* b); /*!< in: second string to compare */
/******************************************************************//**
Strip dir name from a full path name and return only its file name.
@return file name or "null" if no file name */
UNIV_INTERN
const char*
innobase_basename(
/*==============*/
const char* path_name); /*!< in: full path name */
/******************************************************************//**
Returns true if the thread is executing a SELECT statement.
@return true if thd is executing SELECT */

View File

@ -104,6 +104,22 @@ UNIV_INTERN
void
ibuf_update_max_tablespace_id(void);
/*===============================*/
/***************************************************************//**
Starts an insert buffer mini-transaction. */
UNIV_INLINE
void
ibuf_mtr_start(
/*===========*/
mtr_t* mtr) /*!< out: mini-transaction */
__attribute__((nonnull));
/***************************************************************//**
Commits an insert buffer mini-transaction. */
UNIV_INLINE
void
ibuf_mtr_commit(
/*============*/
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/*********************************************************************//**
Initializes an ibuf bitmap page. */
UNIV_INTERN
@ -224,10 +240,12 @@ routine.
For instance, a read-ahead of non-ibuf pages is forbidden by threads
that are executing an insert buffer routine.
@return TRUE if inside an insert buffer routine */
UNIV_INTERN
UNIV_INLINE
ibool
ibuf_inside(void);
/*=============*/
ibuf_inside(
/*========*/
const mtr_t* mtr) /*!< in: mini-transaction */
__attribute__((nonnull, pure));
/***********************************************************************//**
Checks if a page address is an ibuf bitmap page (level 3 page) address.
@return TRUE if a bitmap page */

View File

@ -37,6 +37,30 @@ buffer inserts to this page. If there is this much of free space, the
corresponding bits are set in the ibuf bitmap. */
#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32
/***************************************************************//**
Starts an insert buffer mini-transaction. */
UNIV_INLINE
void
ibuf_mtr_start(
/*===========*/
mtr_t* mtr) /*!< out: mini-transaction */
{
mtr_start(mtr);
mtr->inside_ibuf = TRUE;
}
/***************************************************************//**
Commits an insert buffer mini-transaction. */
UNIV_INLINE
void
ibuf_mtr_commit(
/*============*/
mtr_t* mtr) /*!< in/out: mini-transaction */
{
ut_ad(mtr->inside_ibuf);
ut_d(mtr->inside_ibuf = FALSE);
mtr_commit(mtr);
}
/** Insert buffer struct */
struct ibuf_struct{
ulint size; /*!< current size of the ibuf index
@ -120,6 +144,22 @@ ibuf_should_try(
return(FALSE);
}
/******************************************************************//**
Returns TRUE if the current OS thread is performing an insert buffer
routine.
For instance, a read-ahead of non-ibuf pages is forbidden by threads
that are executing an insert buffer routine.
@return TRUE if inside an insert buffer routine */
UNIV_INLINE
ibool
ibuf_inside(
/*========*/
const mtr_t* mtr) /*!< in: mini-transaction */
{
return(mtr->inside_ibuf);
}
/***********************************************************************//**
Checks if a page address is an ibuf bitmap page address.
@return TRUE if a bitmap page */

View File

@ -190,21 +190,21 @@ functions). The page number parameter was originally written as 0. @{ */
/* @} */
/***************************************************************//**
Starts a mini-transaction and creates a mini-transaction handle
and buffer in the memory buffer given by the caller.
@return mtr buffer which also acts as the mtr handle */
Starts a mini-transaction. */
UNIV_INLINE
mtr_t*
void
mtr_start(
/*======*/
mtr_t* mtr); /*!< in: memory buffer for the mtr buffer */
mtr_t* mtr) /*!< out: mini-transaction */
__attribute__((nonnull));
/***************************************************************//**
Commits a mini-transaction. */
UNIV_INTERN
void
mtr_commit(
/*=======*/
mtr_t* mtr); /*!< in: mini-transaction */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/**********************************************************//**
Sets and returns a savepoint in mtr.
@return savepoint */
@ -378,6 +378,8 @@ struct mtr_struct{
#endif
dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */
ibool inside_ibuf;
/*!< TRUE if inside ibuf changes */
ibool modifications;
/* TRUE if the mtr made modifications to
buffer pool pages */

View File

@ -30,26 +30,23 @@ Created 11/26/1995 Heikki Tuuri
#include "mach0data.h"
/***************************************************************//**
Starts a mini-transaction and creates a mini-transaction handle
and a buffer in the memory buffer given by the caller.
@return mtr buffer which also acts as the mtr handle */
Starts a mini-transaction. */
UNIV_INLINE
mtr_t*
void
mtr_start(
/*======*/
mtr_t* mtr) /*!< in: memory buffer for the mtr buffer */
mtr_t* mtr) /*!< out: mini-transaction */
{
dyn_array_create(&(mtr->memo));
dyn_array_create(&(mtr->log));
mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE;
mtr->inside_ibuf = FALSE;
mtr->n_log_recs = 0;
ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N);
return(mtr);
}
/***************************************************//**

View File

@ -952,7 +952,7 @@ UNIV_INTERN
ibool
page_rec_validate(
/*==============*/
rec_t* rec, /*!< in: physical record */
const rec_t* rec, /*!< in: physical record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
/***************************************************************//**
Checks that the first directory slot points to the infimum record and
@ -972,7 +972,7 @@ UNIV_INTERN
ibool
page_simple_validate_old(
/*=====================*/
page_t* page); /*!< in: old-style index page */
const page_t* page); /*!< in: index page in ROW_FORMAT=REDUNDANT */
/***************************************************************//**
This function checks the consistency of an index page when we do not
know the index. This is also resilient so that this should never crash
@ -982,7 +982,7 @@ UNIV_INTERN
ibool
page_simple_validate_new(
/*=====================*/
page_t* block); /*!< in: new-style index page */
const page_t* page); /*!< in: index page in ROW_FORMAT!=REDUNDANT */
/***************************************************************//**
This function checks the consistency of an index page.
@return TRUE if ok */
@ -990,7 +990,7 @@ UNIV_INTERN
ibool
page_validate(
/*==========*/
page_t* page, /*!< in: index page */
const page_t* page, /*!< in: index page */
dict_index_t* index); /*!< in: data dictionary index containing
the page record type definition */
/***************************************************************//**

View File

@ -600,6 +600,7 @@ ulint
rec_offs_size(
/*==========*/
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#ifdef UNIV_DEBUG
/**********************************************************//**
Returns a pointer to the start of the record.
@return pointer to start */
@ -607,7 +608,7 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
/**********************************************************//**
Returns a pointer to the end of the record.
@ -616,8 +617,12 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#else /* UNIV_DEBUG */
# define rec_get_start(rec, offsets) ((rec) - rec_offs_extra_size(offsets))
# define rec_get_end(rec, offsets) ((rec) + rec_offs_data_size(offsets))
#endif /* UNIV_DEBUG */
/***************************************************************//**
Copies a physical record to a buffer.
@return pointer to the origin of the copy */

View File

@ -1462,6 +1462,7 @@ rec_offs_size(
return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
}
#ifdef UNIV_DEBUG
/**********************************************************//**
Returns a pointer to the end of the record.
@return pointer to end */
@ -1469,11 +1470,11 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(rec, NULL, offsets));
return(rec + rec_offs_data_size(offsets));
return((rec_t*) rec + rec_offs_data_size(offsets));
}
/**********************************************************//**
@ -1483,12 +1484,13 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
rec_t* rec, /*!< in: pointer to record */
const rec_t* rec, /*!< in: pointer to record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(rec, NULL, offsets));
return(rec - rec_offs_extra_size(offsets));
return((rec_t*) rec - rec_offs_extra_size(offsets));
}
#endif /* UNIV_DEBUG */
/***************************************************************//**
Copies a physical record to a buffer.

View File

@ -442,16 +442,8 @@ typedef enum srv_stats_method_name_enum srv_stats_method_name_t;
#ifndef UNIV_HOTBACKUP
/** Types of threads existing in the system. */
enum srv_thread_type {
SRV_COM = 1, /**< threads serving communication and queries */
SRV_CONSOLE, /**< thread serving console */
SRV_WORKER, /**< threads serving parallelized queries and
SRV_WORKER = 0, /**< threads serving parallelized queries and
queries released from lock wait */
#if 0
/* Utility threads */
SRV_BUFFER, /**< thread flushing dirty buffer blocks */
SRV_RECOVERY, /**< threads finishing a recovery */
SRV_INSERT, /**< thread flushing the insert buffer to disk */
#endif
SRV_MASTER /**< the master thread, (whose type number must
be biggest) */
};
@ -490,13 +482,6 @@ ulint
srv_get_n_threads(void);
/*===================*/
/*********************************************************************//**
Returns the calling thread type.
@return SRV_COM, ... */
enum srv_thread_type
srv_get_thread_type(void);
/*=====================*/
/*********************************************************************//**
Check whether thread type has reserved a slot.
@return slot number or UNDEFINED if not found*/
UNIV_INTERN

View File

@ -115,8 +115,11 @@ Prints warnings of long semaphore waits to stderr.
@return TRUE if fatal semaphore wait threshold was exceeded */
UNIV_INTERN
ibool
sync_array_print_long_waits(void);
/*=============================*/
sync_array_print_long_waits(
/*========================*/
os_thread_id_t* waiter, /*!< out: longest waiting thread */
const void** sema) /*!< out: longest-waited-for semaphore */
__attribute__((nonnull));
/********************************************************************//**
Validates the integrity of the wait array. Checks
that the number of reserved cells equals the count variable. */

View File

@ -110,7 +110,6 @@ extern mysql_pfs_key_t syn_arr_mutex_key;
extern mysql_pfs_key_t sync_thread_mutex_key;
# endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t trx_doublewrite_mutex_key;
extern mysql_pfs_key_t thr_local_mutex_key;
extern mysql_pfs_key_t trx_undo_mutex_key;
#endif /* UNIV_PFS_MUTEX */

View File

@ -1,90 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. 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
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/thr0loc.h
The thread local storage
Created 10/5/1995 Heikki Tuuri
*******************************************************/
/* This module implements storage private to each thread,
a capability useful in some situations like storing the
OS handle to the current thread, or its priority. */
#ifndef thr0loc_h
#define thr0loc_h
#include "univ.i"
#include "os0thread.h"
/****************************************************************//**
Initializes the thread local storage module. */
UNIV_INTERN
void
thr_local_init(void);
/*================*/
/****************************************************************//**
Close the thread local storage module. */
UNIV_INTERN
void
thr_local_close(void);
/*=================*/
/*******************************************************************//**
Creates a local storage struct for the calling new thread. */
UNIV_INTERN
void
thr_local_create(void);
/*==================*/
/*******************************************************************//**
Frees the local storage struct for the specified thread. */
UNIV_INTERN
void
thr_local_free(
/*===========*/
os_thread_id_t id); /*!< in: thread id */
/*******************************************************************//**
Gets the slot number in the thread table of a thread.
@return slot number */
UNIV_INTERN
ulint
thr_local_get_slot_no(
/*==================*/
os_thread_id_t id); /*!< in: thread id of the thread */
/*******************************************************************//**
Sets in the local storage the slot number in the thread table of a thread. */
UNIV_INTERN
void
thr_local_set_slot_no(
/*==================*/
os_thread_id_t id, /*!< in: thread id of the thread */
ulint slot_no);/*!< in: slot number */
/*******************************************************************//**
Returns pointer to the 'in_ibuf' field within the current thread local
storage.
@return pointer to the in_ibuf field */
UNIV_INTERN
ibool*
thr_local_get_in_ibuf_field(void);
/*=============================*/
#ifndef UNIV_NONINL
#include "thr0loc.ic"
#endif
#endif

View File

@ -1,24 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. 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
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/thr0loc.ic
Thread local storage
Created 10/4/1995 Heikki Tuuri
*******************************************************/

View File

@ -24,6 +24,8 @@ but is included in mem0mem.* !
Created 6/9/1994 Heikki Tuuri
*************************************************************************/
#include "ha_prototypes.h"
#ifdef UNIV_MEM_DEBUG
# ifndef UNIV_HOTBACKUP
/* The mutex which protects in the debug version the hash table
@ -400,7 +402,7 @@ mem_hash_remove(
fprintf(stderr,
"Memory heap or buffer freed in %s line %lu"
" did not exist.\n",
file_name, (ulong) line);
innobase_basename(file_name), (ulong) line);
ut_error;
}
@ -419,8 +421,9 @@ mem_hash_remove(
"in %s line %lu and tried to free in %s line %lu.\n"
"Hex dump of 400 bytes around memory heap"
" first block start:\n",
node->nth_heap, node->file_name, (ulong) node->line,
file_name, (ulong) line);
node->nth_heap,
innobase_basename(node->file_name), (ulong) node->line,
innobase_basename(file_name), (ulong) line);
ut_print_buf(stderr, (byte*)node->heap - 200, 400);
fputs("\nDump of the mem heap:\n", stderr);
mem_heap_validate_or_print(node->heap, NULL, TRUE, &error,
@ -763,7 +766,8 @@ mem_validate_no_assert(void)
"Inconsistency in memory heap"
" or buffer created\n"
"in %s line %lu.\n",
node->file_name, node->line);
innobase_basename(node->file_name),
node->line);
mutex_exit(&mem_hash_mutex);
@ -989,7 +993,8 @@ mem_print_info_low(
fprintf(outfile,
"%lu: file %s line %lu of size %lu phys.size %lu"
" with %lu blocks, type %lu\n",
node->nth_heap, node->file_name, node->line,
node->nth_heap,
innobase_basename(node->file_name), node->line,
allocated_mem, ph_size, n_blocks,
(node->heap)->type);
next_heap:

View File

@ -251,6 +251,7 @@ mtr_commit(
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(!mtr->inside_ibuf);
ut_d(mtr->state = MTR_COMMITTING);
#ifndef UNIV_HOTBACKUP

View File

@ -166,11 +166,11 @@ static
ibool
page_dir_slot_check(
/*================*/
page_dir_slot_t* slot) /*!< in: slot */
const page_dir_slot_t* slot) /*!< in: slot */
{
page_t* page;
ulint n_slots;
ulint n_owned;
const page_t* page;
ulint n_slots;
ulint n_owned;
ut_a(slot);
@ -1803,12 +1803,12 @@ UNIV_INTERN
ibool
page_rec_validate(
/*==============*/
rec_t* rec, /*!< in: physical record */
const rec_t* rec, /*!< in: physical record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{
ulint n_owned;
ulint heap_no;
page_t* page;
ulint n_owned;
ulint heap_no;
const page_t* page;
page = page_align(rec);
ut_a(!page_is_comp(page) == !rec_offs_comp(offsets));
@ -1889,16 +1889,16 @@ UNIV_INTERN
ibool
page_simple_validate_old(
/*=====================*/
page_t* page) /*!< in: old-style index page */
const page_t* page) /*!< in: index page in ROW_FORMAT=REDUNDANT */
{
page_dir_slot_t* slot;
ulint slot_no;
ulint n_slots;
rec_t* rec;
byte* rec_heap_top;
ulint count;
ulint own_count;
ibool ret = FALSE;
const page_dir_slot_t* slot;
ulint slot_no;
ulint n_slots;
const rec_t* rec;
const byte* rec_heap_top;
ulint count;
ulint own_count;
ibool ret = FALSE;
ut_a(!page_is_comp(page));
@ -2011,7 +2011,7 @@ page_simple_validate_old(
goto func_exit;
}
rec = page_rec_get_next(rec);
rec = page_rec_get_next_const(rec);
own_count++;
}
@ -2072,7 +2072,7 @@ page_simple_validate_old(
goto func_exit;
}
rec = page_rec_get_next(rec);
rec = page_rec_get_next_const(rec);
}
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
@ -2099,16 +2099,16 @@ UNIV_INTERN
ibool
page_simple_validate_new(
/*=====================*/
page_t* page) /*!< in: new-style index page */
const page_t* page) /*!< in: index page in ROW_FORMAT!=REDUNDANT */
{
page_dir_slot_t* slot;
ulint slot_no;
ulint n_slots;
rec_t* rec;
byte* rec_heap_top;
ulint count;
ulint own_count;
ibool ret = FALSE;
const page_dir_slot_t* slot;
ulint slot_no;
ulint n_slots;
const rec_t* rec;
const byte* rec_heap_top;
ulint count;
ulint own_count;
ibool ret = FALSE;
ut_a(page_is_comp(page));
@ -2221,7 +2221,7 @@ page_simple_validate_new(
goto func_exit;
}
rec = page_rec_get_next(rec);
rec = page_rec_get_next_const(rec);
own_count++;
}
@ -2283,7 +2283,7 @@ page_simple_validate_new(
goto func_exit;
}
rec = page_rec_get_next(rec);
rec = page_rec_get_next_const(rec);
}
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
@ -2308,26 +2308,26 @@ UNIV_INTERN
ibool
page_validate(
/*==========*/
page_t* page, /*!< in: index page */
const page_t* page, /*!< in: index page */
dict_index_t* index) /*!< in: data dictionary index containing
the page record type definition */
{
page_dir_slot_t*slot;
mem_heap_t* heap;
byte* buf;
ulint count;
ulint own_count;
ulint rec_own_count;
ulint slot_no;
ulint data_size;
rec_t* rec;
rec_t* old_rec = NULL;
ulint offs;
ulint n_slots;
ibool ret = FALSE;
ulint i;
ulint* offsets = NULL;
ulint* old_offsets = NULL;
const page_dir_slot_t* slot;
mem_heap_t* heap;
byte* buf;
ulint count;
ulint own_count;
ulint rec_own_count;
ulint slot_no;
ulint data_size;
const rec_t* rec;
const rec_t* old_rec = NULL;
ulint offs;
ulint n_slots;
ibool ret = FALSE;
ulint i;
ulint* offsets = NULL;
ulint* old_offsets = NULL;
if (UNIV_UNLIKELY((ibool) !!page_is_comp(page)
!= dict_table_is_comp(index->table))) {
@ -2482,7 +2482,7 @@ page_validate(
count++;
own_count++;
old_rec = rec;
rec = page_rec_get_next(rec);
rec = page_rec_get_next_const(rec);
/* set old_offsets to offsets; recycle offsets */
{
@ -2556,7 +2556,7 @@ n_owned_zero:
buf[offs + i] = 1;
}
rec = page_rec_get_next(rec);
rec = page_rec_get_next_const(rec);
}
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {

View File

@ -653,13 +653,13 @@ page_zip_dir_encode(
Allocate memory for zlib. */
static
void*
page_zip_malloc(
page_zip_zalloc(
/*============*/
void* opaque, /*!< in/out: memory heap */
uInt items, /*!< in: number of items to allocate */
uInt size) /*!< in: size of an item in bytes */
{
return(mem_heap_alloc(opaque, items * size));
return(mem_heap_zalloc(opaque, items * size));
}
/**********************************************************************//**
@ -684,7 +684,7 @@ page_zip_set_alloc(
{
z_stream* strm = stream;
strm->zalloc = page_zip_malloc;
strm->zalloc = page_zip_zalloc;
strm->zfree = page_zip_free;
strm->opaque = heap;
}
@ -2912,19 +2912,18 @@ zlib_error:
page_zip_set_alloc(&d_stream, heap);
if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
!= Z_OK)) {
ut_error;
}
d_stream.next_in = page_zip->data + PAGE_DATA;
/* Subtract the space reserved for
the page header and the end marker of the modification log. */
d_stream.avail_in = page_zip_get_size(page_zip) - (PAGE_DATA + 1);
d_stream.next_out = page + PAGE_ZIP_START;
d_stream.avail_out = UNIV_PAGE_SIZE - PAGE_ZIP_START;
if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
!= Z_OK)) {
ut_error;
}
/* Decode the zlib header and the index information. */
if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) {

View File

@ -66,7 +66,6 @@ Created 10/8/1995 Heikki Tuuri
#include "mem0mem.h"
#include "mem0pool.h"
#include "sync0sync.h"
#include "thr0loc.h"
#include "que0que.h"
#include "log0recv.h"
#include "pars0pars.h"
@ -690,7 +689,7 @@ Unix.*/
struct srv_slot_struct{
os_thread_id_t id; /*!< thread id */
os_thread_t handle; /*!< thread handle */
unsigned type:3; /*!< thread type: user, utility etc. */
unsigned type:1; /*!< thread type: user, utility etc. */
unsigned in_use:1; /*!< TRUE if this slot is in use */
unsigned suspended:1; /*!< TRUE if the thread is waiting
for the event of this slot */
@ -797,6 +796,7 @@ srv_table_get_nth_slot(
/*===================*/
ulint index) /*!< in: index of the slot */
{
ut_ad(mutex_own(&kernel_mutex));
ut_a(index < OS_THREAD_MAX_N);
return(srv_sys->threads + index);
@ -815,7 +815,7 @@ srv_get_n_threads(void)
mutex_enter(&kernel_mutex);
for (i = SRV_COM; i < SRV_MASTER + 1; i++) {
for (i = 0; i < SRV_MASTER + 1; i++) {
n_threads += srv_n_threads[i];
}
@ -825,13 +825,46 @@ srv_get_n_threads(void)
return(n_threads);
}
#ifdef UNIV_DEBUG
/*********************************************************************//**
Reserves a slot in the thread table for the current thread. Also creates the
thread local storage struct for the current thread. NOTE! The server mutex
has to be reserved by the caller!
@return reserved slot index */
Validates the type of a thread table slot.
@return TRUE if ok */
static
ulint
ibool
srv_thread_type_validate(
/*=====================*/
enum srv_thread_type type) /*!< in: thread type */
{
switch (type) {
case SRV_WORKER:
case SRV_MASTER:
return(TRUE);
}
ut_error;
return(FALSE);
}
#endif /* UNIV_DEBUG */
/*********************************************************************//**
Gets the type of a thread table slot.
@return thread type */
static
enum srv_thread_type
srv_slot_get_type(
/*==============*/
const srv_slot_t* slot) /*!< in: thread slot */
{
enum srv_thread_type type = (enum srv_thread_type) slot->type;
ut_ad(srv_thread_type_validate(type));
return(type);
}
/*********************************************************************//**
Reserves a slot in the thread table for the current thread.
NOTE! The server mutex has to be reserved by the caller!
@return reserved slot */
static
srv_slot_t*
srv_table_reserve_slot(
/*===================*/
enum srv_thread_type type) /*!< in: type of the thread */
@ -839,8 +872,7 @@ srv_table_reserve_slot(
srv_slot_t* slot;
ulint i;
ut_a(type > 0);
ut_a(type <= SRV_MASTER);
ut_ad(srv_thread_type_validate(type));
ut_ad(mutex_own(&kernel_mutex));
i = 0;
@ -851,53 +883,40 @@ srv_table_reserve_slot(
slot = srv_table_get_nth_slot(i);
}
ut_a(slot->in_use == FALSE);
slot->in_use = TRUE;
slot->suspended = FALSE;
slot->type = type;
ut_ad(srv_slot_get_type(slot) == type);
slot->id = os_thread_get_curr_id();
slot->handle = os_thread_get_curr();
thr_local_create();
thr_local_set_slot_no(os_thread_get_curr_id(), i);
return(i);
return(slot);
}
/*********************************************************************//**
Suspends the calling thread to wait for the event in its thread slot.
NOTE! The server mutex has to be reserved by the caller!
@return event for the calling thread to wait */
NOTE! The server mutex has to be reserved by the caller! */
static
os_event_t
srv_suspend_thread(void)
/*====================*/
void
srv_suspend_thread(
/*===============*/
srv_slot_t* slot) /*!< in/out: thread slot */
{
srv_slot_t* slot;
os_event_t event;
ulint slot_no;
enum srv_thread_type type;
ut_ad(mutex_own(&kernel_mutex));
slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
ut_ad(slot->in_use);
ut_ad(!slot->suspended);
ut_ad(slot->id == os_thread_get_curr_id());
if (srv_print_thread_releases) {
fprintf(stderr,
"Suspending thread %lu to slot %lu\n",
(ulong) os_thread_get_curr_id(), (ulong) slot_no);
(ulong) os_thread_get_curr_id(),
(ulong) (slot - srv_sys->threads));
}
slot = srv_table_get_nth_slot(slot_no);
type = slot->type;
ut_ad(type >= SRV_WORKER);
ut_ad(type <= SRV_MASTER);
event = slot->event;
type = srv_slot_get_type(slot);
slot->suspended = TRUE;
@ -905,9 +924,7 @@ srv_suspend_thread(void)
srv_n_threads_active[type]--;
os_event_reset(event);
return(event);
os_event_reset(slot->event);
}
/*********************************************************************//**
@ -926,8 +943,7 @@ srv_release_threads(
ulint i;
ulint count = 0;
ut_ad(type >= SRV_WORKER);
ut_ad(type <= SRV_MASTER);
ut_ad(srv_thread_type_validate(type));
ut_ad(n > 0);
ut_ad(mutex_own(&kernel_mutex));
@ -935,7 +951,8 @@ srv_release_threads(
slot = srv_table_get_nth_slot(i);
if (slot->in_use && slot->type == type && slot->suspended) {
if (slot->in_use && slot->suspended
&& srv_slot_get_type(slot) == type) {
slot->suspended = FALSE;
@ -962,34 +979,6 @@ srv_release_threads(
return(count);
}
/*********************************************************************//**
Returns the calling thread type.
@return SRV_COM, ... */
UNIV_INTERN
enum srv_thread_type
srv_get_thread_type(void)
/*=====================*/
{
ulint slot_no;
srv_slot_t* slot;
enum srv_thread_type type;
mutex_enter(&kernel_mutex);
slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
slot = srv_table_get_nth_slot(slot_no);
type = slot->type;
ut_ad(type >= SRV_WORKER);
ut_ad(type <= SRV_MASTER);
mutex_exit(&kernel_mutex);
return(type);
}
/*********************************************************************//**
Check whether thread type has reserved a slot. Return the first slot that
is found. This works because we currently have only 1 thread of each type.
@ -1003,6 +992,7 @@ srv_thread_has_reserved_slot(
ulint i;
ulint slot_no = ULINT_UNDEFINED;
ut_ad(srv_thread_type_validate(type));
mutex_enter(&kernel_mutex);
for (i = 0; i < OS_THREAD_MAX_N; i++) {
@ -1040,22 +1030,18 @@ srv_init(void)
mutex_create(srv_innodb_monitor_mutex_key,
&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
srv_sys->threads = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
slot = srv_table_get_nth_slot(i);
slot->in_use = FALSE;
slot->type=0; /* Avoid purify errors */
slot = srv_sys->threads + i;
slot->event = os_event_create(NULL);
ut_a(slot->event);
}
srv_mysql_table = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
srv_mysql_table = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
slot = srv_mysql_table + i;
slot->in_use = FALSE;
slot->type = 0;
slot->event = os_event_create(NULL);
ut_a(slot->event);
}
@ -1142,7 +1128,6 @@ srv_general_init(void)
os_sync_init();
sync_init();
mem_init(srv_mem_pool_size);
thr_local_init();
}
/*======================= InnoDB Server FIFO queue =======================*/
@ -1501,7 +1486,7 @@ srv_table_reserve_slot_for_mysql(void)
while (slot->in_use) {
i++;
if (i >= OS_THREAD_MAX_N) {
if (UNIV_UNLIKELY(i >= OS_THREAD_MAX_N)) {
ut_print_timestamp(stderr);
@ -2382,6 +2367,12 @@ srv_error_monitor_thread(
ib_uint64_t old_lsn;
ib_uint64_t new_lsn;
ib_int64_t sig_count;
/* longest waiting thread for a semaphore */
os_thread_id_t waiter = os_thread_get_curr_id();
os_thread_id_t old_waiter = waiter;
/* the semaphore that is being waited for */
const void* sema = NULL;
const void* old_sema = NULL;
old_lsn = srv_start_lsn;
@ -2435,7 +2426,8 @@ loop:
sync_arr_wake_threads_if_sema_free();
if (sync_array_print_long_waits()) {
if (sync_array_print_long_waits(&waiter, &sema)
&& sema == old_sema && os_thread_eq(waiter, old_waiter)) {
fatal_cnt++;
if (fatal_cnt > 10) {
@ -2450,6 +2442,8 @@ loop:
}
} else {
fatal_cnt = 0;
old_waiter = waiter;
old_sema = sema;
}
/* Flush stderr so that a database user gets the output
@ -2489,7 +2483,7 @@ srv_is_any_background_thread_active(void)
mutex_enter(&kernel_mutex);
for (i = SRV_COM; i <= SRV_MASTER; ++i) {
for (i = 0; i <= SRV_MASTER; ++i) {
if (srv_n_threads_active[i] != 0) {
ret = TRUE;
break;
@ -2643,7 +2637,7 @@ srv_master_thread(
os_thread_create */
{
buf_pool_stat_t buf_stat;
os_event_t event;
srv_slot_t* slot;
ulint old_activity_count;
ulint n_pages_purged = 0;
ulint n_bytes_merged;
@ -2671,7 +2665,7 @@ srv_master_thread(
mutex_enter(&kernel_mutex);
srv_table_reserve_slot(SRV_MASTER);
slot = srv_table_reserve_slot(SRV_MASTER);
srv_n_threads_active[SRV_MASTER]++;
@ -3060,7 +3054,7 @@ suspend_thread:
goto loop;
}
event = srv_suspend_thread();
srv_suspend_thread(slot);
mutex_exit(&kernel_mutex);
@ -3070,7 +3064,7 @@ suspend_thread:
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";
os_event_wait(event);
os_event_wait(slot->event);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
/* This is only extra safety, the thread should exit
@ -3084,8 +3078,6 @@ suspend_thread:
main thread goes back to loop. */
goto loop;
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
}
/*********************************************************************//**
@ -3100,7 +3092,6 @@ srv_purge_thread(
{
srv_slot_t* slot;
ulint retries = 0;
ulint slot_no = ULINT_UNDEFINED;
ulint n_total_purged = ULINT_UNDEFINED;
ut_a(srv_n_purge_threads == 1);
@ -3116,9 +3107,7 @@ srv_purge_thread(
mutex_enter(&kernel_mutex);
slot_no = srv_table_reserve_slot(SRV_WORKER);
slot = srv_table_get_nth_slot(slot_no);
slot = srv_table_reserve_slot(SRV_WORKER);
++srv_n_threads_active[SRV_WORKER];
@ -3137,15 +3126,13 @@ srv_purge_thread(
|| (n_total_purged == 0
&& retries >= TRX_SYS_N_RSEGS)) {
os_event_t event;
mutex_enter(&kernel_mutex);
event = srv_suspend_thread();
srv_suspend_thread(slot);
mutex_exit(&kernel_mutex);
os_event_wait(event);
os_event_wait(slot->event);
retries = 0;
}
@ -3179,16 +3166,11 @@ srv_purge_thread(
mutex_enter(&kernel_mutex);
ut_ad(srv_table_get_nth_slot(slot_no) == slot);
/* Decrement the active count. */
srv_suspend_thread();
srv_suspend_thread(slot);
slot->in_use = FALSE;
/* Free the thread local memory. */
thr_local_free(os_thread_get_curr_id());
mutex_exit(&kernel_mutex);
#ifdef UNIV_DEBUG_THREAD_CREATION

View File

@ -85,7 +85,6 @@ Created 2/16/1996 Heikki Tuuri
# include "row0row.h"
# include "row0mysql.h"
# include "btr0pcur.h"
# include "thr0loc.h"
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
# include "zlib.h" /* for ZLIB_VERSION */
@ -2210,7 +2209,6 @@ innobase_shutdown_for_mysql(void)
ibuf_close();
log_shutdown();
lock_sys_close();
thr_local_close();
trx_sys_file_format_close();
trx_sys_close();

View File

@ -40,6 +40,7 @@ Created 9/5/1995 Heikki Tuuri
#include "os0sync.h"
#include "os0file.h"
#include "srv0srv.h"
#include "ha_prototypes.h"
/*
WAIT ARRAY
@ -478,8 +479,8 @@ sync_array_cell_print(
fprintf(file,
"--Thread %lu has waited at %s line %lu"
" for %.2f seconds the semaphore:\n",
(ulong) os_thread_pf(cell->thread), cell->file,
(ulong) cell->line,
(ulong) os_thread_pf(cell->thread),
innobase_basename(cell->file), (ulong) cell->line,
difftime(time(NULL), cell->reservation_time));
if (type == SYNC_MUTEX) {
@ -493,7 +494,8 @@ sync_array_cell_print(
"Last time reserved in file %s line %lu, "
#endif /* UNIV_SYNC_DEBUG */
"waiters flag %lu\n",
(void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
(void*) mutex, innobase_basename(mutex->cfile_name),
(ulong) mutex->cline,
(ulong) mutex->lock_word,
#ifdef UNIV_SYNC_DEBUG
mutex->file_name, (ulong) mutex->line,
@ -512,7 +514,7 @@ sync_array_cell_print(
fprintf(file,
" RW-latch at %p created in file %s line %lu\n",
(void*) rwlock, rwlock->cfile_name,
(void*) rwlock, innobase_basename(rwlock->cfile_name),
(ulong) rwlock->cline);
writer = rw_lock_get_writer(rwlock);
if (writer != RW_LOCK_NOT_LOCKED) {
@ -533,7 +535,7 @@ sync_array_cell_print(
(ulong) rw_lock_get_reader_count(rwlock),
(ulong) rwlock->waiters,
rwlock->lock_word,
rwlock->last_s_file_name,
innobase_basename(rwlock->last_s_file_name),
(ulong) rwlock->last_s_line,
rwlock->last_x_file_name,
(ulong) rwlock->last_x_line);
@ -913,8 +915,10 @@ Prints warnings of long semaphore waits to stderr.
@return TRUE if fatal semaphore wait threshold was exceeded */
UNIV_INTERN
ibool
sync_array_print_long_waits(void)
/*=============================*/
sync_array_print_long_waits(
/*========================*/
os_thread_id_t* waiter, /*!< out: longest waiting thread */
const void** sema) /*!< out: longest-waited-for semaphore */
{
sync_cell_t* cell;
ibool old_val;
@ -922,6 +926,7 @@ sync_array_print_long_waits(void)
ulint i;
ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
ibool fatal = FALSE;
double longest_diff = 0;
#ifdef UNIV_DEBUG_VALGRIND
/* Increase the timeouts if running under valgrind because it executes
@ -937,22 +942,36 @@ sync_array_print_long_waits(void)
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
double diff;
void* wait_object;
cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
if (cell->wait_object != NULL && cell->waiting
&& difftime(time(NULL), cell->reservation_time)
> SYNC_ARRAY_TIMEOUT) {
wait_object = cell->wait_object;
if (wait_object == NULL || !cell->waiting) {
continue;
}
diff = difftime(time(NULL), cell->reservation_time);
if (diff > SYNC_ARRAY_TIMEOUT) {
fputs("InnoDB: Warning: a long semaphore wait:\n",
stderr);
sync_array_cell_print(stderr, cell);
noticed = TRUE;
}
if (cell->wait_object != NULL && cell->waiting
&& difftime(time(NULL), cell->reservation_time)
> fatal_timeout) {
if (diff > fatal_timeout) {
fatal = TRUE;
}
if (diff > longest_diff) {
longest_diff = diff;
*sema = wait_object;
*waiter = cell->thread;
}
}
if (noticed) {

View File

@ -39,6 +39,7 @@ Created 9/11/1995 Heikki Tuuri
#include "mem0mem.h"
#include "srv0srv.h"
#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
#include "ha_prototypes.h"
/*
IMPLEMENTATION OF THE RW_LOCK
@ -407,7 +408,8 @@ lock_loop:
" cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()),
(void*) lock,
lock->cfile_name, (ulong) lock->cline, (ulong) i);
innobase_basename(lock->cfile_name),
(ulong) lock->cline, (ulong) i);
}
/* We try once again to obtain the lock */
@ -442,7 +444,8 @@ lock_loop:
"Thread %lu OS wait rw-s-lock at %p"
" cfile %s cline %lu\n",
os_thread_pf(os_thread_get_curr_id()),
(void*) lock, lock->cfile_name,
(void*) lock,
innobase_basename(lock->cfile_name),
(ulong) lock->cline);
}
@ -664,7 +667,8 @@ lock_loop:
"Thread %lu spin wait rw-x-lock at %p"
" cfile %s cline %lu rnds %lu\n",
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
lock->cfile_name, (ulong) lock->cline, (ulong) i);
innobase_basename(lock->cfile_name),
(ulong) lock->cline, (ulong) i);
}
sync_array_reserve_cell(sync_primary_wait_array,
@ -687,7 +691,8 @@ lock_loop:
"Thread %lu OS wait for rw-x-lock at %p"
" cfile %s cline %lu\n",
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
lock->cfile_name, (ulong) lock->cline);
innobase_basename(lock->cfile_name),
(ulong) lock->cline);
}
/* these stats may not be accurate */

View File

@ -43,6 +43,7 @@ Created 9/5/1995 Heikki Tuuri
#ifdef UNIV_SYNC_DEBUG
# include "srv0start.h" /* srv_is_being_started */
#endif /* UNIV_SYNC_DEBUG */
#include "ha_prototypes.h"
/*
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
@ -543,7 +544,8 @@ spin_loop:
"Thread %lu spin wait mutex at %p"
" cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
innobase_basename(mutex->cfile_name),
(ulong) mutex->cline, (ulong) i);
#endif
mutex_spin_round_count += i;
@ -620,7 +622,8 @@ spin_loop:
fprintf(stderr,
"Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
innobase_basename(mutex->cfile_name),
(ulong) mutex->cline, (ulong) i);
#endif
mutex_os_wait_count++;
@ -869,7 +872,8 @@ sync_print_warning(
if (mutex->magic_n == MUTEX_MAGIC_N) {
fprintf(stderr,
"Mutex created at %s %lu\n",
mutex->cfile_name, (ulong) mutex->cline);
innobase_basename(mutex->cfile_name),
(ulong) mutex->cline);
if (mutex_get_lock_word(mutex) != 0) {
ulint line;

View File

@ -1,307 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. 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
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file thr/thr0loc.c
The thread local storage
Created 10/5/1995 Heikki Tuuri
*******************************************************/
#include "thr0loc.h"
#ifdef UNIV_NONINL
#include "thr0loc.ic"
#endif
#include "sync0sync.h"
#include "hash0hash.h"
#include "mem0mem.h"
#include "srv0srv.h"
/*
IMPLEMENTATION OF THREAD LOCAL STORAGE
======================================
The threads sometimes need private data which depends on the thread id.
This is implemented as a hash table, where the hash value is calculated
from the thread id, to prepare for a large number of threads. The hash table
is protected by a mutex. If you need modify the program and put new data to
the thread local storage, just add it to struct thr_local_struct in the
header file. */
/** Mutex protecting thr_local_hash */
static mutex_t thr_local_mutex;
/** The hash table. The module is not yet initialized when it is NULL. */
static hash_table_t* thr_local_hash = NULL;
/** Thread local data */
typedef struct thr_local_struct thr_local_t;
#ifdef UNIV_PFS_MUTEX
/* Key to register the mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/** @brief Thread local data.
The private data for each thread should be put to
the structure below and the accessor functions written
for the field. */
struct thr_local_struct{
os_thread_id_t id; /*!< id of the thread which owns this struct */
os_thread_t handle; /*!< operating system handle to the thread */
ulint slot_no;/*!< the index of the slot in the thread table
for this thread */
ibool in_ibuf;/*!< TRUE if the thread is doing an ibuf
operation */
hash_node_t hash; /*!< hash chain node */
ulint magic_n;/*!< magic number (THR_LOCAL_MAGIC_N) */
};
/** The value of thr_local_struct::magic_n */
#define THR_LOCAL_MAGIC_N 1231234
#ifdef UNIV_DEBUG
/*******************************************************************//**
Validates thread local data.
@return TRUE if valid */
static
ibool
thr_local_validate(
/*===============*/
const thr_local_t* local) /*!< in: data to validate */
{
ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
ut_ad(local->slot_no == ULINT_UNDEFINED
|| local->slot_no < OS_THREAD_MAX_N);
ut_ad(local->in_ibuf == FALSE || local->in_ibuf == TRUE);
return(TRUE);
}
#endif /* UNIV_DEBUG */
/*******************************************************************//**
Returns the local storage struct for a thread.
@return local storage */
static
thr_local_t*
thr_local_get(
/*==========*/
os_thread_id_t id) /*!< in: thread id of the thread */
{
thr_local_t* local;
try_again:
ut_ad(thr_local_hash);
ut_ad(mutex_own(&thr_local_mutex));
/* Look for the local struct in the hash table */
local = NULL;
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, ut_ad(thr_local_validate(local)),
os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
thr_local_create();
mutex_enter(&thr_local_mutex);
goto try_again;
}
ut_ad(thr_local_validate(local));
return(local);
}
/*******************************************************************//**
Gets the slot number in the thread table of a thread.
@return slot number */
UNIV_INTERN
ulint
thr_local_get_slot_no(
/*==================*/
os_thread_id_t id) /*!< in: thread id of the thread */
{
ulint slot_no;
thr_local_t* local;
mutex_enter(&thr_local_mutex);
local = thr_local_get(id);
slot_no = local->slot_no;
mutex_exit(&thr_local_mutex);
return(slot_no);
}
/*******************************************************************//**
Sets the slot number in the thread table of a thread. */
UNIV_INTERN
void
thr_local_set_slot_no(
/*==================*/
os_thread_id_t id, /*!< in: thread id of the thread */
ulint slot_no)/*!< in: slot number */
{
thr_local_t* local;
mutex_enter(&thr_local_mutex);
local = thr_local_get(id);
local->slot_no = slot_no;
mutex_exit(&thr_local_mutex);
}
/*******************************************************************//**
Returns pointer to the 'in_ibuf' field within the current thread local
storage.
@return pointer to the in_ibuf field */
UNIV_INTERN
ibool*
thr_local_get_in_ibuf_field(void)
/*=============================*/
{
thr_local_t* local;
mutex_enter(&thr_local_mutex);
local = thr_local_get(os_thread_get_curr_id());
mutex_exit(&thr_local_mutex);
return(&(local->in_ibuf));
}
/*******************************************************************//**
Creates a local storage struct for the calling new thread. */
UNIV_INTERN
void
thr_local_create(void)
/*==================*/
{
thr_local_t* local;
if (thr_local_hash == NULL) {
thr_local_init();
}
local = mem_alloc(sizeof(thr_local_t));
local->id = os_thread_get_curr_id();
local->handle = os_thread_get_curr();
local->magic_n = THR_LOCAL_MAGIC_N;
local->slot_no = ULINT_UNDEFINED;
local->in_ibuf = FALSE;
mutex_enter(&thr_local_mutex);
HASH_INSERT(thr_local_t, hash, thr_local_hash,
os_thread_pf(os_thread_get_curr_id()),
local);
mutex_exit(&thr_local_mutex);
}
/*******************************************************************//**
Frees the local storage struct for the specified thread. */
UNIV_INTERN
void
thr_local_free(
/*===========*/
os_thread_id_t id) /*!< in: thread id */
{
thr_local_t* local;
mutex_enter(&thr_local_mutex);
/* Look for the local struct in the hash table */
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, ut_ad(thr_local_validate(local)),
os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
return;
}
HASH_DELETE(thr_local_t, hash, thr_local_hash,
os_thread_pf(id), local);
mutex_exit(&thr_local_mutex);
ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
ut_ad(thr_local_validate(local));
mem_free(local);
}
/****************************************************************//**
Initializes the thread local storage module. */
UNIV_INTERN
void
thr_local_init(void)
/*================*/
{
ut_a(thr_local_hash == NULL);
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
mutex_create(thr_local_mutex_key,
&thr_local_mutex, SYNC_THR_LOCAL);
}
/********************************************************************
Close the thread local storage module. */
UNIV_INTERN
void
thr_local_close(void)
/*=================*/
{
ulint i;
ut_a(thr_local_hash != NULL);
/* Free the hash elements. We don't remove them from the table
because we are going to destroy the table anyway. */
for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
thr_local_t* local;
local = HASH_GET_FIRST(thr_local_hash, i);
while (local) {
thr_local_t* prev_local = local;
local = HASH_GET_NEXT(hash, prev_local);
ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
ut_ad(thr_local_validate(prev_local));
mem_free(prev_local);
}
}
hash_table_free(thr_local_hash);
thr_local_hash = NULL;
}

View File

@ -518,7 +518,7 @@ fill_trx_row(
query[stmt_len] = '\0';
row->trx_query = ha_storage_put_memlim(
cache->storage, stmt, stmt_len + 1,
cache->storage, query, stmt_len + 1,
MAX_ALLOWED_FOR_STORAGE(cache));
row->trx_query_cs = innobase_get_charset(trx->mysql_thd);

View File

@ -38,7 +38,6 @@ Created 3/26/1996 Heikki Tuuri
#include "usr0sess.h"
#include "read0read.h"
#include "srv0srv.h"
#include "thr0loc.h"
#include "btr0sea.h"
#include "os0proc.h"
#include "trx0xa.h"

View File

@ -25,6 +25,7 @@ Created 1/30/1994 Heikki Tuuri
#include "univ.i"
#include "ut0dbg.h"
#include "ha_prototypes.h"
#if defined(__GNUC__) && (__GNUC__ > 2)
#else
@ -55,12 +56,13 @@ ut_dbg_assertion_failed(
ut_print_timestamp(stderr);
#ifdef UNIV_HOTBACKUP
fprintf(stderr, " InnoDB: Assertion failure in file %s line %lu\n",
file, line);
innobase_basename(file), line);
#else /* UNIV_HOTBACKUP */
fprintf(stderr,
" InnoDB: Assertion failure in thread %lu"
" in file %s line %lu\n",
os_thread_pf(os_thread_get_curr_id()), file, line);
os_thread_pf(os_thread_get_curr_id()),
innobase_basename(file), line);
#endif /* UNIV_HOTBACKUP */
if (expr) {
fprintf(stderr,
@ -93,7 +95,8 @@ ut_dbg_stop_thread(
{
#ifndef UNIV_HOTBACKUP
fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n",
os_thread_pf(os_thread_get_curr_id()), file, line);
os_thread_pf(os_thread_get_curr_id()),
innobase_basename(file), line);
os_thread_sleep(1000000000);
#endif /* !UNIV_HOTBACKUP */
}